Prolog初学者(避免使用分号和if else语句)

时间:2015-04-08 07:14:13

标签: prolog

所以我想创建一个谓词,它将获取一个数字列表并总结每个条目的平方,如果它们可以被5或3整除。

所以,如果我有列表[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会给它一个错误。这是因为我的代码中有可分(Head)。我试图寻找一种解决方法,而不使用“if-else语句”或“;”在Prolog。

3 个答案:

答案 0 :(得分:2)

你走在正确的轨道上。您的代码中缺少一些内容。

首先,你只处理了" divisible"案件。因此,如果一个列表项不可分割,则整个目标都会失败。

接下来,在不使用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.

答案 1 :(得分:0)

你的第二个sumsquare / 2子句涵盖列表的第一个元素可以整除的情况。你需要添加第三个条款来涵盖它不是的情况。

答案 2 :(得分: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