2010-10-05 2 views
0

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

[[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.

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

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

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). 

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

ответ

0

Два предложения. Во-первых, вот один (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([_|_]). 

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

+0

Спасибо! Я использовал второй вариант и заменил 'is_list (L)' на '(L == []; L = [_ | _])', как и вы, для M, поскольку 'is_list/1' недоступен в GNU Prolog , Очень признателен! – sentinel

+0

Ха-ха, кричит! Я рад, что смогу помочь. Я отредактирую определение второго предложения об удалении 'is_list/1', поскольку я намерен опустить любые встроенные модули. Ура! – sharky

Смежные вопросы