我遇到这样的问题:查找列表中的所有元素,使得除此之外的所有元素都是奇数。
例如
?- find([20,1,2,3,4,5,6,7,8,10], L).
L = [20, 2, 4, 6]
通常在其他语言中我会遍历列表并检查条件,但我不知道在这种情况下如何在Prolog中“思考”。我该怎么做呢?
答案 0 :(得分:3)
考虑一对头元素访问列表:
find([A,B|R], [A|T]) :-
is_odd(B),
... etc etc
你需要明显添加基本递归情况和必须丢弃A的情况。
答案 1 :(得分:1)
编辑:基于CapelliCs建议的更好解决方案(这使用下面的isodd
谓词):
% if N0 and N2 are odd, cut, add N1 to the result and recurse
ff([N0,N1,N2|T], [N1|R]) :- isodd(N0), isodd(N2), !, ff([N1,N2|T], R).
% for any other case where the list has at least three members, cut and recurse
ff([_,N1,N2|T], R) :- !, ff([N1,N2|T], R).
% this is reached if the list has less that three members - we're done
ff(_, []).
% append and prepend '1' to the list to deal with the edges, call ff.
find(L, R) :- append(L, [1], L1), ff([1|L], R).
我的旧解决方案,用额外的参数跟踪前两个值:
% isodd(+N)
% helper predicate that succeds for odd numbers.
isodd(N) :- mod(N, 2) =:= 1.
% find(+I, +N1, +N2, +R, -L)
% find/5 is the predicate doing the actual work.
% I is the input list, N1 and N2 are the numbers before the current one,
% R is the intermediate result list and L the result.
% we're done if the input list is empty
find([], _, _, R, R) :- !.
% check if N0 and N2 are odd to see if N1 should be appended to the list.
% if yes, do a cut, append N1 to the result and recurse.
find([N0|T], N1, N2, R, L) :-
isodd(N0), isodd(N2), !,
append(R, [N1], R1), find(T, N0, N1, R1, L).
% if N0 and N2 are not odd (and thus the cut in the previous clause isn't
% reached) just continue the recursion.
find([N0|T], N1, _, R, L) :- find(T, N0, N1, R, L).
% find(+I, -L)
% this predicate is the entry point - initialize the result list and the first
% values for N1 and N2, and append 1 to the input list so we don't need an extra
% predicate for dealing with the last item.
find(I, L) :- append(I, [1], I1), find(I1, 1, 0, [], L).