Comment faire pour supprimer le dernier élément d'une liste dans le Prologue?
Je suis dans la situation suivante: j'ai une liste et je voudrais en supprimer uniquement le dernier élément.
J'ai appliquer la règle suivante (qui ne fonctionnent pas bien):
deleteLastElement([Only],WithoutLast) :-
!,
delete([Only],Only,WithoutLast).
deleteLastElement([_|Tail],WithoutLast) :-
!,
deleteLastElement(Tail,WithoutLast).
Le problème est que lorsque je l'appelle, tous les éléments de la liste sont supprimés, en fait, si j'ai exécutez l'instruction suivante-je obtenir:
[debug] ?- deleteLastElement([a,b,c], List).
List = [].
À la recherche à la trace je pense que c'est clairement la cause de ce problème:
[trace] ?- deleteLastElement([a,b], List).
Call: (7) deleteLastElement([a, b], _G396) ? creep
Call: (8) deleteLastElement([b], _G396) ? creep
Call: (9) lists:delete([b], b, _G396) ? creep
Exit: (9) lists:delete([b], b, []) ? creep
Exit: (8) deleteLastElement([b], []) ? creep
Exit: (7) deleteLastElement([a, b], []) ? creep
List = [].
Lorsque le cas de base est atteint, le WithoutLast liste est unifié avec le liste vide [] et lors de la mandature est effectuée la WithoutLast toujours de la liste vide.
Ce n'est pas bon.
Je pensais à le mettre en œuvre en faisant l'opération suivante:
- De compter le nombre d'élément dans la liste avant d'appeler la fonction qui supprime le dernier élément.
- Itérer par récurrence et de décrémenter la valeur du nombre d'élément à chaque fois
- S'il est vrai que le nombre d'élément est 0, cela signifie que c'est le dernier élément, donc je l'ai supprimer de la liste originale
Mais cela ne me paraît pas clair, et ne pas bon, je voudrais savoir si il existe un déclarative bonne solution pour ce problème.
Vous devez vous connecter pour publier un commentaire.
Pour empêcher la création de l'inutile choicepoints, utilisez la traîne de bénéficier de premier argument de l'indexation:
Exemples de requêtes:
L'autre sens?
Que sur les plus générales de la requête?
Je trouve ton analyse un peu trop complexe. Commençons par le cas de base:
Lorsque vous êtes sur le dernier élément, le résultat devrait être la liste vide.
Inductif cas doit donc être le cas où nous ne sommes pas au dernier élément. Dans le cas où j'ai quelques élément attaché à arbitrairement une longue liste, celle-ci sans le dernier élément est juste la queue de la liste sans le dernier élément avec l'élément en cours sur le devant. Ou:
Cela fonctionne dans tous les sens.
Si vous développez une procédure récursive, qui passe par chaque élément de la liste de saisie, de votre base de cas, arrêtez-vous quand vous trouver le dernier élément unificateur de la liste avec la liste vide. Ensuite, de retour de l'appel récursif vous venez d'ajouter tout autre élément à la liste:
Sans l'aide de la coupe:
La première clause (cas de base) unifie le deuxième argument avec la liste vide quand il n'est qu'un élément de la première liste d'arguments.
Le deuxième alinéa précise que lorsque le premier argument est une liste comportant au moins deux éléments, alors vous récursive s'appeler lui-même (sans la tête), un complément à la Tête de la deuxième argument retourné par l'appel.
En fait, vous n'avez pas besoin de rendre explicite dans le deuxième paragraphe que la liste doit comporter au moins deux éléments,
Et, bien sûr, vous pouvez également utiliser
append/3
pour supprimer le dernier élément d'une liste:@répéter la mise en œuvre est certainement la plus efficace, avec l'actuel Prologue de processeurs, encore, je tiens à utiliser DCGs pour cela, espérant secrètement qu'un jour, la mise en œuvre de la technologie sera assez bon pour courir avec cette comparables (de l'espace) de l'efficacité.