Prolog 工作深度优先,这意味着它将继续寻找将列表与玩具一起进一步添加到列表中,并且永远不会查看是否已经达到总价格,从而添加更多元素没有意义。
我们可以通过反向计算价格来解决这个问题:我们可以使用library(clpfd)并定义有玩具的列表价格和没有玩具的价格之间的关系,并添加一个约束条件,即我们的价格如果我们递归,寻找应该总是大于零,例如:
:- use_module(library(clpfd)).
calculatePrice([], 0).
calculatePrice([H|T], PHT) :-
PHT #> 0,
toy(H, PH),
PHT #= PT + PH,
calculatePrice(T, PT).
然后我们得到例如:
?- calculatePrice(L, 21).
L = [train, train, train, doll] ;
L = [train, train, train, car, car] ;
L = [train, train, doll, train] ;
L = [train, train, car, train, car] ;
L = [train, train, car, car, train] ;
L = [train, doll, train, train] ;
...
?- calculatePrice([train, train], P).
P = 10.
?- calculatePrice(L, P).
L = [],
P = 0 ;
L = [train],
P = 5 ;
L = [train, train],
P = 10 ;
L = [train, train, train],
P = 15 ;
L = [train, train, train, train],
P = 20 ;
L = [train, train, train, train, train],
P = 25
...
这里需要约束PHT #> 0。当我们查询 calculatePrice(L, 21) 时,您可以看到 PHT 作为“我们还剩下要花费的金额”。如果金额小于或等于零,我们就不能再花任何钱了,因此这个约束应该失败。