Prolog中预期功能规则中的错误

时间:2019-04-25 16:44:26

标签: prolog

我正在尝试解决有关枪支有两种损坏选择(选项:s,选项:c)的问题。选项s给予伤害D,选项c将当前伤害加倍至2 * D。规则的结构方式如下:

evaluate_damage(D,List,TotalDamage).

D是初始伤害。

列表是一个包含s和c的列表。

TotalDamage是列表造成的总损坏。

这里有一些例子。

?- evaluate_damage(1, [s,s], TotalDamage).
TotalDamage = 2
Yes

?- evaluate_damage(1, [s,c,s,c], TotalDamage).
TotalDamage = 3
Yes

?- evaluate_damage(1, [s,c,s,c,s,s], TotalDamage).
TotalDamage = 11
Yes

?- evaluate_damage(2, [s,s], TotalDamage).
TotalDamage = 4
Yes

它本身可以很好地工作,但是当我在另一条规则中使用它时,它并没有给出预期的结果。具体来说,我的程序中还有另一个规则,该规则重新排列字符的顺序以减少损害。 该规则的结构方式如下:

hack(List,Max,NewProgram,N).

“列表”是元素列表。 “最大”是重新排列的列表将造成的最大损坏。 NewProgram是重新排列的列表,

N是为到达重新排列的列表NewProgram而进行的交换次数。

以下是该规则的预期结果:

?- hack([c, s], 1, NewProgram, N).
NewProgram = [s, c]
N = 1
Yes
?- hack([s, s], 1, NewProgram, N).
No
?- hack([s, c, c, s, s, c], 6, NewProgram, N).
NewProgram = [s, s, c, c, s, c]
N = 2
Yes
?- hack([c, s, c, s, s], 3, NewProgram, N).
NewProgram = [s, s, s, c, c]
N = 5
Yes

这是我的代码。

evaluate_damage(_,[],0).
evaluate_damage(D,s,D).
evaluate_damage(D,c,Damage) :-
  Damage is D*2.
evaluate_damage(D,[H|List],TotalDamage) :- 
    evaluate_damage(D,H,Damage),
    (Damage=D;Damage=0),
    evaluate_damage(D,List,TDamage),
    TotalDamage is D+TDamage.
evaluate_damage(D,[H|List],TotalDamage) :-
    evaluate_damage(D,H,Damage),
    Damage>D,
    evaluate_damage(Damage,List,TotalDamage).

cutList(List,List1,[c|List2]) :- 
    append(List1,[c|List2], List),!.

hack(List,Max,NewProgram,N) :-
    cutList(List,L1,[c|L2]),
    length(L2,Length2),
    append(L2,c,NewList2),
    append(L1,NewList2,NewList),
    evaluate_damage(1,NewList,SecondDamage),
    SecondDamage=<Max,
    N is Length2,
    NewProgram is NewList.

实际输出是

?- hack([c, s], 1, NewProgram, N).
No (0.00s cpu)

我通过跟踪器(工具-tkEclipse中的选项)调试了它,问题是当

evaluate_damage(D,Program,TotalDamage)

在内部被称为

hack(Program,Max,NewProgram,N)

它没有给出预期的输出。真的很奇怪,因为     Evaluation_damage(D,Program,TotalDamage)

被自己调用,可以完美工作。有人知道是什么问题吗?

1 个答案:

答案 0 :(得分:1)

...
append(L2,c,NewList2),
...

append的第二个参数必须是列表。

和is / 2不会从右到左“复制”一个值。在头部或统一运算符= / 2中使用变量。认真考虑Daniel关于重命名后重新考虑代码的建议。

总体而言,您的Prolog进展顺利。 当然,现代Prolog系统中有一些库可以大大缩短代码。但是解决基本问题所获得的教学价值是无价的。