给定现金金额和币种列表即可生成更改

时间:2019-04-15 20:30:12

标签: prolog

我正在尝试用Prolog编写一个程序,该程序可以完成两件事:

  1. 带有两个参数,一个整数和一个整数列表
  2. 对于第二个元素的某些组合可以对第一个参数进行更改感到满意

我想出了一个解决该问题的方法,可以使更改规则统一为事实,例如:

coin(quarter, 25).
coin(dime,10).
coin(nickel,5).
coin(penny,1).

change(0, []).
change(A, [(C, Num)|L]) :- 
    coin(C, V), 
    A >= V, 
    Num is floor(A / V), 
    B is A mod V, 
    change(B, L).

此外,如果您将诸如change(27,L)之类的内容传递给解释器,它将生成可用于进行更改的四分之一,小数,镍和美分的所有可能组合,例如:

?- change(27,L).
L = [(quarter, 1),  (penny, 2)] ;
L = [(dime, 2),  (nickel, 1),  (penny, 2)] ;
L = [(dime, 2),  (penny, 7)] ;
L = [(nickel, 5),  (penny, 2)] ;
L = [(penny, 27)] ;
false.

但是,我遇到了麻烦,如何通过简单地将[25,10,5,1]这样的货币列表传递到找零,使通话看起来像找零(27,[25,10 ,, 5,1],L)。这可能吗?如果可以,怎么办?

1 个答案:

答案 0 :(得分:3)

因此,您实际上距离很近。这基本上是我留下的,扩大的评论。让我们为造币的类型添加另一个参数。

change(0, _, []).
change(A, Coinage, [(C, Num)|L]) :- 
    member(C=V, Coinage), 
    A >= V, 
    Num is floor(A / V), 
    B is A mod V, 
    change(B, Coinage, L).

我已将此coin(C, V)替换为member(C=V, Coinage)member/2是使Prolog程序更具动态性的好方法,因为从本质上讲,您可以从列表中生成解决方案,而不必查阅事实存储。看一下结果:

?- change(27, [quarter=25, dime=10, nickel=5, penny=1], Change).
Change = [(quarter, 1),  (penny, 2)] ;
Change = [(dime, 2),  (nickel, 1),  (penny, 2)] ;
Change = [(dime, 2),  (penny, 7)] ;
Change = [(nickel, 5),  (penny, 2)] ;
Change = [(penny, 27)] ;
false.

让我们看看是否应该添加3美分的硬币,也许上面印有最近的总统头像:

?- change(27, [quarter=25, dime=10, nickel=5, thripenny=3, penny=1], Change).
Change = [(quarter, 1),  (penny, 2)] ;
Change = [(dime, 2),  (nickel, 1),  (penny, 2)] ;
Change = [(dime, 2),  (thripenny, 2),  (penny, 1)] ;
Change = [(dime, 2),  (penny, 7)] ;
Change = [(nickel, 5),  (penny, 2)] ;
Change = [(thripenny, 9)] ;
Change = [(penny, 27)] ;

看起来这是个好主意!