swi prolog程序“未更改”未正确返回面额

swi prolog程序“未更改”未正确返回面额,prolog,Prolog,如果我取消第3行中的“中止”,程序将在屏幕上生成所需输出的近似值,例如: ?- biggest_denom(37,P). Pay with 25 ; remainder =12 Pay with 10 ; remainder =2 Pay with 1 ; remainder =1 Pay with 1 ; remainder =0 Finish % Execution Aborted ?- 但是,我希望在按分号或按列表变量返回时使用“更纯”的返回解决方案。查出似乎没有提供任何线索 第3行中

如果我取消第3行中的“中止”,程序将在屏幕上生成所需输出的近似值,例如:

?- biggest_denom(37,P).
Pay with 25 ; remainder =12
Pay with 10 ; remainder =2
Pay with 1 ; remainder =1
Pay with 1 ; remainder =0
Finish
% Execution Aborted
?- 
但是,我希望在按分号或按列表变量返回时使用“更纯”的返回解决方案。查出似乎没有提供任何线索

第3行中的“中止”没有取消,我能得到的最好结果是:

?- biggest_denom(13,P).
Pay with 10 ; remainder =3
Pay with 1 ; remainder =2
Pay with 1 ; remainder =1
Pay with 1 ; remainder =0
Finish
P = 10 ;
Pay with 5 ; remainder =8
Pay with 5 ; remainder =3
Pay with 1 ; remainder =2
Pay with 1 ; remainder =1
Pay with 1 ; remainder =0
Finish
P = 5 ;
Pay with 1 ; remainder =7
Pay with 5 ; remainder =2
Pay with 1 ; remainder =1
Pay with 1 ; remainder =0
Finish
P = 5 ;
Pay with 1 ; remainder =6
Pay with 5 ; remainder =1
Pay with 1 ; remainder =0
Finish
P = 5 ;
Pay with 1 ; remainder =5
Pay with 5 ; remainder =0
Finish
P = 5 ;
Pay with 1 ; remainder =4
Pay with 1 ; remainder =3
Pay with 1 ; remainder =2
Pay with 1 ; remainder =1
Pay with 1 ; remainder =0
Finish
P = 5        %IT GOES ON AND ON LIKE THIS!! XXXXXXXXXXXXX
这是我的密码:

%XXXXXXXXXXXXX no change given XXXXXXXXXXXXXXXXXXXXXXXXXXXX  
accept([100,50,25,10,5,1]). %pre-sorted (listing from big to small)

biggest_denom( 0 , _ ) :- writeln('Finish'). %,abort. %please STOP!!! horrible!
biggest_denom( N , D ) :-
  N \= 0  ,
  accept(X)  ,
  member(D,X) ,
  D =< N ,
  Remainder is N-D ,
  write('Pay with ') ,
  write(D) ,
  write(' ; remainder =') ,
  writeln(Remainder) ,
  %Remainder \= 0 , %gives more output, for some reason, not less
  biggest_denom(Remainder,D2)
  .

pay( N ) :- %print list of denoms which adds up to N ; will use findall
  writeln('not yet implemented') .

任何建议都将不胜感激

你应该让高层为你写作。您还可以去掉accept/1中的列表,将它们作为事实

accept(100).
accept(50).
accept(25).
accept(10).
accept(5).
accept(1).

return_change(N, C) :- integer(N), N > 0,
    return_change_1(N, C).

return_change_1(0, []) :- !.
return_change_1(N, [X-R|Change]) :-
    accept(X),
    X =< N,
    R is N - X,
    return_change_1(R, Change).
或者,如果您坚持输出:

?- return_change(37, C), !, forall(member(P-R, C), format("Pay with ~d ; remainder ~d~n", [P, R])).
Pay with 25 ; remainder 12
Pay with 10 ; remainder 2
Pay with 1 ; remainder 1
Pay with 1 ; remainder 0
C = [25-12, 10-2, 1-1, 1-0].
删除查询中的剪切以获得更多解决方案


正如@mat所指出的,所谓的foo!可以使用谓词one/1更优雅地表达,如下所示:oncefo

@mat Yes,这是故意的。错误的做法是更改谓词的名称。是的,这个程序有类似的版本,要求以所有可能的方式支付或返回更改,但今天我只是在寻找一个最明显的解决方案,我认为,这就是Boris的代码似乎一直在做的事情。感谢所有人,尤其是鲍里斯!!!once/1是提交第一个解决方案的一个优雅的替代方案。
?- return_change(37, C), !, forall(member(P-R, C), format("Pay with ~d ; remainder ~d~n", [P, R])).
Pay with 25 ; remainder 12
Pay with 10 ; remainder 2
Pay with 1 ; remainder 1
Pay with 1 ; remainder 0
C = [25-12, 10-2, 1-1, 1-0].