2013-06-18 50 views
0

我跟隨Learn Prolog Now!並正在查看Exercise 2.4如何創建將每個值作爲唯一返回的規則

溶液我found here似乎解決,但不完全:

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, _, V1H1, _, V1H2, _, V1H3, _), 
    word(V2, _, V2H1, _, V2H2, _, V2H3, _), 
    word(V3, _, V3H1, _, V3H2, _, V3H3, _), 
    word(H1, _, V1H1, _, V2H1, _, V3H1, _), 
    word(H2, _, V1H2, _, V2H2, _, V3H2, _), 
    word(H3, _, V1H3, _, V2H3, _, V3H3, _). 

這將產生以下結果:

H1 = astoria 
H2 = baratto 
H3 = statale 
V1 = astante 
V2 = cobalto 
V3 = pistola ? ; 

H1 = astante 
H2 = cobalto 
H3 = pistola 
V1 = astoria 
V2 = baratto 
V3 = statale ? ; 

H1 = astoria 
H2 = cobalto 
H3 = pistola 
V1 = astoria 
V2 = cobalto 
V3 = pistola ? ; 

H1 = baratto 
H2 = baratto 
H3 = statale 
V1 = baratto 
V2 = baratto 
V3 = statale ? ; 

H1 = cobalto 
H2 = baratto 
H3 = statale 
V1 = cobalto 
V2 = baratto 
V3 = statale ? ; 

H1 = astante 
H2 = baratto 
H3 = statale 
V1 = astante 
V2 = baratto 
V3 = statale ? ; 

在這些中,只有2個是實用:

H1 = astoria 
H2 = baratto 
H3 = statale 
V1 = astante 
V2 = cobalto 
V3 = pistola ? ; 

H1 = astante 
H2 = cobalto 
H3 = pistola 
V1 = astoria 
V2 = baratto 
V3 = statale ? ; 

因爲其他3種解決方案都包含重複項,所以它們不適用於pr oblem。

如何添加到填字遊戲規則,讓它只返回V1,V2,V3,H1,H2,H3都是唯一的結果?

回答

1

你可以使用這樣的程序,以確保值都不同:

all_dif([]). 
all_dif([A|Tail]):- 
    all_dif(Tail, A), 
    all_dif(Tail). 

all_dif([], _). 
all_dif([B|Tail], A):- 
    dif(A,B), 
    all_dif(Tail, A). 

all_dif([V1,V2,V3,H1,H2,H3])

1

常用的技術把它利用select/3,以獲得回溯獨特另類元素:

crossword(V1,V2,V3,H1,H2,H3) :- 
    selects(
     [[V1, _, V1H1, _, V1H2, _, V1H3, _], 
     [V2, _, V2H1, _, V2H2, _, V2H3, _], 
     [V3, _, V3H1, _, V3H2, _, V3H3, _], 
     [H1, _, V1H1, _, V2H1, _, V3H1, _], 
     [H2, _, V1H2, _, V2H2, _, V3H2, _], 
     [H3, _, V1H3, _, V2H3, _, V3H3, _] 
     ], 
     [[a,s,t,a,n,t,e], 
     [a,s,t,o,r,i,a], 
     [b,a,r,a,t,t,o], 
     [c,o,b,a,l,t,o], 
     [p,i,s,t,o,l,a], 
     [s,t,a,t,a,l,e] 
     ]). 

selects([], []). 
selects([[W|Cs]|Ws], L) :- 
    select(Cs, L, R), 
    selects(Ws, R), 
    atom_chars(W, Cs). 

這顯然是您已經找到的非常簡單的解決方案的替代方法。

選擇/ 3還可以用來檢查是否有在列表中沒有重複:

crossword(V1,V2,V3,H1,H2,H3) :- 
    word(V1, _, V1H1, _, V1H2, _, V1H3, _), 
    word(V2, _, V2H1, _, V2H2, _, V2H3, _), 
    word(V3, _, V3H1, _, V3H2, _, V3H3, _), 
    word(H1, _, V1H1, _, V2H1, _, V3H1, _), 
    word(H2, _, V1H2, _, V2H2, _, V3H2, _), 
    word(H3, _, V1H3, _, V2H3, _, V3H3, _), 
    maplist(nodup([V1,V2,V3,H1,H2,H3]), [V1,V2,V3,H1,H2,H3]). 

nodup(L, E) :- select(E, L, R), \+ memberchk(E, R). 

最後,因爲排序/ 2刪除重複,最簡單的檢查可能是

crossword(V1,V2,V3,H1,H2,H3) :- 
    word(V1, _, V1H1, _, V1H2, _, V1H3, _), 
    word(V2, _, V2H1, _, V2H2, _, V2H3, _), 
    word(V3, _, V3H1, _, V3H2, _, V3H3, _), 
    word(H1, _, V1H1, _, V2H1, _, V3H1, _), 
    word(H2, _, V1H2, _, V2H2, _, V3H2, _), 
    word(H3, _, V1H3, _, V2H3, _, V3H3, _), 
    sort([V1,V2,V3,H1,H2,H3], [_,_,_,_,_,_]). 
+0

+ 1我喜歡'select/3'並始終使用它。 :) –

相關問題