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

在Prolog中从多个答案中形成一个列表,prolog,dcg,Prolog,Dcg,我目前在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. 如果不使用任何内置谓词,例如findall/3?,则需要

我目前在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.

如果不使用任何内置谓词,例如
findall/3

,则需要在列表中添加解决方案,如果列表中的解决方案失败

?- findall(Qs,generate(Qs),Qss1),
   numlist(2,49,Xs),
   numlist(2,98,Ys),
   phrase(xproduct(x_y_maybe_quadruple,Xs,Ys),Qss2),
   Qss1 = Qss2.
Qss1 = Qss2, 
Qss2 = [[2, 3, 5, 6], [2, 4, 6, 8], [2|...], [...|...]|...],
Xs   = [2, 3, 4, 5, 6, 7, 8, 9, 10|...],
Ys   = [2, 3, 4, 5, 6, 7, 8, 9, 10|...].
所以


首先,您为
X
Y
给出的区间上限均为1:

  • 1
    不匹配
    nat(X,49)
    1
    匹配
  • 1
    不匹配
    nat(Y,98)
    1
    匹配
让我们开始吧

如果要收集所有解决方案而不使用
findall/3
(etc),一种方法是计算两个列表
Xs
Ys
的(也称叉积)

要获得
Xs
Ys
,我们可以使用内置谓词:

Xs
中的每个
X
Ys
中的每个
Y
组合使用

要选择要收集的四元组,请使用语法规则
x\u y\u maybe\u fourple//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.
   ).
所以。。。如果我们使用
findall/3
,我们真的会得到四倍吗

?- findall(Qs,generate(Qs),Qss1),
   numlist(2,49,Xs),
   numlist(2,98,Ys),
   phrase(xproduct(x_y_maybe_quadruple,Xs,Ys),Qss2),
   Qss1 = Qss2.
Qss1 = Qss2, 
Qss2 = [[2, 3, 5, 6], [2, 4, 6, 8], [2|...], [...|...]|...],
Xs   = [2, 3, 4, 5, 6, 7, 8, 9, 10|...],
Ys   = [2, 3, 4, 5, 6, 7, 8, 9, 10|...].

它能工作不仅如此:我们以完全相同的顺序得到完全相同的四倍体

是否允许您使用
成员
成员chk
?这些都是内置的谓词。由于某种奇怪的原因,在SO-Prolog问题中似乎有一种对常见ISO-Prolog谓词的流行恐惧症@潜伏者是的,不允许使用它们,任何内置的东西。从某种意义上说,我们必须用纯Prolog从头开始编写代码。作为一种方法的提示:为自己编写一个简单的
memberchk/2
谓词(您可以查看该谓词),然后编写一个简单的递归
genall/1
,它以空列表开始并递归填充,但避免已添加的元素(这就是
memberchk/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(Qs,generate(Qs),Qss1),
   numlist(2,49,Xs),
   numlist(2,98,Ys),
   phrase(xproduct(x_y_maybe_quadruple,Xs,Ys),Qss2),
   Qss1 = Qss2.
Qss1 = Qss2, 
Qss2 = [[2, 3, 5, 6], [2, 4, 6, 8], [2|...], [...|...]|...],
Xs   = [2, 3, 4, 5, 6, 7, 8, 9, 10|...],
Ys   = [2, 3, 4, 5, 6, 7, 8, 9, 10|...].