Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
521 views
in Technique[技术] by (71.8m points)

crossword - Force Prolog to choose unique values of variables

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).

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 .

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.

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.

Thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Use alldif/1 defined like so:

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) ...

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) ...

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).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...