私はこのような問題を抱えています:リスト内のすべての要素を見つけて、それ以外のすべての要素が奇数になるようにします。
例えば
?- find([20,1,2,3,4,5,6,7,8,10], L).
L = [20, 2, 4, 6]
通常、他の言語ではリストを調べて条件を確認しますが、このシナリオでPrologで「考える」方法がわかりません。これにどのようにアプローチすればよいですか?
私はこのような問題を抱えています:リスト内のすべての要素を見つけて、それ以外のすべての要素が奇数になるようにします。
例えば
?- find([20,1,2,3,4,5,6,7,8,10], L).
L = [20, 2, 4, 6]
通常、他の言語ではリストを調べて条件を確認しますが、このシナリオでPrologで「考える」方法がわかりません。これにどのようにアプローチすればよいですか?
ヘッド要素のペアを考慮してリストにアクセスしてください。
find([A,B|R], [A|T]) :-
is_odd(B),
... etc etc
明らかに、基本再帰ケースとAを破棄する必要があるケースを追加する必要があります。
編集: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).
追加の引数で前の2つの値を追跡する私の古いソリューション:
% 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).