【问题标题】:Crossword solver in PROLOGPROLOG 中的填字游戏求解器
【发布时间】:2012-03-13 22:59:03
【问题描述】:

天堂岛的克里奥尔语有14个字:“放弃”、“鲍鱼”、“字谜”、“船”、“船夫”、“孩子”、“连接”、“优雅”、“增强”、“岛屿” ”、“男人”、“沙子”、“太阳”和“女人”。

天堂时代有 发表了这个填字游戏:

填字游戏包含 14 个单词中的一些单词,但没有其他单词。

写 一个从

开始的Prolog程序
word(X) :-
member(X,
[
[a,b,a,n,d,o,n], [a,b,a,l,o,n,e], [a,n,a,g,r,a,m],
[b,o,a,t], [b,o,a,t,m,a,n], [c,h,i,l,d],
[c,o,n,n,e,c,t], [e,l,e,g,a,n,t], [e,n,h,a,n,c,e],
[i,s,l,a,n,d], [m, a, n], [s,a,n,d],
[s,u,n], [w, o, m, a, n]
]).

solution(H1,H2,H3,V1,V2,V3) :-

并以这样的方式定义谓词solution

solution(H1,H2,H3,V1,V2,V3)

当且仅当 H1H2H3V1V2V3 是天堂的有效词时为真 当写入上面给出的网格时形成有效填字游戏的岛屿。 (例如H1的第二个字母应该和第二个字母重合 V1.)

使用查询

?- solution(H1,H2,H3,V1,V2,V3).

解决填字游戏。找到填字游戏的所有解决方案。

提示:您可能希望从较小的填字游戏和较不丰富的游戏开始 词典。

【问题讨论】:

  • 天啊,我现在正试图解决同样的问题!我简直不敢相信!

标签: prolog crossword


【解决方案1】:

看图,字都是用字母写的,图里什么都有,用Prolog行翻译(我的方案是12行,一个字2行)。

[编辑] 每个人都有自己的解决方案,这是我的:

solution(H1,H2,H3,V1,V2,V3) :-
    H1 = [_,A2,_,A4,_,A6,_],
    H2 = [_,B2,_,B4,_,B6,_],
    H3 = [_,C2,_,C4,_,C6,_],
    V1 = [_,A2,_,B2,_,C2,_],
    V2 = [_,A4,_,B4,_,C4,_],
    V3 = [_,A6,_,B6,_,C6,_],
    maplist(word, [H1,H2,H3,V1,V2,V3]).

PS 我原来 写字(H1), 单词(H2) ...

【讨论】:

  • 我已经有 15 年没有在 Prolog 中编码了,甚至不记得它长什么样了,但是出于好奇,我很想看看你的解决方案!
  • 我的解决方案只是针对这个填字游戏,不是通用的解决方案。我只是翻译我看到的。
  • 这是我今天写的同一个例子......但这并不是@Jhonny Tim 所问的。
【解决方案2】:

唯一的域选择 select/2 可以解决问题:

select([A|As],S):- select(A,S,S1),select(As,S1).
select([],_). 
words(X) :- X = [
    [a,b,a,n,d,o,n], [a,b,a,l,o,n,e], [a,n,a,g,r,a,m],
    [b,o,a,t],       [b,o,a,t,m,a,n], [c,h,i,l,d],
    [c,o,n,n,e,c,t], [e,l,e,g,a,n,t], [e,n,h,a,n,c,e],
    [i,s,l,a,n,d],   [m, a, n],       [s,a,n,d],
    [s,u,n],         [w, o, m, a, n]
    ].
solve(Crossword):- words(Words), 
    Crossword = [ [_,A2,_,A4,_,A6,_],
                  [_,B2,_,B4,_,B6,_],
                  [_,C2,_,C4,_,C6,_],
                  [_,A2,_,B2,_,C2,_],
                  [_,A4,_,B4,_,C4,_],
                  [_,A6,_,B6,_,C6,_] ],
    select(Crossword, Words).
solve:- solve(Crossword),
        maplist(writeln, Crossword), writeln(';'), fail 
     ;  writeln('No more solutions!').

测试:

7 ?- solve.
[a, b, a, n, d, o, n]
[e, l, e, g, a, n, t]
[e, n, h, a, n, c, e]
[a, b, a, l, o, n, e]
[a, n, a, g, r, a, m]
[c, o, n, n, e, c, t]
;
[a, b, a, l, o, n, e]
[a, n, a, g, r, a, m]
[c, o, n, n, e, c, t]
[a, b, a, n, d, o, n]
[e, l, e, g, a, n, t]
[e, n, h, a, n, c, e]
;
No more solutions!

此解决方案仅允许在拼图中使用唯一单词(不允许重复)。这可能是也可能不是您想要的。

【讨论】:

    【解决方案3】:

    本身不是 Prolog 程序,但可以在 Hakan Kjellerstrand's excellent blog on CP 中找到使用约束逻辑编程的解决方案。它在 ECLiPSe 中,但很容易适应具有有限域求解器的其他 Prolog 系统。使用 CLP 而不是纯 Prolog 将使搜索速度更快。

    【讨论】:

      【解决方案4】:
      solution(H1, H2, H3, V1, V2, V3) :-
          crosswordize([H1,H2,H3], [V1,V2,V3]),
          maplist(word, [H1,H2,H3,V1,V2,V3]).
      
      crosswordize([], [[_],[_],[_]]).
      crosswordize([[_, X1, _, X2, _, X3, _]|Lines],
                   [[_, X1|R1], [_, X2|R2], [_, X3|R3]]) :-
          crosswordize(Lines, [R1,R2,R3]).
      

      算法不难得到:

      • 我们通过 crosswordize/2 谓词调用构建网格
      • 我们告诉 prolog 每个列表都是一个单词

      crosswordize/2 谓词在构建行时一次通过两个单元格的列。如果你没有得到它,你仍然可以像 Will 那样“硬编码”它,它也可以工作!

      【讨论】:

      • 我们可以在填字游戏中多次使用同一个词吗?我认为,通常不会。
      • 好吧,定义说填字游戏是有效的,当且仅当每个列表都是一个有效的天堂事物词。因为这是一个当且仅当我确实认为成员而不是 select 调用是有效的!
      • btw with member/2 我没有任何重复相同单词的解决方案,所以一种或另一种方式不会改变这个问题中的很多事情:p
      • 这是一个拼图创造者;如果词典允许,您的版本很乐意创建包含重复单词的填字游戏。
      • 当然,正如我所说,在参考给出的定义时它是有效的......无论如何,为了不允许重复进行编辑是微不足道的,这只是你如何阅读练习的问题...... .
      【解决方案5】:

      这里的理论是检查垂直和水平单词中与自己对应的字母。这可以通过在word 规则中使用占位符来实现。查看这个要点https://gist.github.com/ITPol/f8f5418d4f95015b3586 它给出了一个声称没有重复的答案。但是,来自 SQL,我认为正确地抑制重复将需要一个类似于V1 @< V2 的解决方案;因为仅仅使用“不等于”是不够的。请原谅多个“[k]nots”;它实际上并没有那么复杂。双关语意(:

      【讨论】:

      • 如果我们从可用项目池中删除所选项目,则自动不可能重复。正如我在回答中所展示的那样。 (这就是select/3 所做的)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多