从Prolog中的多个答案中形成一个列表

时间:2015-03-16 14:57:34

标签: prolog

我目前在Prolog中有这段代码

s1(Q,100) :- generate(Q).

generate([X,Y,S,P]) :-
  nat(X, 49),
  nat(Y, 98),
  S is X+Y,
  P is X*Y,
  S =< 100,
  X < Y.

nat(2,_).
nat(X,N) :-
  N > 2,
  M is N - 1,
  nat(Y,M),
  X is Y + 1.

它目前会生成一个四元组列表X, Y, S, P,以便

  • 1&lt; X&lt; 49
  • 1&lt; Y&lt; 98
  • 1&lt; X&lt; ÿ
  • X + Y <= 100
  • P = X * Y
  • S = X + Y

这有效并创建所有可能的解决方案,但有多个答案(即每次都必须按;才能获得下一个结果。)

如何从所有这些结果中形成单个列表,例如

[[2, 3, 5, 6], [2, 4, 6, 8], ...]

没有使用任何内置谓词,例如findall/3

2 个答案:

答案 0 :(得分:2)

首先,您为XY提供的上限间隔都是一个:

  • 1 < X < 49nat(X,49)不匹配,1 < X =< 49无效。
  • 1 < Y < 98nat(Y,98)不匹配,1 < Y =< 98无效。

让我们开始吧!

如果您想使用findall/3(等)收集而不的所有解决方案,一种方法是计算两个列表的Cartesian product(又名交叉产品){{ 1}}和Xs

要获得YsXs,我们可以使用内置谓词numlist/3

Ys

要将?- numlist(2,49,Xs). Xs = [2,3,4,/* consecutive integers from 5 to 47 omitted */,48,49]. ?- numlist(2,98,Ys). Ys = [2,3,4,/* consecutive integers from 5 to 96 omitted */,97,98]. 中的每个XXs中的每个Y合并,我们会使用 xproduct//3

要选择要收集的四元组,请使用语法规则Ys

x_y_maybe_quadruple//2

让我们把它们放在一起!

x_y_maybe_quadruple(X,Y) -->
   (  { 1 < X, X < Y, X+Y =< 100 }       % if all these conditions are met
   -> { P is X * Y },
      { S is X + Y },
      [[X,Y,S,P]]                        % then add single "quadruple"
   ;  []                                 % else add nothing.
   ).

那么......如果我们使用?- numlist(2,49,Xs), numlist(2,98,Ys), phrase(xproduct(x_y_maybe_quadruple,Xs,Ys),Qss). Qss = [[2,3,5,6],[2,4,6,8], /* lots of other quadruples omitted */, [48,51,99,2448],[48,52,100,2496]]. ,我们实际上会得到所有四倍吗?

findall/3

它有效!不仅如此:我们在完全相同的订单中获得完全相同的四倍!

答案 1 :(得分:0)

如果列表中尚未包含解决方案,则需要在列表中添加解决方案...如果列表中的解决方案失败。

所以

myfindall(List) :-
   my_find(List,[]),
   !.

my_find(List,Ac) :-
   s1(Q,100), 
   my_set(Q,Ac,NewAc),
   my_find(List,NewAc).
my_find(Ac,Ac).

my_set(X,[],[X]) :-
   !.
my_set(H,[H|_],_) :-
   !,
   fail.
my_set(X,[H|T],L) :- 
   my_set(X,T,Rtn),
   L = [H|Rtn].