【问题标题】:Prolog : coin change序言:硬币变化
【发布时间】:2015-04-01 05:02:43
【问题描述】:

我是 prolog 的新手,试图解决这个经典的硬币找零问题。

change(M,P,N,D) 用公式 M>=0 和 M = P+5*N+10*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。 这是什么原因?

edit : 通过使用 between predicate 来修复我的代码 介于(0,M,P),介于(0,M,N),介于(0,M,D),M为P+5*N+10*D。

【问题讨论】:

  • 您得到错误的原因是is/2 计算了一个算术表达式:它不是一个纯粹的“逻辑”谓词。您似乎已经知道至少一种解决此问题的方法;查看重复的问题和答案以获得更好的方法。

标签: prolog coin-change


【解决方案1】:

使用

:- use_module(library(clpfd)).

我们只需要表达change/4 就是一个方程:

change(Money,Pennies,Nickels,Dimes) :-
   Money #= Pennies + Nickels*5 + Dimes*10.

让我们运行 OP 给出的地面查询!

?- change(100,10,8,5).
true.

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

?- 零钱(,10,8,5)。 金钱 = 100。 ?- 零钱(100,便士,8,5)。 便士 = 10。 ?- 变化(100,10,,5)。 镍 = 8。 ?- 变化(100,10,8,Dimes)。 硬币 = 5。

当我们使用时,我们也可以提出更一般的查询,比如这个带有三个变量的查询:

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

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

  1. 使用ins/2 声明“所有计数都是非负数”:

    ?- [Pennies,Nickels,Dimes] ins 0..sup, 改变(100,便士,镍,角钱)。 100 #= 便士 + 5*镍 + 10*角钱, 0..100 美分, 0..20 中的镍, 0..10 美元。
  2. 使用枚举谓词labeling/2

    ?- Zs = [便士、镍、角钱], Zs ins 0..sup, 零钱(100,便士,镍,角钱), 标签([],Zs)。 便士 = 0,镍币 = 0,硬币 = 10 ;便士 = 0,镍币 = 2,硬币 = 9 ;便士 = 0,镍币 = 4,一角硬币 = 8 % 为简洁起见,省略了接下来的 115 个答案 ;便士 = 90,镍币 = 2,一角硬币 = 0 ;便士 = 95,镍币 = 1,硬币 = 0 ;便士 = 100,镍币 = 0,一角钱 = 0 ;错误的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-11
    • 2016-01-24
    • 2017-10-28
    • 2014-01-11
    • 1970-01-01
    • 1970-01-01
    • 2012-07-04
    相关资源
    最近更新 更多