[remue-cervelle] arbre dont les noeuds connaissent leur parent -SOLUCE

arbre dont les noeuds connaissent leur parent -SOLUCE [remue-cervelle] - Divers - Programmation

Marsh Posté le 26-02-2003 à 00:28:54    

Voilà, au cours d'un diner, un pote m'a lancé un petit défit (que l'écriture d'un compilo lui a inspiré).
 
On a un arbre (binaire, pour pas se faire chier), qu'on va transformer en un autre arbre (au cours d'une passe de compilation par ex.).
Bien entendu, sur aucun des 2 arbres on a d'accesseur en écriture.
On a uniquement des constructeurs et des accesseurs en lecture pour les noeuds et les feuilles.
Dans le nouvel arbre construit, on a une référence dans chaque noeud à son noeud parent (à l'exception de la racine).
Il n'est pas question de filer une référence à quelqu'un sur un objet qui n'est pas dans un état respectant l'invariant (en gros pas question de tenter de finir la construction plus tard, sinon violation de l'invariant).
 
Vous pouvez supposer que l'arbre de départ possède déjà des pointeurs vers le parent (mais ça ne vous servira probablement pas).
 
Hint : il n'est pas sûr que tous les langages permettent de le faire, je l'ai fait en Objective Caml, mon pote en Smalltalk, ça doit être faisable, en en chiant un peu, en C++, C# et java ; ruby et python devraient aller.
 
Note : non, c'est pas mon devoir, je suis pas sûr que mes profs seraient capables de faire ça.
 
edit : la question est bien entendu d'écrire le code construisant le nouvel arbre à partir de l'ancien.


Message édité par nraynaud le 27-02-2003 à 22:59:32
Reply

Marsh Posté le 26-02-2003 à 00:28:54   

Reply

Marsh Posté le 26-02-2003 à 00:57:15    

Et c'est quoi la question ?

Reply

Marsh Posté le 26-02-2003 à 06:45:42    

moi je dirais plutot au cour d(un cours (non d un diner) un prof (et non un ami) a lancé un devoir ...

Reply

Marsh Posté le 26-02-2003 à 08:54:33    

tu t'éclates pendant tes diners entre potes toi [:kunks]


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 26-02-2003 à 08:55:08    

Sérieusement, tu t'estimes meilleur que t profs !?

Reply

Marsh Posté le 26-02-2003 à 09:05:46    

[:cupra]
 
En fait, la solution à ton problème est très simple !
 
Tu créé un pointeur pour chaque référence d'accesseur présent dans chaque branche de l'arbre. Ceci te permet de créér une classe virtuelle qui te permettra de créer unc copie bit à bit de la branche ne possédant pas de fils et ainsi de passer outre les règles de polymorphisme propre à la POO, en faisant du pseudo-procédural de la manière la plus simple qui soit.
 
Tu vas me dire que l'utilisation de classes et méthodes virtuelles ne permettra pas d'hériter directement du noeud fils, étant donné que le fait de déclarer des classes amies casse toute la structure objet de ton arbre, ceci étant provoqué par un unboxing bourrin des variables membres de la classe associée (qui dérive bien évidemment de la classe abstraite créée précédemment). Mais tu oublies que l'utilisation d'interfaces te permet d'appliquer toutes les règles de polymorphisme définies plus haut comme s'il s'agissait de classes abstraites définies normalement.
 
La prochaine fois, pose des questions plus compliquées ! Y'a longtemps que je ne suis plus en 6ème :)
 
:hello:


---------------
Je code en série et en parallèle
Reply

Marsh Posté le 26-02-2003 à 09:08:00    


 
mouais moyen ce coup ci, fodrait voir a t'entrainer tu perds la main :O

Reply

Marsh Posté le 26-02-2003 à 09:09:39    

chrisbk a écrit :


 
mouais moyen ce coup ci, fodrait voir a t'entrainer tu perds la main :O


normal, je suis prof !


---------------
Je code en série et en parallèle
Reply

Marsh Posté le 26-02-2003 à 13:42:48    

AsPHrO a écrit :

moi je dirais plutot au cour d(un cours (non d un diner) un prof (et non un ami) a lancé un devoir ...


Le pire c'est que t'es pas loin de la réalité, le pote en question est un ancien intervenant avec qui on va se prendre une mine et parler info une fois de temps-en-temps.

Reply

Marsh Posté le 26-02-2003 à 13:48:24    

nraynaud a écrit :


Le pire c'est que t'es pas loin de la réalité, le pote en question est un ancien intervenant avec qui on va se prendre une mine et parler info une fois de temps-en-temps.
 


ca explique le sujet que tu proposes alors  :D

Reply

Marsh Posté le 26-02-2003 à 13:48:24   

Reply

Marsh Posté le 26-02-2003 à 14:03:12    

gloop a écrit :


ca explique le sujet que tu proposes alors  :D  


Ceci-dit, c'est un problème qu'on rencontre super-souvent en compilation, voir en info en général. La technique classique consiste à pêter le contrat et à ne renseigner soit les enfant soit le parent d'abord et l'autre enssuite. Mais c'est mal.

Reply

Marsh Posté le 26-02-2003 à 14:06:33    

nraynaud a écrit :

Mais c'est mal.

mais c'est simple et ca marche :o

Reply

Marsh Posté le 26-02-2003 à 14:07:23    

lorill a écrit :

mais c'est simple et ca marche :o


un temps

Reply

Marsh Posté le 26-02-2003 à 15:01:18    


 
de toute facon tout est voue  l'echec dans cette vallee de larmes :O

Reply

Marsh Posté le 27-02-2003 à 22:49:17    

La soluce repose tout simplement sur la fainéantise. (j'aime bien dire ça, ça sous-entend que c'est évident, alors que si on m'avait pas mis sur la voie, je serais encore en train de chercher).
 

Code :
  1. (* arbre de départ *)
  2. type 'a ltree = LLeaf of 'a | LNode of 'a ltree * 'a ltree
  3. (* arbre d'arrivée *)
  4. (* solution à parent lazy, enfants lazy ou tout le monde lazy possible *)
  5. type 'a rtree = RRoot of 'a rtree | RNode of 'a rtree * 'a rtree * 'a rtree Lazy.t | RLeaf of 'a * 'a rtree Lazy.t
  6. let lexemple =
  7. LNode(
  8. LNode(
  9.   LNode(LLeaf(20), LLeaf(10)),
  10.   LNode(LLeaf(10), LNode(LLeaf(14), LLeaf(10)))),
  11. LNode(LLeaf(30), LLeaf(53))
  12. )
  13. let convert t =
  14.   let rec root = lazy(RRoot(tree t))
  15.   and tree t' = go root t'
  16.   and go pn = function
  17.     | LLeaf(v) -> RLeaf(v, pn)
  18.     | LNode(f, s) ->
  19.       let rec top = lazy (RNode(lson f, rson s, pn)) (* l'image du noeud *)
  20.       and lson f' = go top f' (* l'image de son fils gauche *)
  21.       and rson s' = go top s' (* l'image de son fils droit *)
  22.       in Lazy.force top
  23.   in Lazy.force root
  24. (* explosons l'affichage du toplevel ! *)
  25. let r = convert lexemple
  26. (*
  27. comme marqué dans
  28. http://caml.inria.fr/ocaml/htmlman [...] s:localdef (dernière ligne)
  29. Caml sait pas faire grand'chose en récursif indirect pour les valeur non-fonctionelles.
  30. en Haskell, la notation est plus proche de (pour les premières lignes) :
  31. let convert t =
  32.   let rec root = lazy(RRoot(tree))
  33.   and tree = go root t
  34. ben tant pis.
  35. *)


 
Pour ceux qui ne conaissent pas le lazy, c'est une expression stockée sous forme non évaluée.
notation :

lazy (expression)

)
 elle ne sera évaluée que si c'est nécessaire (par Lazy.force).

'a Lazy.t

est en fait le type

unit -> 'a

(une fonction qui prend l'unité () en paramètre et qui renvoie un 'a)

Lazy.force <expression>


est l'équivalent de  

(<expression> ())


passer l'unité en paramètre à la fonction (donc l'évaluer).
et  

lazy (<epression> )

 
est transformé syntaxiquement (grace à camlp4) en  

(fun () -> <expression> )


 
Voilou.


Message édité par nraynaud le 27-02-2003 à 22:53:01
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed