我正在尝试用Prolog编写一个程序,该程序可以完成两件事:
我想出了一个解决该问题的方法,可以使更改规则统一为事实,例如:
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)。这可能吗?如果可以,怎么办?
答案 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)] ;
看起来这是个好主意!