2015-04-08 54 views
1

所以我想創建一個謂語,將採取數字列表並總結了每個條目的平方IF他們要麼是整除5或3Prolog的初學者(避免使用分號,如果else語句)

所以,如果我有列表[6,7,9,10],它將返回的

6^2+9^2+10^2 

一筆什麼我迄今所做的是這樣的:

sumsquared([], 0). 


sumsquared([Head|Tail], Sum):- 

    divisible(Head), 

    sumsquared(Tail, Sumofrest), 

    Sum is Head*Head + Sumofrest. 



divisible(Head):- 

    0 is Head mod 3. 

divisible(Head):- 

    0 is Head mod 5. 

此代碼工作對於[3,6,9,10]和類似的事情,但是當我們有一個列表[2,3,6,9,10],prolog會給它一個錯誤的。這是因爲我在我的代碼中可以分割(頭)。我試圖尋找一種解決方法,而不使用「if-else語句」或「;」在Prolog中。

回答

0

您的第二個sumsquare/2子句涵蓋了列表的第一個元素可以被整除的情況。你需要添加第三個條款來覆蓋不是的情況。

2

您正處於正確的軌道上。你的代碼中缺少一些東西。

首先,您只處理了「可分割」的情況。所以如果一個列表項不可分割,整個目標都會失敗。

接下來,以表達non_divisible不使用->;申請 德摩根定律去:

divisible(X) :- X mod 3 =:= 0. 
divisible(X) :- X mod 5 =:= 0. 

non_divisible(X) :- X mod 3 =\= 0, 
        X mod 5 =\= 0. 

sumsquared([], 0). 
sumsquared([Head|Tail], Sum):- 
    divisible(Head), 
    sumsquared(Tail, Sumofrest), 
    Sum is Head*Head + Sumofrest. 
sumsquared([Head|Tail], Sum) :-  % new clause 
    non_divisible(Head), 
    sumsquared(Tail, Sum). 

我們來測試你又給了查詢:

?- sumsquared([6,7,9,10], Sum). 
Sum = 217 ; 
false. 
0
One solution, not tail-recursive (meaning it will overflow the stack given a sufficiently long list). 

    compute_sum_of_list_squaring_multiples_of_five_or_three([]  , 0) . 
    compute_sum_of_list_squaring_multiples_of_five_or_three([X|Xs] , R) :- 
     compute_sum_of_list_squaring_multiples_of_five_or_three(Xs , T) , 
     transform(X,N) , 
     R is T + N. 

    transform(X , X) :- 0 =:= X mod 5 + X mod 3 , ! . 
    transform(X , N) :- N is X*X . 

Transformed into tail-recursion: 

    compute_sum_of_list_squaring_multiples_of_five_or_three(Xs,R) :- 
     compute_sum_of_list_squaring_multiples_of_five_or_three(Xs,0,R) 
     . 

    compute_sum_of_list_squaring_multiples_of_five_or_three([]  , R , R) . 
    compute_sum_of_list_squaring_multiples_of_five_or_three([X|Xs] , T , R) :- 
     transform(X,N) , 
     T1 is T+N, 
     compute_sum_of_list_squaring_multiples_of_five_or_three(Xs , T1, R). 

    transform(X , X) :- 0 =:= X mod 5 + X mod 3 , ! . 
    transform(X , N) :- N is X*X . 

A generic version: 

    compute_sum_of_list_squaring_certain_multiples(Xs , Ds , R) :- 
     compute_sum_of_list_squaring_certain_multiples(Xs , Ds , 0 , R) 
     . 

    compute_sum_of_list_squaring_certain_multiples([]  , _ , R , R) . % when we get to the end of the list, the accumulator has the desired value. Unify it with the result. 
    compute_sum_of_list_squaring_certain_multiples([X|Xs] , Ds , T , R) :- % otherwise... 
     transform(X,Ds,N) ,              % - transform X (squaring X if divisible an item in Ds, leaving it alone otherwise) 
     T1 is T+N ,                % - add the transformed value to the accumulator 
     compute_sum_of_list_squaring_certain_multiples(Xs,Ds,T1,R)    % - and recurse down. 
     .                  % 

    transform(X , [] ,X ) .    % no target dividends? leave it alone. 
    transform(X , [D|_] , N) :-    % otherwise... 
     0 =: X mod D ,       % - if X is divisible by the current dividend, 
     !,          % - cut off the alternatives, 
     N is X*X        % - square X and unify with the result. 
     .          % 
    transform(X,[_|Ds],N) :-     % Finally (X is not divisible by the dividend in question)... 
     transform(X,Ds,N)      % - uust recurse down and keep looking. 
     .          % 

你應該能夠調用上述:

compute_sum_of_list_squaring_certain_multiples([1,2,3,4,5,6] , [3,5] , R) . 

並獲得

R = 41 
+0

'變換/ 2'不踏實。 – repeat