Пользовательский реверс списка в Прологе - PullRequest
0 голосов
/ 05 октября 2010

Я пытаюсь написать предикат, который, учитывая следующий список в Прологе:

[[1,a,b],[2,c,d],[[3,e,f],[4,g,h],[5,i,j]],[6,k,l]]

создаст следующий список:

[[6,k,l],[[5,i,j],[4,g,h],[3,e,f]],[2,c,d],[1,a,b]]

Как видите, я бы хотелсохранить порядок элементов на самом низком уровне, чтобы получить элементы в порядке 1, a, b и NOT b, a, 1.

Я также хотел бы сохранить глубину списков, то естьсписки, которые изначально являются вложенными, возвращаются как таковые, но в обратном порядке.

Мне удалось достичь желаемого порядка с помощью следующего кода, но глубина потеряна, то есть списки больше не вложены правильно:

accRev([F,S,T],A,R) :- F \= [_|_], S \= [_|_], T \= [_|_], 
                                 accRev([],[[F,S,T]|A],R).
accRev([H|T],A,R) :- accRev(H,[],R1), accRev(T,[],R2), append(R2,R1,R).
accRev([],A,A).
rev(A,B) :- accRev(A,[],B).

Буду признателен за помощь в исправлении кода, чтобы сохранить правильное вложение списков.Спасибо!

1 Ответ

0 голосов
/ 05 октября 2010

Два предложения.Во-первых, вот один (rev_lists/2), который использует несколько встроенных модулей SWI-PROLOG:

rev_lists(L, RL) :-
    forall(member(M, L), is_list(M)), !,
    maplist(rev_lists, L, L0),
    reverse(L0, RL).
rev_lists(L, L).

Этот работает путем проверки, все ли элементы списка L сами являются списками (M);если это так, он будет рекурсивно применять себя (через maplist) ко всем отдельным подспискам, иначе он вернет тот же список.Это имеет необходимый эффект.

Во-вторых, здесь снова rev_lists/2, но написано так, что оно не полагается на встроенные модули, кроме member/2 (что является обычным):

rev_lists(L, RL) :-
    reversible_list(L), !,
    rev_lists(L, [], RL). 
rev_lists(L, L).

rev_lists([], Acc, Acc).
rev_lists([L|Ls], Acc, R) :-
    (   rev_lists(L, RL), !
    ;   RL = L
    ),
    rev_lists(Ls, [RL|Acc], R).

reversible_list(L) :-
    is_a_list(L),
    \+ (
        member(M, L),
        \+ is_a_list(M)
    ).

is_a_list([]).
is_a_list([_|_]).

Это в основном то же самоестратегия, но использует аккумулятор для создания обратных списков на каждом уровне, если они состоят исключительно из списков;в противном случае возвращается тот же список.

...