让我们解决它在阶段:
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,但是我不能没有整个事情。 –