Prolog:改变硬币

时间:2015-04-01 05:02:43

标签: prolog

我是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.

1 个答案:

答案 0 :(得分:4)

使用

:- 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.

在我们使用时,我们还可以提出更多一般性查询,例如三个变量的查询:

?- change(100,Pennies,Nickels,Dimes).
100 #= Pennies + 5*Nickels + 10*Dimes.

请注意,这还没有(还)枚举所有可能的组合...这样做需要两个步骤:

  1. 声明"所有计数都是非负面的"使用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.
    
  2. 使用枚举谓词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.