2012-04-09 33 views
2

对于我的程序,我需要列出一个列表,每个子列表包含2个数字,X和Y以及这两个数字的总和和乘积。 到目前为止,我有以下几点:列表建设问题

genList(95, X,[]):-!. 
genList(N, X,[[X,Y,Sum,Product]|Xs]):- 
    Y is N+1, 
    Sum is X+Y, 
    Sum<101, 
    Product is X*Y, 
    N1 is N+1, 
    genList(N1, X,Xs). 

这只是正常的genList我的测试用例(5,5,Q)。 但是,我很难让它适用于任何起始号码。

的目标是找到每对其中sum < = 100。通过上述所以在针对一个起始值的数字,X会发现每对1 < X < Y,其中sum < = 100,并通过它在运行所有数字2-N都会给出完整的可能配对列表。

对于那些有兴趣,我通过工作问题的总和/产品问题描述here

如果任何人都可以在这方面帮助其将不胜感激(页二上)!

此外,没有内置的序言谓词能够使用,因此这是做这件事的复杂方式,而不是findall。

通过该预测所产生的输出的一小摘录如下:

[[5,6,11,30],[5,7,12,35],[5,8,13, 40],[5,9,14,45],[5,10,15,50],[5,11,16,55],[5,12,17,60],[5,13,​​18, 65],[5,14,19,70],[5,15,20,75],[5,16,21,80],[5,17,22,85],[5,18,23, 90],[5,19,24,95],[5,20,25,100],[5,21,26,105],[5,22,27,110],...

编辑:

好的,经过一些编辑,这是我的代码的最新版本。

我觉得它非常接近,但还是有些不太对劲。

它通过数字对循环,但需要使用“;”查看所有的答案,这不是我想要的。另外,在所有答案都用完之后它会返回false。我无法弄清楚。

此外,它在中间给出了一个完整的答案,但每次都会删除一个子列表,直到剩下最后一组对。

E.g. genList(0,48,48,Q)。给我:

[[48,49,97,2352],[48,50,98,2400],[48,51,99,2448],[48,52,100,2496]] 
[[48,49,97,2352],[48,50,98,2400],[48,51,99,2448],[48,52,100,2496],[49,50,99,2450],[49,51,100,2499]] 
[[48,49,97,2352],[48,50,98,2400],[48,51,99,2448],[49,50,99,2450],[49,51,100,2499]] 
[[48,49,97,2352],[48,50,98,2400],[49,50,99,2450],[49,51,100,2499]] 
[[48,49,97,2352],[49,50,99,2450],[49,51,100,2499]] 
[[49,50,99,2450],[49,51,100,2499]] 
false. 

正如你所看到的,一个子列表每次被删除,我只是不明白为什么!

回答

1

您可以利用Prolog的回溯这里。只是说出你想要的。例如,你可以说:

  • 我想X1100之间。
  • 我要Y介于1min(100 - X, X)之间。
  • 那么我想他们对

让我们来看看什么是validPair/1谓词会是什么样子:

validPair(X-Y) :- 
    between(1, 100, X), 
    Limit is min(100 - X, X), 
    between(1, Limit, Y). 

你可以只用

?- validPair(X). 

调用它,并且与;浏览结果或者使用findall/3构建所有匹配对的列表。

编辑:即使有递归,我们可以保持我们的声明:

  • 我想X1100之间。
  • 我要Y介于1min(100 - X, X)之间。
  • 那么我想他们对

于是,一个想法做这将是建立一个工人断言:

validPair(Result) :- 
    validPair(0, 0, Result). 
validPair(X, Y, R) :- 
    ... 

然后设置基本情况:

validPair(101, _Y, []) :- !. 

并在工作者谓词中实现我们在某些条件下做出的表述:

validPair(X, Y, [SomeStuff|R]) :- 
    X =< 100, 
    Limit is min(100 - X, X), 
    Y =< Limit, 
    !, 
    % we can go on and increment Y once we're finished 
    validPair(X, NextY, R). 
validPair(X, Y, R) :- 
    % if we come here that means that Y is finished growing and 
    % we have to increment X 
    NextX is X + 1, 
    validPair(NextX, 0, R). 
+0

啊,是的,对于这个程序,我们不允许使用除算术和切割以外的任何序言内置插件 - 可能应该提到这个! – XavierNuquos 2012-04-09 13:41:01

+0

感谢莫格。这几乎就在那里,然而这里的限制因素是总和<= 100,而不是<= 100。我很抱歉,因为我在原始文章中注意到一个巨大的块被省略了:“目标是找到每一对数字,其中sum <= 100。因此,对于一个初始值运行上述操作,X会发现每对1 XavierNuquos 2012-04-09 14:31:44

+0

哈哈,我想不是,只是在我的尝试中,我最终以“假”的方式返回,就像我在另一个问题中那样:(这很烦人,因为它非常接近我所需要的,但我可以'嗯,我会尝试一些更多的东西,如果它还没有发生,就回到这里... – XavierNuquos 2012-04-09 14:40:54

1

我有一种感觉,你正在以错误的方式解决问题;我必须承认我并不真正了解你的谓词在做什么。

目标是找到每一对数字,其中总和< = 100。

假设你的意思是无序对非负整数,这是

between(0, 100, Sum), 
between(0, Sum, X), 
Y is Sum - X, 
X =< Y. 

集合所有这些对(如列表)中,然后可以用findall/3构造。

你也可以做到这一点使用CLP(FD):

use_module(library(clpfd)). 
[X, Y, Sum] ins 0..100, 
X #=< Y, 
X + Y #= Sum, 
label([X,Y,Sum]).