Prolog - 生成填字游戏

时间:2015-09-19 20:31:51

标签: prolog crossword

我正面对这个困难的练习,我已经看过其他关于填字游戏的练习(即最后一次练习" p-99:九十九个prolog节目"或者#&# 34;人工智能的Prolog编程" Bratko),但这是不同的,也更难,因为在这里我们没有任何模板可以填写。

文字

编写Prolog程序以生成填字游戏。假设你有一个这样的事实字典:w(Word,Lentgth)。写一个谓词填字游戏(C,W,H)来实例化C,到字典的字符列表(填字游戏行)的所有可能列表(填字游戏),其中黑色单元格用星号表示。
例如:

w(online,6).
w(prolog,6).
w(perl,5).
w(emacs,5).
w(linux,5).
w(gnu,3).
w(mac,3).
w(nfs,3).
w(sql,3).
w(web,3).
w(xml,3).
w(a,1).
w(b,1).
w(e,1).
w(i,1).
w(l,1).
w(m,1).
w(n,1).
w(o,1).
w(q,1).
w(r,1).
w(s,1).
w(t,1).
w(u,1).
w(w,1).

?- crossword(C,9,6).
C=[[p,r,o,l,o,g,*,*,e],
   [e,*,n,*,*,n,*,*,m],
   [r,*,l,i,n,u,x,*,a],
   [l,*,i,*,f,*,m,a,c],
   [*,*,n,*,s,q,l,*,s],
   [*,w,e,b,*,*,*,*,*]]

给出提示

1)你可以在字典中添加这些" black"词:

black(*,1).
black(**,2).
black(***,3).
black(****,4).
black(*****,5).

2)每一行都是" white"单词(普通单词)和"黑色"单词交错,这个序列可以用两者开始/结束。

3)我建议你用2个不同的条款管理前一点的2种可能性。

4)填字游戏是一个字符矩阵,因此它的转置仍然是一个填字游戏。

5)转置填字游戏已经实例化,所以你只需要用字典检查它的可行性。

这就是我的想法:为每个列表(行)创建一个H(填字游戏,行的高度)列表(填字游戏的行)列表我尝试从字典中插入单词后跟&# 34;黑色"单词,然后再一个单词,直到行满,或者从"黑色"开始。当填字游戏已满时,我将其转置并检查转置是否也是一个有效的填字游戏:包含的每个单词都是字典中的有效单词。 我知道这是一种非常低效的方法,我尝试使用一个小字典生成填字游戏2x2,它正确地生成第一个第二,但似乎需要多年才能获得第三个。我不知道我的代码是否有问题,可能会卡在某处。您是否知道一种更有效的方法来解决此问题,或者您在我的代码中看到了一些需要改进的地方?

crossword(C,W,H):- create(C,H),
                   insert_words(C,W,[],_),
                   clpfd:transpose(C,Traspose),
                   isok(Traspose).

insert_words([],_,U,U).
insert_words([H|T],W,Uacc,U):-
                             (add_white(H,[],C,[],Uacc,Udef);
                              add_black(H,[],C,[],Uacc,Udef)),
                              insert_words(T,C,Udef,U).

create(Puzzle,H) :- length(Puzzle,H).


add_white(P,P,0,_,U,U).
add_white(P,Row,R,Used,Uacc,Udef):- 
                                R\=0,
                                w(Word,L),
                                \+member(Word,Used),
                                \+member(Word,Uacc),
                                R2 is R-L,
                                R2 >= 0,
                                atom_chars(Word,Word2),
                                append(Row,Word2,Row2),
                                append(Used,[Word],Used2),
                                append(Uacc,[Word],Uacc2),
                                add_black(P,Row2,R2,Used2,Uacc2,Udef).

add_white(P,Row,R,Used,Uacc,Udef):-
                                   R\=0,
                                   w(Word,L),
                                   \+member(Word,Used),
                                   R2 is R-L,
                                   R2 < 0,
                                   append(Used,[Word],Used2),
                                   add_white(P,Row,R,Used2,Uacc,Udef).

add_white(P,Row,R,Used,Uacc,Udef):-
                                   R\=0,
                                   w(Word,_),
                                   member(Word,Used),
                                   add_white(P,Row,R,Used,Uacc,Udef).


add_black(P,P,0,_,U,U).
add_black(P,Row,R,Used,Uacc,Udef):-
                                   R\=0,
                                   black(Black,L),
                                   R2 is R-L,
                                   R2 >= 0,
                                   atom_chars(Black,Black2),
                                   append(Row,Black2,Row2),
                                   add_white(P,Row2,R2,Used,Uacc,Udef).

add_black(P,Row,R,Used,Uacc,Udef):-
                                   R\=0,
                                   black(_,L),
                                   R2 is R-L,
                                   R2 < 0,
                                   add_black(P,Row,R,Used,Uacc,Udef).

isok([]).
isok([H|T]):-split(H,*,R),
        check(R),
        isok(T).

split(L,C,R):-split2(L,C,X),trim(X,R).

split2(In, Sep, [Left|Rest]) :-
append(Left, [Sep|Right], In), !, split2(Right, Sep, Rest).
split2(In, _Sep, [In]).

trim([],[]).
trim([H|T],[H|T2]):-H\=[],trim(T,T2).
trim([H|T],Y):-H=[],trim(T,Y).

check([]).
check([H|T]):-
               atom_chars(X,H),
               w(X,_),
               check(T).

我使用这个小字典而不是原始字典来测试我的程序并生成简单的2x2填字游戏,但正如我之前所说的那样,在正确找到2个解决方案后似乎卡住了。

w(ci,2).
w(ca,2).
w(i,1).
w(a,1).
black(*,1).

0 个答案:

没有答案