8

OK、私は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).

そして、各単語のクロスワード配置を解決するために私が思いついた解決策は次のとおりです。

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

V1atoV1gなどは各単語の文字であり、toV1bH1bV3fH3fクロスワードの単語間で共通する文字です。

解決策は機能しているように見えますが、結果は重複した値を生成しています。最初の結果は次のとおりです。

?- 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ですか? 1つずつ個別に行うと、120個の順列が必要になるため、より迅速な方法が必要であり、これは初心者の演習であるため、何かが欠けているに違いありません.

この同様の質問を見つけましたが、提供された回答は非常に複雑に思えます。もっと簡単な方法があることを願っています。念のため、Ubuntuでswi-prologを使用しています。

ありがとう。

4

3 に答える 3

10

alldif/1次のように定義して使用します。

alldif([]).
alldif([E|Es]) :-
   maplist(dif(E), Es),
   alldif(Es).

最も一般的なクエリにも使用できます。

?- 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)、答えを見ることで最もよく理解できます。

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

于 2013-01-30T14:40:40.743 に答える
0

length(List, N): N はリストの長さです
sort(List, SortedList): SortedList はリストのソート済みバージョンです (重複する要素は削除されます)

一方、使用可能な単語のリストを用意し、使用された単語を削除する方が高速な場合があります。最後にチェックを行う必要がないだけでなく、無意味なインスタンス化を回避できます (A1 = foo, A2 = foo最後に拒否されるのではなく、すぐに停止します)。つまり、枝の剪定。

于 2013-01-29T19:40:58.970 に答える
0

コメントで@falseがあなたに言ったこと。または、ドメイン選択を使用したい:

selectM([A|As],S,Z):- select(A,S,S1),selectM(As,S1,Z).
selectM([],Z,Z).

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

crossword(Words) :- findall(W, word(_,W), WS),
   Words = [[ _,A,_,B,_,C,_], 
            [ _,D,_,E,_,F,_], 
            [ _,G,_,H,_,I,_],
            [ _,A,_,D,_,G,_],
            [ _,B,_,E,_,H,_],
            [ _,C,_,F,_,I,_]],
   selectM( Words, WS, _).
于 2013-01-30T02:33:29.837 に答える