swi-prolog progam"没有给出任何改变"没有正确回归教派

时间:2014-07-27 10:42:32

标签: 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
?- 

然而,我想要'purer'return-solutions-when-hit-decmicon或return-as-list变体。 (“追踪。”似乎没有提供任何线索)。

我能得到的最好(第3行中的'abort'没有被删除)是:

?- 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') .

非常感谢任何建议!

1 个答案:

答案 0 :(得分:0)

你应该让顶级成员为你写作。你也可以删除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), !.
C = [25-12, 10-2, 1-1, 1-0].

或者,如果你坚持输出:

?- 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, !可以更优雅地表达来电once/1,如下所示:once(foo)