2012-04-09 31 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]).