2015-06-21 96 views
3

對序言不熟悉。我有一個我無法解釋的小故障,但是如果我添加其他字典(X)事實,該程序似乎工作。該程序需要一個字符串列表,其中的字母已經被編碼併產生一個解碼列表。每個字母表示單詞列表中的不同字母。所以去([abccd,edfgh,ade,ifb,kdl],X)返回X = ['HELLO','WORLD','HOW','ARE','你']。問題是如果字典('HOW')事實出現在字典('YOU')事實之前,那麼程序返回X = ['HELLO','WORLD','HOW','ARE','HOW']。 。這裏是令人毛骨悚然的代碼:事實的序言更改順序產生不同的結果

/*word bank*/ 
dictionary('HELLO'). 
dictionary('WORLD'). 
dictionary('HOW'). 
dictionary('ARE'). 
dictionary('YOU'). 

/*This spits out a single list where 
the lengths of words in the dictionary 
are matched to each word in the encoded 
message, so [abccd,edfgh,ade,ifb,kdl] 
matches [HELLO,WORLD,HOW,ARE,HOW] or 
any combination*/ 
sameLength([X|XTail],[Y|YTail]) :- 
    dictionary(Y), 
    name(X,L1),name(Y,L2), 
    length(L1,Z),length(L2,Z), 
    sameLength(XTail,YTail). 
sameLength([],[]). 

/*Turns a list of lists into 
a single list*/ 
oneWord([X|XTail],Y) :- 
    name(X,L), 
    append(L,Z,Y), 
    oneWord(XTail,Z). 
oneWord([],[]). 

/*This replaces the letters that are in 
the dictionary, with the letters in the 
message. If at any point a letter has 
been replaced because it is UPPERCASE, 
and that letter is being replaced by 
something else then fail, other wise, 
the letter has to be lowercase*/ 
replaceLetters(List,[X|XTail],[Y|YTail],Result) :- 
    (X<91,X=Y);(X>96), 
    replaceP(X,Y,List,Result1), 
    replaceLetters(Result1,XTail,YTail,Result). 
replaceLetters(Result,[],[],Result). 

/*the call to action*/ 
go(X,Y) :- 
    sameLength(X,Y), 
    oneWord(X,A), 
    oneWord(Y,B), 
    replaceLetters(A,A,B,C), 
    B=C, 
    !. 

/*replace thanks to @repeat*/ 
replaceP(_, _, [], []). 
replaceP(O, R, [O|T], [R|T2]) :- replaceP(O, R, T, T2). 
replaceP(O, R, [H|T], [H|T2]) :- dif(H,O), replaceP(O, R, T, T2). 

我想補充一點,Prolog很酷。謝謝你的幫助。

+1

+1使用dif/2!但是名稱/ 2自30多年以來已被棄用和過時 - 如果您從20世紀70年代開始穿2英寸高原鞋,則只允許使用它。 – false

回答

1

m Ÿ解決方案讓我明白了,從這個問題出來

go(X,Y) :- 
    go(X,Y,[]). 

go([],[],_Dict). 
go([W|Ws],[T|Ts],Dict) :- 
    assoc_codes(W,T,Dict,DictUpd), 
    go(Ws,Ts,DictUpd). 

assoc_codes(W,T,Dict,DictUpd) :- 
    atom_codes(W, Cs), 
    dictionary(T), 
    atom_codes(T, Tcs), 
    upd_dict(Cs, Tcs, Dict, DictUpd). 

upd_dict([], [], DictUpd, DictUpd). % done, all went well 
upd_dict([C|Cs], [D|Ds], Dict, DictUpd) :- 
     memberchk(C-T, Dict) % if C already 'assigned', must match D 
    -> T = D, 
     upd_dict(Cs, Ds, Dict, DictUpd) 
    ; \+ (memberchk(X-D, Dict), X \= C), 
     upd_dict(Cs, Ds, [C-D|Dict], DictUpd). 

注意else分支:當C仍沒有被分配,同樣必須如果我們將其註釋掉爲D.是真實的(即

... 
; % \+ (memberchk(X-D, Dict), X \= C), 
... 

)我們有問題,你舉報

?- go([abccd,edfgh,ade,ifb,kdl],X). 
X = ['HELLO', 'WORLD', 'HOW', 'ARE', 'HOW'] ; 
X = ['HELLO', 'WORLD', 'HOW', 'ARE', 'YOU'] ; 
false. 

它的事實, 'L' 必須分配給 'C' 和 'G' 出來。 取消註釋測試後,我們有

?- go([abccd,edfgh,ade,ifb,kdl],X). 
false. 

?- go([abccd,edfch,ade,ifb,kdl],X). 
X = ['HELLO', 'WORLD', 'HOW', 'ARE', 'YOU'] ; 
false. 
+0

我很感激你花時間去解決這個問題。我不明白語法memberchk(C-T,Dict)。這是我不認識的C-T部分。 – lefunction

+0

它只是一對字符代碼,存儲在我能想到的最簡單的關聯數據結構中:對的列表 – CapelliC

+0

ok。我追溯了這一點,我看到你在做什麼。非常感謝! – lefunction

0

幾個百分點:

  1. 我認爲你有 ';'優先順序錯誤並需要另一組括號。
  2. 雙HOW實際上是一個有效的答案,因爲您沒有檢查例如'a'和'k'都映射到H(偶然中間的'O'符合兩個3字母的模式)。
  3. 有可能解決你的問題,通過瓦爾自然統一更「序言」的方式,即

Respresent [abccd,edfgh,ADE,售後不退,KDL]作爲類似瓦爾名單:

[[A,B,C,C,D],[E,D,F,G,H],[A,D,E],[I,F,B][K,D,L]] 

並將您的字典存儲爲信件列表 eg

dictionary(['H','E','L','L','O']). 
dictionary('['W','O','R','L','D']). 

那麼就使用Prolog的回溯,以匹配所有的話:

solve([],[]). 
solve([Word|Ps],[Word|Words]) :- dictionary(Word), solve(Ps,Words). 

並且用類似

:- solve([[A,B,C,C,D],[E,D,F,G,H],[A,D,E],[I,F,B],[K,D,L]], Answer). 

注意調用,這仍然具有相同的「錯誤」您的代碼 - 沒有檢查所有的瓦爾匹配不同的字母 - 你將不得不爲此編碼...

+0

嗨,謝謝!變換聽起來像是一個很好的解決方案,並且是我最初想到解決方案的方式,但我不知道如何去做。問題正是如何向變量表示一個潛在的無限列表,所以我會試試這個。真棒。 – lefunction