IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Lisp Discussion :

Double récursion liste


Sujet :

Lisp

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre du Club
    Inscrit en
    Septembre 2008
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 8
    Par défaut Double récursion liste
    Bonjour Tout le monde
    Je suis confronté à un problème concernant la double récursion sur une liste.

    Je dois créer une fonction qui renvoie la dernière occurence d'une lettre qu'on recherche suivie du reste de la liste.
    For example:

    (function 'z '((a z)c d))
    (Z)


    (function 'x '((a (x x)) x c x d e))
    (x d e)

    La logique de mon développement est la suivante.
    Je regarde si l'élément recherché figure dans (last liste), et si c'est le cas je renvoie la bonne réponse;

    Mais si c pas le cas que fais je?
    Comment parcourir la liste dans l'autre sens(Existe t'il une fonction qui renvoie previous d'un élément d'une liste, ou je dois la créer)?

    Voilà j'espère avoir été clair. Je pense que je dois utiliser la double récursion pour résoudre ce problème, mais je suis toujours dans le brouillard.

    Merci de votre aide

  2. #2
    Inactif  
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 958
    Détails du profil
    Informations personnelles :
    Âge : 60
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 958
    Par défaut
    Citation Envoyé par jahol Voir le message
    Bonjour Tout le monde[...]
    Salut,

    Bon avant tout, il y a une balise code à utiliser pour présenter du code.
    Ensuite, ton problème est d'ordre algorithmique et non de l'ordre de la mise en pratique en lisp. Car visiblement, tu n'as pas trouvé la réponse.

    Citation Envoyé par jahol Voir le message
    Je regarde si l'élément recherché figure dans (last liste), et si c'est le cas je renvoie la bonne réponse;
    Pas exactement: tu regardes s'il y a une réponse dans la suite de la liste. Pas juste si l'élément y est. Mais il te manque des morceaux (cf. après).

    Citation Envoyé par jahol Voir le message
    Mais si c pas le cas que fais je?
    Comment parcourir la liste dans l'autre sens(Existe t'il une fonction qui renvoie previous d'un élément d'une liste, ou je dois la créer)?
    C'est là ton erreur: ta fonction ne commence pas en plein milieu de la liste mais au début.

    Il manque un morceau dans l'étape qui tu avais trouvé. Notamment tu sembles ignorer complètement la cellule de tête de ta liste. Comment espères-tu trouver quoique ce soit ?

    Il faut donc que tu te demandes quoi faire, en fonction de la cellule de tête. Si elle contient la valeur recherché, que fais-tu ?
    Et sinon, que fais-tu ?

    Là tu as deux cas exhaustif. Dans le « que fais-tu ? » tu utiliseras la queue de ta liste.

    Réfléchis à ça, et reviens nous voir en cas de besoin.

  3. #3
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 103
    Par défaut
    Citation Envoyé par jahol Voir le message
    Bonjour Tout le monde
    Je suis confronté à un problème concernant la double récursion sur une liste.

    Je dois créer une fonction qui renvoie la dernière occurence d'une lettre qu'on recherche suivie du reste de la liste.
    For example:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    (function 'z '((a z)c d))
    (Z)
     
     
    (function 'x '((a (x x)) x c x d e))
    (x d e)
    La logique de mon développement est la suivante.
    Je regarde si l'élément recherché figure dans (last liste), et si c'est le cas je renvoie la bonne réponse;

    Mais si c pas le cas que fais je?
    Comment parcourir la liste dans l'autre sens(Existe t'il une fonction qui renvoie previous d'un élément d'une liste, ou je dois la créer)?

    Voilà j'espère avoir été clair. Je pense que je dois utiliser la double récursion pour résoudre ce problème, mais je suis toujours dans le brouillard.

    Merci de votre aide
    Bonjour,

    est-ce que tu peux expliciter la logique (ou les spécifications de la fonction)?

    Pourquoi est-ce que (x d e) est plus que (x x) la dernière occurrence de x dans ((a (x x)) x c x d e)?
    Car on pourrait dire que (x x) est plus en queue, car de longueur 2, que (x d e) qui est de longueur 3 !

    Tes exemples semblent indiquer que la "liste" à explorer est en fait plus un arbre qu'une liste. (pour moi, une liste est plutôt une séquence d'éléments (tous plus ou moins du même type), alors qu'un arbre est plutôt un groupe de noeuds, branches et feuilles raccordés ensemble).

    Du coup, tu peux t'interroger sur la manière de parcourir cet arbre.


    Sinon, une manière "simple" de résoudre un problème par récurrence est la suivante:

    imagine que tu possèdes déjà une fonction "foo" qui soit capable de trouver la dernière occurrence d'un élément dans un arbre.
    Comment pourrais-tu créer une nouvelle fonction "bar" pour trouver la dernière occurrence d'un élément dans un arbre en te servant de "foo", mais évidemment sans la triviale implémentation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (defun bar (x arbre) (foo x arbre))
    Bonne continuation

    )jack(

  4. #4
    Membre du Club
    Inscrit en
    Septembre 2008
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 8
    Par défaut
    Salut Garulfo et jack-t et Merci.

    J'ai essayé de pousser un tout p'tit peu la réflexion avec votre aide.
    J'utilise bien une liste (qui peut etre représentée sous forme d'arbre binaire !).

    @Jack-t la spécifications de la fonction est de trouver la dernière occurence d'un élément recherché dans une liste ainsi que le reste de la liste.


    J'ai une solution qui (je reconnais) n'est pas optimale:
    Je regarde si l'élément recherché est présent en début de liste, si c'est le cas je vérifie sa présence dans le reste de la liste.
    Que fais je?
    - Si l'élement recherché est trouvé et n'est pas présent dans le reste de la liste , alors je construis la liste finale(résultat).
    - Si ce dernier est présent , je rappelle la fonction.

    Etant donné que c'est la dernière occurence qui m'interesse, je commence par executer le reste de la liste. Si je n'ai aucun résultat ,j'execute le début de la liste.

    Solution non optimale parce qu'il y a une partie du code qui est executée deux fois.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    (defun f1 (x l)
                       (cond 
                          ((endp l) '())
                          ((atom (first l))
                           (if (eq x (first l))
                               (if (member x (rest l))
                                   (f1 x (rest l))
                                   (cons x (rest l))
                                   )
                               (f1 x (rest l))))
                        ((eq (f1 x (rest l)) nil) (f1 x (first l)))
                        (t (f1 x (rest l)))))
     
    (defun F2 (x l)
      (let ((rep (f1 x l)))
      (if (eq rep nil) 
          l
          rep)
        )
      )

  5. #5
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Vu les exemples du premier post et le code du précédent, il me semble plutôt que la spécification serait:
    Renvoyer le plus petit sous-arbre d'un arbre binaire (l) contenant la dernière occurrence d'un atome donné (x) dans un parcours ordonné de cet arbre (ou l'arbre complet si l'atome n'y figure pas (cf. fonction f2)).

    Si c'est bien ça, il me semble que le test "member x (rest l)" est non seulement inutile, mais incorrect, car il ne trouverait pas les occurrences de x dans les sous-arbres de gauches de (rest l).

    Etant moi-même débutant en LISP, je propose ceci, mais je ne sais pas si cette utilisation assez idiomatique de AND et OR est conseillée en pratique:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    (defun f1 (x l)
      (and l
           (or (f1 x (cdr l))
    	   (if (atom (car l))
    	       (if (eql x (car l)) l)
    	       (f1 x (car l))))))
     
    (defun f2 (x l)
      (or (f1 x l) l))

  6. #6
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 103
    Par défaut
    Citation Envoyé par jahol Voir le message
    Salut Garulfo et jack-t et Merci.

    J'ai essayé de pousser un tout p'tit peu la réflexion avec votre aide.
    J'utilise bien une liste (qui peut etre représentée sous forme d'arbre binaire !).

    @Jack-t la spécifications de la fonction est de trouver la dernière occurence d'un élément recherché dans une liste ainsi que le reste de la liste.
    Bonjour,

    si la spécification est bien de trouver la dernière occurrence d'un élément recherché dans une liste (et non un arbre) ainsi que le reste de la liste,
    alors la réponse est vraiment simple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    (defun f1 (x l)
      (member x l)
    Easy, isn't it?

    J'ai une solution qui (je reconnais) n'est pas optimale:
    Je regarde si l'élément recherché est présent en début de liste, si c'est le cas je vérifie sa présence dans le reste de la liste.
    Que fais je?
    - Si l'élement recherché est trouvé et n'est pas présent dans le reste de la liste , alors je construis la liste finale(résultat).
    - Si ce dernier est présent , je rappelle la fonction.

    Etant donné que c'est la dernière occurence qui m'interesse, je commence par executer le reste de la liste. Si je n'ai aucun résultat ,j'execute le début de la liste.
    Je crois que ce serait vraiment plus simple si tu essayais de "penser" et t'exprimer avec un arbre (qui a dit "je préfère un crayon"?).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Un arbre binaire est 
        ou bien une feuille 
        ou bien un noeud (ou racine) avec 
               un arbre gauche 
            et un arbre droit.
    Parfois l'arbre binaire peut être simplifié et ne contient pas vraiment de racine.

    Solution non optimale parce qu'il y a une partie du code qui est executée deux fois.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    (defun f1 (x l)
                       (cond 
                          ((endp l) '())
                          ((atom (first l))
                           (if (eq x (first l))
                               (if (member x (rest l))
                                   (f1 x (rest l))
                                   (cons x (rest l))
                                   )
                               (f1 x (rest l))))
                        ((eq (f1 x (rest l)) nil) (f1 x (first l)))
                        (t (f1 x (rest l)))))
     
    (defun F2 (x l)
      (let ((rep (f1 x l)))
      (if (eq rep nil) 
          l
          rep)
        )
      )
    Pourquoi veux-tu retourner l si f1 ne trouve rien?

    Bizarre, cette peur du vide...

    et je suis d'accord avec dividee (voir plus loin).

    Citation Envoyé par dividee Voir le message
    Vu les exemples du premier post et le code du précédent, il me semble plutôt que la spécification serait:
    Renvoyer le plus petit sous-arbre d'un arbre binaire (l) contenant la dernière occurrence d'un atome donné (x) dans un parcours ordonné de cet arbre (ou l'arbre complet si l'atome n'y figure pas (cf. fonction f2)).
    Ah!!!! OUI!

    Je préfère!

    encore que:
    - j'aimerais savoir ce que tu entends par "le plus petit". S'il y a une occurrence quelque part dans le car et une autre dans le cdr, comment définis-tu le plus petit?
    - j'aimerais savoir de quel parcours ordonné il s'agit (j'en connais plusieurs (notamment les 6 classiques: GRD, DRG, RGD, RDG, GDR, DGR (j'ai d'ailleurs un peu de mal à en imaginer d'autres...)))
    - je préfèrerais retourner nil plutôt que l'arbre complet si l'atome n'y figure pas (comme fait la fonction "member") sinon on ne distingue pas bien (f2 'x '(x y)) de (f2 'z '(x y)).

    Si c'est bien ça, il me semble que le test "member x (rest l)" est non seulement inutile, mais incorrect, car il ne trouverait pas les occurrences de x dans les sous-arbres de gauches de (rest l).
    Tout à fait exact, mon cher Watson!

    Etant moi-même débutant en LISP, je propose ceci, mais je ne sais pas si cette utilisation assez idiomatique de AND et OR est conseillée en pratique:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    (defun f1 (x l)
      (and l
           (or (f1 x (cdr l))
    	   (if (atom (car l))
    	       (if (eql x (car l)) l)
    	       (f1 x (car l))))))
     
    (defun f2 (x l)
      (or (f1 x l) l))
    C'est beaucoup mieux et l'usage de "or" dans "f1" me convient tout à fait.

    L'usage du "and" me convient moins bien. Dans ce cas, je prèfére "cond" "when" "unless" ou "if".

    Mais, à mon humble avis, on peut faire encore un petit peu mieux et un peu plus simple...

    As-tu essayé ceci:
    Et ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    (let ((x '(a)))
       (f1 x (list x)))
    Et que disent les specs pour ceci:
    et ceci:
    Encore un petit effort...

    )jack(

  7. #7
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Bonjour jack-ft,

    Oui je me suis embrouillé avec la définition d'un arbre. Comme je suis fainéant je vais essayer de changer la spec plutôt que le code
    J'avais d'abord pensé à un arbre n-aire, mais comme j'avais un peu de mal à formuler ce que devait être la valeur de retour, je suis passé à un arbre binaire, et j'ai perdu quelques plumes au passage.
    En fait, je pensais à l'encodage d'un arbre n-aire en arbre binaire, et à sa représentation sous forme de cons cell, telle qu'indiquée ici.
    Pour le parcours, il n'y a que deux ordres possibles: GD ou DG, vu que la racine ne contient pas d'info. J'aurais du préciser qu'il s'agissait de la dernière occurrence dans un parcours GD (ou de façon équivalente, de la première occurrence dans un parcours DG).

    Donc la spec devient:

    "Rechercher la première occurrence d'un atome donné dans le parcours droite-gauche d'un arbre n-aire de hauteur >=1 donné, et retourner un nouvel arbre n-aire composé d'une racine ayant pour fils l'atome trouvé et ses frères droits (ou NIL si l'atome n'est pas trouvé)."

    Du coup:
    etsortent de la spec car ne correspondent pas à la représentation d'un arbre n-aire.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    (let ((x '(a)))
       (f1 x (list x)))
    Celle-là sortait déjà précédemment de la spec car x n'est pas un atome
    cf. hauteur >=1 dans la spec (oui je sais c'est petit).

    Et voilà, maintenant ce n'est plus le code qui est faux mais l'appelant qui ne respecte pas les préconditions

  8. #8
    Inactif  
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 958
    Détails du profil
    Informations personnelles :
    Âge : 60
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 958
    Par défaut
    Citation Envoyé par jack-ft Voir le message
    [...]
    si la spécification est bien de trouver la dernière occurrence d'un élément recherché dans une liste (et non un arbre) ainsi que le reste de la liste,
    alors la réponse est vraiment simple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    (defun f1 (x l)
      (member x l)
    Easy, isn't it?
    Pas vraiment, car tu oublies que si un prof pose cette question, c'est qu'il veut voir le code faisant ça

    On apprends à coder les fonctions pour les comprendre et comprendre les principes. Après on utilise celle qui existe (et on évite de les recoder pour rien).

    Mais d'après dividee, il semble que la solution soit plutôt une forme de member pour un arbre et non une liste effectivement.

    J'interviendrais bien. Mais il me semble que Jack-ft est bien assez locace et plus de blahblah pourrait t'embrouiller

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [AC-2007] Double filtre liste déroulante
    Par theuma dans le forum Access
    Réponses: 4
    Dernier message: 10/05/2011, 08h06
  2. double clic liste deroulante
    Par Daniela dans le forum VBA Access
    Réponses: 8
    Dernier message: 12/06/2009, 18h05
  3. Réponses: 15
    Dernier message: 28/11/2008, 16h13
  4. Réponses: 16
    Dernier message: 22/05/2006, 10h48
  5. double clic liste
    Par Yukhaa dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 21/02/2006, 16h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo