2010-10-05 3 views
0

Je suis en train d'écrire un prédicat qui la liste suivante en Prolog:inverse personnalisée d'une liste dans Prolog

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

produira la liste suivante:

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

Comme vous pouvez le voir, je Je voudrais préserver l'ordre des éléments au niveau le plus bas, pour produire des éléments dans l'ordre 1, a, b et NOT b, a, 1.

Je voudrais également préserver la profondeur des listes, que est, les listes qui sont origi nally nested sont retournés en tant que tels, mais dans l'ordre inverse.

J'ai réussi à obtenir l'ordre désiré avec le code suivant, mais la profondeur est perdue, à savoir les listes ne sont plus correctement imbriquées:

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

Je vous serais reconnaissant de l'aide pour corriger le code pour préserver le bon imbrication de listes. Merci!

Répondre

0

Deux suggestions. Tout d'abord, voici un (rev_lists/2) qui utilise un tas de SWI-Prolog Encastrements:

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

Celui-ci fonctionne en testant si tous les éléments d'une liste L sont eux-mêmes des listes (M); si c'est le cas, il s'appliquera récursivement lui-même (via maplist) sur toutes les sous-listes individuelles, sinon il retournera la même liste. Cela a l'effet requis.

En second lieu, voici rev_lists/2 à nouveau, mais écrit de telle sorte qu'elle ne repose pas sur Encastrements sauf member/2 (qui est commun):

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([_|_]). 

Il est fondamentalement la même stratégie, mais utilise un accumulateur pour construire des listes inversées à chaque niveau, si elles sont composées exclusivement de listes; sinon, la même liste est renvoyée.

+0

Merci! J'ai utilisé la deuxième variante et remplacé 'is_list (L)' par '(L == []; L = [_ | _])', comme vous l'avez fait pour M, car 'is_list/1' est indisponible dans GNU Prolog . Très appréciée! – sentinel

+0

Haha, whoops! Je suis heureux d'avoir pu aider. Je vais éditer la définition de la deuxième suggestion pour supprimer 'is_list/1', car c'était mon intention d'omettre les built-ins. À votre santé! – sharky