强制 Prolog 选择变量的唯一值 [英] Force Prolog to choose unique values of variables
问题描述
好的,我是 Prolog 的新手,所以如果这是微不足道的事情,请原谅,但我似乎找不到合适的优雅答案.我正在尝试在 learnprolognow.org,练习 2.4(填字游戏).
OK I am new to Prolog, so excuse me if this is something trivial, but I can't seem to find a proper elegant answer to this. I am trying to work out the exercise here on learnprolognow.org, exercise 2.4 (the crossword).
该练习提供了以下事实:
The exercise provides these facts:
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).
而我想出的解决每个单词的填字游戏位置的解决方案是这样的:
And the solution I came up with to solve the crossword placement of each word is this:
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).
V1a
到V1g
等是每个单词的字符,V1bH1b
到V3fH3f
是填字游戏中单词之间的共同字符.
With V1a
to V1g
etc. being the characters of each word, and the V1bH1b
to V3fH3f
being the characters in common between words in the crossword.
该解决方案似乎有效,但结果是产生重复值,第一个结果是:
The solution seems to work, however the result is producing duplicate values, with the first result being:
?- crossword(V1, V2, V3, H1, H2, H3).
V1 = astante,
V2 = baratto,
V3 = statale,
H1 = astante,
H2 = baratto,
H3 = statale .
如何强制 Prolog 具有 V1 = V2 = V3 = H1 = H2 = H3
?如果我一个一个地做,我需要 120 个排列,所以必须有一个更快的方法,而且这是一个初学者练习,所以我一定会遗漏一些东西.
How can I force Prolog to have V1 = V2 = V3 = H1 = H2 = H3
?
If I do them individually one by one I will need 120 permutations, so there must be a quicker way, and this is a beginners exercise so I must be missing something.
我发现 这个类似的问题,但提供的答案似乎很复杂,我希望有一个更简单的方法.我在 Ubuntu 上使用 swi-prolog,以防万一.
I found this similar question, but the answers provided seem so complicated, I hope there is a simpler way. I am using swi-prolog on Ubuntu, just in case it matters.
谢谢.
推荐答案
使用 alldif/1
定义如下:
alldif([]).
alldif([E|Es]) :-
maplist(dif(E), Es),
alldif(Es).
这甚至可以用于最一般的查询:
Which can be used even for the most general query:
?- 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) ...
目标maplist(dif(E),Es)
的含义最好看答案就明白了:
The meaning of the goal maplist(dif(E),Es)
is best understood by looking at the answers:
?- 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) ...
也就是说,Es
是一个与E
完全不同的元素的列表.目标 maplist(dif(E),[A,B,C]) 将第一个元素(在本例中为 dif(E)
)与列表的每个元素组合在一起.因此 dif(E,A), dif(E,B), dif(E,C)
.
That is, Es
is a list of elements that are all different to E
. The goal maplist(dif(E),[A,B,C]) combines the first element (in this case dif(E)
) with each element of the list. Thus dif(E,A), dif(E,B), dif(E,C)
.
这篇关于强制 Prolog 选择变量的唯一值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!