2015-04-01 82 views
3

我是新的prolog,试图解决这个经典的硬币更换问题。Prolog:硬币更换

变化(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 这是什么东西? (0,M,P)之间,(0,M,N)之间,(0,M,D)之间使用谓词 修复我的代码,M是P + 5 * N + 10 * d。

+2

POSS可重复的[Prolog打破更小的金额](http://stackoverflow.com/questions/29338495/prolog-break-money-into-smaller-amounts) – 2015-04-01 06:20:31

+2

你得到错误的原因是'是/ 2评估一个_arithmetic表达式:它不是一个纯粹的“逻辑”谓词。您似乎已经知道至少有一种解决方法,看到重复的问题和更好的方法的答案。 – 2015-04-01 06:42:29

回答

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.