序言:硬币找零

box*_*oxy 3 prolog coin-change

我是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).
Run Code Online (Sandbox Code Playgroud)

几个测试用例

  change(100,10,8,5).
  True
  change(X,10,8,5).
  X = 100.
Run Code Online (Sandbox Code Playgroud)

但是,如果我尝试

 change(100,P,8,5).
Run Code Online (Sandbox Code Playgroud)

它给了我“参数没有被充分实例化”,而不是P = 10。

编辑:通过在谓词之间(0,M,P),之间(0,M,N),之间(0,M,D),之间的谓词来修复我的代码,M是P + 5 * N + 10 * D。

rep*_*eat 5

使用

:- use_module(library(clpfd)).
Run Code Online (Sandbox Code Playgroud)

我们需要表达的change/4只是一个等式:

change(Money,Pennies,Nickels,Dimes) :-
   Money #= Pennies + Nickels*5 + Dimes*10.
Run Code Online (Sandbox Code Playgroud)

让我们运行OP给出的基本查询!

?- change(100,10,8,5).
true.
Run Code Online (Sandbox Code Playgroud)

接下来,四个查询仅具有一个变量:

?-change (Money,10,8,5)。
金钱= 100。

?-change(100,便士,8,5)。
便士= 10。

--change(100,10,,5)。
镍= 8。

?-change(100,10,8,Dimes)。
角钱= 5。

当我们使用,我们还可以问一些更通用的查询,例如带有三个变量的查询:

?- change(100,Pennies,Nickels,Dimes).
100 #= Pennies + 5*Nickels + 10*Dimes.
Run Code Online (Sandbox Code Playgroud)

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

  1. 使用以下命令声明“所有计数均为非负数” ins/2

    ?- [小便镍,角钱] ins 0..sup,
       零钱(100,小便,镍,角钱)。
    100#=便士+ 5 *镍+ 10 *角钱,
    硬币在0..100中,
    0..20中的镍,
    毛钱在0..10。
    
  2. 使用枚举谓词labeling/2

    ?-Zs = [小便,镍,角钱],
       Zs ins 0..sup,
       零钱(100,小便,镍,角钱),
       labeling([],Zs)。
      便士= 0,镍= 0,角钱= 10
    ; 便士= 0,镍= 2,角钱= 9
    ; 硬币= 0,镍= 4,角钱= 8
    为简洁起见,省略了下一个115个答案的百分比
    ; 便士= 90,镍= 2,角钱= 0
    ; 便士= 95,镍= 1,角钱= 0
    ; 硬币= 100,镍= 0,角钱= 0
    ; 假。