jbx*_*jbx 8 prolog crossword prolog-dif
好的我是Prolog的新手,请原谅,如果这是微不足道的,但我似乎无法找到一个合适的优雅答案.我试图在learnprolognow.org,练习2.4(填字游戏)上进行练习.
练习提供了以下事实:
word(astante, a,s,t,a,n,t,e).
word(astoria, a,s,t,o,r,i,a).
word(baratto, b,a,r,a,t,t,o).
word(cobalto, c,o,b,a,l,t,o).
word(pistola, p,i,s,t,o,l,a).
word(statale, s,t,a,t,a,l,e).
Run Code Online (Sandbox Code Playgroud)
我想出解决每个单词的填字游戏位置的解决方案是这样的:
crossword(V1, V2, V3, H1, H2, H3) :-
word(V1, V1a, V1bH1b, V1c, V1dH2b, V1e, V1fH3b, V1g),
word(V2, V2a, V2bH1d, V2c, V2dH2d, V2e, V2fH3d, V2g),
word(V3, V3a, V3bH1f, V3c, V3dH2f, V3e, V3fH3f, V3g),
word(H1, H1a, V1bH1b, H1c, V2bH1d, H1e, V3bH1f, H1g),
word(H2, H2a, V1dH2b, H2c, V2dH2d, H2e, V3dH2f, H2g),
word(H3, H3a, V1fH3b, H3c, V2fH3d, H3e, V3fH3f, H3g).
Run Code Online (Sandbox Code Playgroud)
随着V1a对V1g等为每个单词的字符,并且V1bH1b以V3fH3f成为在纵横字之间公共的字符.
该解决方案似乎有效,但结果是产生重复值,第一个结果是:
?- crossword(V1, V2, V3, H1, H2, H3).
V1 = astante,
V2 = baratto,
V3 = statale,
H1 = astante,
H2 = baratto,
H3 = statale .
Run Code Online (Sandbox Code Playgroud)
我怎么能强迫Prolog有V1 \= V2 \= V3 \= H1 \= H2 \= H3?如果我逐个单独进行,我将需要120个排列,所以必须有一个更快的方法,这是一个初学者练习所以我必须缺少一些东西.
我发现了这个类似的问题,但提供的答案看起来很复杂,我希望有一个更简单的方法.我在Ubuntu上使用swi-prolog,以防万一.
谢谢.
fal*_*lse 10
使用alldif/1定义如下:
alldif([]).
alldif([E|Es]) :-
maplist(dif(E), Es),
alldif(Es).
Run Code Online (Sandbox Code Playgroud)
哪个甚至可以用于最常见的查询:
?- alldif(Es).
Es = [] ;
Es = [_G1924] ;
Es = [_G2061, _G2064],
dif(_G2061, _G2064) ;
Es = [_G2163, _G2166, _G2169],
dif(_G2163, _G2169),
dif(_G2163, _G2166),
dif(_G2166, _G2169) ;
Es = [_G2309, _G2312, _G2315, _G2318],
dif(_G2309, _G2318),
dif(_G2309, _G2315),
dif(_G2309, _G2312),
dif(_G2315, _G2318),
dif(_G2312, _G2315),
dif(_G2312, _G2318) ...
Run Code Online (Sandbox Code Playgroud)
maplist(dif(E),Es)通过查看答案可以最好地理解目标的含义:
?- maplist(dif(E),Es).
Es = [] ;
Es = [_G1987],
dif(E, _G1987) ;
Es = [_G2040, _G2043],
dif(E, _G2043),
dif(E, _G2040) ;
Es = [_G2093, _G2096, _G2099],
dif(E, _G2099),
dif(E, _G2096),
dif(E, _G2093) ;
Es = [_G2146, _G2149, _G2152, _G2155],
dif(E, _G2155),
dif(E, _G2152),
dif(E, _G2149),
dif(E, _G2146) ...
Run Code Online (Sandbox Code Playgroud)
也就是说,Es是一个完全不同的元素列表E.目标地图列表(dif(E),[A,B,C])将第一个元素(在本例中dif(E))与列表的每个元素组合在一起.因此dif(E,A), dif(E,B), dif(E,C).