2017-02-24 51 views
0

我目前正在Prolog中制定一個程序,該程序將計算一個數字的所有倍數(包括其自身),該數字不超過另一個數字的值。我正在使用以下查詢進行測試:Prolog - 低於上限的數字的倍數

?- multiples(4,12,R,0) 

此查詢將列出小於或等於12的所有4的倍數,例如, 4,8,12。R將返回結果,0是我打算實現一個計數器,每次乘法計數的位置,例如。 4 * 1,4 * 2,4 * 3。我被卡住了,我不確定是否更好的設計,只需添加倍數並檢查它是否低於上限或者是否可以使用計數器或累加器來完成。

multiples(N,U,R,Ctr) :- 
     N =< U, 
     R is Ctr * N, 
     R =< U, 
     increment(Ctr,Ctr2), 
     multiples(N,U,R,Ctr2). 

increment(Num, Num1) :- 
     Num1 is Num+1. 

我相信我的程序在從本身調用倍數的遞歸步驟失敗。我知道遞歸需要一個基本的例子來允許它退出,但我完全停留在這裏,並會欣賞一些方向。

+0

你並不需要檢查'N =

+0

此外'R'將**從未統一。這總是會導致「錯誤」。 –

回答

1

與你接近的問題是,沒有basecase:確實是你的算法總是會產生false.將統一RN,然後做遞歸和遞歸將試圖統一R2*N將失敗。

那麼一個想法可能是使用一個累加器,您每次都在其中添加增量。喜歡的東西:

multiples(N,U,R) :- 
    multiples(N,N,U,R). 

multiples(_,C,U,C) :- 
    C =< U. 
multiples(N,C,U,R) :- 
    C =< U, 
    C1 is C+N, 
    multiples(N,C1,U,R). 

所以在這裏我們稱之爲multiples(3,12,R).,它會導致:

?- multiples(4,12,R). 
R = 4 ; 
R = 8 ; 
R = 12 ; 
false. 
1

CLP(FD)是非常有幫助的位置:

:- use_module(library(clpfd)). 

multiple(Multiplicand, Max, Multiple) :- 
    MaxMultiplier #= Max // Multiplicand, 
    label([MaxMultiplier]), 
    Multiplier in 1 .. MaxMultiplier, 
    Multiple #= Multiplier * Multiplicand, 
    label([Multiple]). 

?- multiple(4, 12, M). 
M = 4 ; 
M = 8 ; 
M = 12. 

?- 

隨着CLP(FD)的這種情況下,也可以用第一個參數作爲變量進行查詢:

|?- multiple(N, 12, 8). 
N = 8 ; 
N = 4 ; 
N = 2 ; 
N = 1. 

或兩個乘數和結果:

?- multiple(N, 4, M). 
N = M, M = 3 ; 
N = M, M = 4 ; 
N = M, M = 2 ; 
N = 2, 
M = 4 ; 
N = M, M = 1 ; 
N = 1, 
M = 2 ; 
N = 1, 
M = 3 ; 
N = 1, 
M = 4. 

?- 

如果你想收集它們在列表中,你可以使用findall/3

?- findall(Multiple, multiple(4, 12, Multiple), Multiples). 
Multiples = [4, 8, 12]. 

?-