我是prolog的新手,试图解决这个经典的硬币更换问题。
用M> = 0且M = P + 5 * N + 10 * D的公式改变(M,P,N,D) 这是我的方法
change(M,P,N,D) :-
M is P+5*N+10*D,
P is M - (5*N+10*10).
几个测试用例
change(100,10,8,5).
True
change(X,10,8,5).
X = 100.
但是,如果我尝试
change(100,P,8,5).
它给了我"参数没有充分实例化"而不是P = 10。 什么是这个?
编辑:使用谓词之间修复我的代码 在(0,M,P)之间,(0,M,N)之间,(0,M,D)之间,M是P + 5 * N + 10 * D.
答案 0 :(得分:4)
使用clpfd!
:- use_module(library(clpfd)).
我们需要表达change/4
一个等式:
change(Money,Pennies,Nickels,Dimes) :-
Money #= Pennies + Nickels*5 + Dimes*10.
让我们运行OP给出的地面查询!
?- change(100,10,8,5).
true.
接下来,有四个查询具有一个变量:
?- change(Money,10,8,5). Money = 100. ?- change(100,Pennies,8,5). Pennies = 10. ?- change(100,10,Nickels,5). Nickels = 8. ?- change(100,10,8,Dimes). Dimes = 5.
在我们使用clpfd时,我们还可以提出更多一般性查询,例如三个变量的查询:
?- change(100,Pennies,Nickels,Dimes).
100 #= Pennies + 5*Nickels + 10*Dimes.
请注意,这还没有(还)枚举所有可能的组合...这样做需要两个步骤:
声明"所有计数都是非负面的"使用ins/2
:
?- [Pennies,Nickels,Dimes] ins 0..sup, change(100,Pennies,Nickels,Dimes). 100 #= Pennies + 5*Nickels + 10*Dimes, Pennies in 0..100, Nickels in 0..20, Dimes in 0..10.
使用枚举谓词labeling/2
:
?- Zs = [Pennies,Nickels,Dimes], Zs ins 0..sup, change(100,Pennies,Nickels,Dimes), labeling([],Zs). Pennies = 0 , Nickels = 0, Dimes = 10 ; Pennies = 0 , Nickels = 2, Dimes = 9 ; Pennies = 0 , Nickels = 4, Dimes = 8 % the next 115 answers were omitted for the sake of brevity ; Pennies = 90 , Nickels = 2, Dimes = 0 ; Pennies = 95 , Nickels = 1, Dimes = 0 ; Pennies = 100, Nickels = 0, Dimes = 0 ; false.