讓我們解決它在階段:
1,消除副作用並簡化程序
我開始與你的程序的下面直接的變化:
- 我消除執行I/O的所有目標,因爲這些只能得到在推理的方式,我們希望執行有關程序。
- 代替
X is C
其中C
是恆定,變量只在代碼的其餘部分使用一次,我簡單地使用恆定 C
直接。
因此,我們得到:現在
main :-
prologwhile(0, 0, 0, 0, ["Garbage data1", "More garbage data"]).
prologwhile(Num, A, B, C, Usedlist) :-
Num < 9 ,
F = [["time of day", 1], ["Season", 5], ["Yesterdays weather", 2], ["Month of last big storm", 2], ["Randomly generated riddle", 9], ["A captcha", 1], ['Current day', 6], ["Tomorrows date", 5]],
random_member(Rand, F),
nth0(1, Rand, Add),
nth0(0, Rand, Z),
( member(Z, Usedlist) ->
prologwhile(Num, A, B, C, Usedlist)
; append(Usedlist, Z, Usedlist3),
Num3 is Num + Add,
prologwhile(Num3, A, B, 1, Usedlist3)
).
,爲便於閱讀,我提出以下額外變化:
- 我分解出短語到自己的謂語
- 我使用對而不是列表代表
Phrase-Value
對
- 我使用模式匹配和一個更具有說服力的變量名稱。
總體而言,我們現在有:
main :-
prologwhile(0, 0, 0, 0, ["Garbage data1", "More garbage data"]).
prologwhile(Num, A, B, C, Usedlist) :-
Num < 9 ,
phrases(Ps),
random_member(Phrase-Value, Ps),
( member(Phrase, Usedlist) ->
prologwhile(Num, A, B, C, Usedlist)
; append(Usedlist, Phrase, Usedlist3),
Num3 is Num + Value,
prologwhile(Num3, A, B, 1, Usedlist3)
).
phrases(["time of day"-1,
"Season"-5,
"Yesterdays weather"-2,
"Month of last big storm"-2,
"Randomly generated riddle"-9,
"A captcha"-1,
'Current day'-6,
"Tomorrows date"-5]).
從今往後,我認爲phrases/1
在上面的代碼中定義的,並沒有隨身攜帶它的定義。
2.找到失敗的原因
現在實際推理有關程序啓動,因爲我們有:
?- main.
false.
爲了幫助您發現錯誤,我添加了以下定義該程序:
$(Goal) :-
portray_clause(Goal),
Goal.
我們可以利用這個謂詞如下的prologwhile/5
:
prologwhile(Num, A, B, C, Usedlist) :-
Num < 9 ,
phrases(Ps),
random_member(Phrase-Value, Ps),
( member(Phrase, Usedlist) ->
prologwhile(Num, A, B, C, Usedlist)
; $(append(Usedlist, Phrase, Usedlist3)),
Num3 is Num + Value,
prologwhile(Num3, A, B, 1, Usedlist3)
).
現在,我們得到:
?- main.
append(["Garbage data1", "More garbage data"], "A captcha", _).
append(["Garbage data1", "More garbage data"|"A captcha"], 'Current day', _).
false.
所以這裏的問題:
?- append(["Garbage data1", "More garbage data"|"A captcha"], 'Current day', _).
false
這個目標失敗和因此整個計劃失敗。
你明明意如下:
append(Usedlist, [Phrase], Usedlist3)
即要追加合併兩個名單,的內容不是一個列表和一些其他的。請注意,它往往是一個好主意,前置列表中的前元素,而不是追加他們獲得良好的性能,所以我們可以這樣寫:
Usedlist3 = [Phrase|Usedlist]
所以,整個謂語變爲:
prologwhile(Num, A, B, C, Usedlist) :-
Num < 9 ,
phrases(Ps),
random_member(Phrase-Value, Ps),
( member(Phrase, Usedlist) ->
prologwhile(Num, A, B, C, Usedlist)
; Usedlist3 = [Phrase|Usedlist],
Num3 is Num + Value,
prologwhile(Num3, A, B, 1, Usedlist3)
).
或更短:
prologwhile(Num, A, B, C, Usedlist) :-
Num < 9 ,
phrases(Ps),
random_member(Phrase-Value, Ps),
( member(Phrase, Usedlist) ->
prologwhile(Num, A, B, C, Usedlist)
; Num3 is Num + Value,
prologwhile(Num3, A, B, 1, [Phrase|Usedlist])
).
然而,我們還有:
?- main.
false.
爲了說明爲什麼這仍然失敗,想想案件中,謂詞應該 到舉行。一點反思之後,下面這樣一種情況,它應該保持:
prologwhile(Num, _, _, _, [_,_|_]) :- Num >= 9.
因此,我們的情況下加入到我們的節目,獲得:
prologwhile(Num, _, _, _, [_,_|_]) :- Num >= 9.
prologwhile(Num, A, B, C, Usedlist) :-
Num < 9 ,
phrases(Ps),
random_member(Phrase-Value, Ps),
( member(Phrase, Usedlist) ->
prologwhile(Num, A, B, C, Usedlist)
; Num3 is Num + Value,
prologwhile(Num3, A, B, 1, [Phrase|Usedlist])
).
注意如何我使用模式匹配在累積列表中檢測至少來自2個不同對的元素是 的情況。現在
,我們終於有:
?- main.
true .
這很酷,但不是那有用。
3.報告頂層
實際的解決方案現在,是時候詢問有關程序的一些更深層的問題。例如,這些論據真的在這裏做了什麼?讓我們完全忘記A
,B
和C
,獲得:
main :-
prologwhile(0, ["Garbage data1", "More garbage data"]).
prologwhile(Num, [_,_|_]) :- Num >= 9.
prologwhile(Num, Usedlist) :-
Num < 9 ,
phrases(Ps),
random_member(Phrase-Value, Ps),
( member(Phrase, Usedlist) ->
prologwhile(Num, Usedlist)
; Num3 is Num + Value,
prologwhile(Num3, [Phrase|Usedlist])
).
它的工作原理一樣好:
?- main.
true .
在另一方面,一個重要的事情似乎缺少,即短語我們實際上有 使用!讓我們通過介紹來表示它們。在這種情況下,一個有用的命名規則是一對Ls0
和Ls
,與Ls0
表示的初始列表,Ls
我們想要的頂層報告的最後一個。
我們也可以簡單地忘記「垃圾」元素。
因此,整個程序就變成了:
solution(List) :-
prologwhile(0, [], List).
prologwhile(Num, Ls, Ls) :- Num >= 9, Ls = [_,_|_].
prologwhile(Num, Ls0, Ls) :-
Num < 9 ,
phrases(Ps),
random_member(Phrase-Value, Ps),
( member(Phrase, Ls0) ->
prologwhile(Num, Ls0, Ls)
; Num3 is Num + Value,
prologwhile(Num3, [Phrase|Ls0], Ls)
).
phrases(["time of day"-1,
"Season"-5,
"Yesterdays weather"-2,
"Month of last big storm"-2,
"Randomly generated riddle"-9,
"A captcha"-1,
'Current day'-6,
"Tomorrows date"-5]).
樣品查詢:
?- solution(Ls).
Ls = ["Randomly generated riddle", "Season"] ;
false.
您也可以輕鬆擴展這個報告的總價值,無論是在構建列表或一個簡單的額外步驟。我把這留作練習。還請注意prologwhileisnotaseasytoread
,例如using_underscores_would_be
。
感謝您的幫助。這似乎工作。 –
@mat:非常好的指導性答案,+ s(0)! – tas
由於我一直在研究這個問題,你能否向我解釋最後兩步如何工作?我需要重新加入A,B和C,但是我不能沒有整個事情。 –