2012-04-10 7 views
2

J'ai un problème avec mon code prolog. J'ai besoin d'inverser tous les éléments atomiques de la liste.Inverser la liste des listes

Exemple: [1,2, [3,4]] -> [[4,3], 2,1]

Ma solution:

myReverse([], []). 
myReverse([H|T], X) :- myReverse(T, RT), myAppend(RT, H, X). 

Mais il me donne seulement: [[3,4], 2,1] Je pense, je dois utiliser la fonction is_list et la liste d'appels récursifs si ce n'est pas atomique ... mais je suis coincé ... les gars savez-vous comment l'écrire?

+0

Quoi 'SPOJ/3'? Je suis familier avec SPhere Online Judge, mais quand il s'agit de Prolog, je suis perdu ... – dasblinkenlight

+0

Je l'ai renommé myAppend, la fonction joindre deux listes et enregistrer le résultat à X. – nich

Répondre

3

Presque. Considérez cette solution:

myReverse([], []) :- !. 

myReverse([H|T], X) :- 
    !, 
    myReverse(H, NewH), 
    myReverse(T, NewT), 
    append(NewT, [NewH], X). 

myReverse(X, X). 

La première clause est le cas de base, qui comprend une coupe (!) pour exclure les choix laissés à cause de la dernière clause.

La deuxième clause inverse la tête H, qui peut être un atome ou une liste. Si H est un atome, le sous-objectif récursif après la coupe est évalué avec la dernière clause, et les atomes sont passés inchangés. Si H est une liste, elle est évaluée avec la deuxième clause et tous les éléments sont inversés. Le sous-objectif suivant fait la même chose avec le reste de la liste (la queue, T), puis sont finalement concaténés en utilisant le append/3 intégré. Notez que le nouvel élément de tête NewH est singulier, il doit donc être ajouté à une structure de liste singleton comme [NewH] selon la définition de append/3 qui fonctionne sur des listes. La dernière clause passe toutes les autres choses (c'est-à-dire, les atomes, les nombres, etc. - tout ce qui n'est pas une liste ou une variable) à travers inchangée.

2
revall(L, Y) :- 
    revall(L, [], Y). 
revall([], Y, Y). 
revall([H|T], T2, Y) :- 
    is_list(H),!, 
    revall(H, Hr), 
    revall(T, [Hr|T2], Y). 
revall([H|T], T2, Y) :- 
    revall(T, [H|T2], Y). 

ici sans append

+2

+1: Ceci est un bon accumulateur version et utiliserait moins d'espace de pile comme la version que j'ai proposée (qui n'est pas récursive). Vous pouvez même remplacer l'appel 'is_list/1' (et laisser la coupure) si vous avez utilisé pattern-matching à la place en changeant' H' à '[H | Hs]' tout au long de la deuxième clause de 'revall/3', alors non built-ins serait nécessaire du tout. – sharky