所以我想创建一个谓词,它将获取一个数字列表并总结每个条目的平方,如果它们可以被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。
答案 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