Aller au contenu

Correspondance de Schröder

😀 On considère ici des arbres non étiquetés et ordonnés.

Arbres de Schröder

Un arbre de Schröder est un arbre enraciné ordonné sans étiquette, ayant la propriété suivante :

un nœud ne possède jamais un unique sous-arbre ; soit aucun, soit au moins deux sous-arbres.

Ainsi, pour un arbre de Schröder :

  • Une feuille ne possède aucun sous-arbre ; (classique)
  • Sinon, un nœud possède au moins deux sous-arbres ; (particularité)

Exemples

est représenté en interne avec [[[], []], [], []]

est représenté en interne interne avec [[], [[], []], []]

⚠ Les deux arbres ci-dessus sont différents, d'où la qualification ordonné.

est représenté en interne avec [[], [[], [[], []], [], [], []], []]

Correspondance de Schröder

Pour un arbre de Schröder, on effectue un parcours préfixe et pour chaque nœud rencontré hormis la racine, on ajoute une étape à un chemin sur une grille qui part de l'origine :

  • ↗, codée \((1, 1)\), si le nœud est le plus à gauche (parmi ceux de son ancêtre direct)
  • ↘, codée \((1, -1)\), si le nœud est le plus à droite (parmi ceux de son ancêtre direct)
  • →→, codée \((2, 0)\), sinon.

Exercice

L'objectif de l'exercice est de construire une fonction telle que arbre_vers_chemin(arbre) renvoie la description du chemin de l'arbre de Schröder passé en paramètre.

Exemples

donne

🐍 Console Python
>>> arbre_vers_chemin([[[], []], [], []])
[(1, 1), (1, 1), (1, -1), (2, 0), (1, -1)]

donne

🐍 Console Python
>>> arbre_vers_chemin([[], [[], []], []])
[(1, 1), (2, 0), (1, 1), (1, -1), (1, -1)]

donne

🐍 Console Python
>>> arbre_vers_chemin([[], [[], [[], []], [], [], []], []])
[(1, 1), (2, 0), (1, 1), (2, 0), (1, 1), (1, -1), (2, 0), (2, 0), (1, -1), (1, -1)]
Indice

En réalisant le parcours préfixe, pour chaque nœud, on veillera à identifier le premier et le dernier sous-arbre. Pour cela, on pourra obtenir d'abord le nombre de sous-arbres, puis en itérant, savoir s'il s'agit du premier, du dernier ou un autre cas.

Guide
🐍 Script Python
def arbre_vers_chemin(arbre):
    def parcours_préfixe(arbre, chemin):
        i_premier = 0
        i_dernier = ...
        for i, sous_arbre in enumerate(arbre):
            if i == i_premier:
                chemin.append(...)
            elif i == i_dernier:
                ...
            else:
                ...
            parcours_préfixe(..., chemin)

    chemin = []
    parcours_préfixe(arbre, chemin)
    return chemin

🥚 easter egg

Si vous résolvez cet exercice, vous aurez accès à un exercice caché : reconstruire un arbre avec le procédé inverse ; c'est bien plus délicat à implémenter.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : /
.128013.129370x/.r;nbylaeu)dV63öm(P02è-],59fq7B8 _o=pcwgv41kRéhtsSàC[i:050p0m0Z0l0)0k0!0K0P0k0l0!0!0N010Z0)0O010406050!0n0u0u0l0f0j040#0M0k0n0~0M0h0K020l0u0O0g0K0W0m180f0G0n0m0!050d1517191b130O04051G1z1J0d1G130p0)0S0?0^0`0|0Y0)0R0Y0k1X0Y0Z11050.0i0k0m1S0_0{011W1Y1!1Y0Z1*1,1(0Z0f1H0Z0Y1.1U010F0:0m0h1m0m010?1e0!0O0l0h0|0y1(2e2g221:251,280u2a040a0K0w0f0M0O0M0!0)1h1j0,2c0f0f0m0P2E1z2l0h1H0d202Q1}1 1~1)0p2n0|1!0h272B1(1P1R0@1/2!0)2$0h0M2*1(0O2J1H2O2Q2{142f1j2,232;0f180k110K0U2N2 122~2m311:3335370y3a2g3c2O2Z013h0l36040K0s3l2P133o3f0|3r3t0K0T3x3n2 3p3D370D3H3z3J3B3q0M343s370r3O3d301T3g3T3i3u0H3Y3A3#3C3%3V3u0J3+3Q3-3S3U3E0E3?3e3^3L040U0x3}3!2-3_3(0U391A3b3P3~46400U3k4b3m4d45323/3t0U3w4j3y3Z3K4o110U3G4s3I4e4n3`4x3N4A4l4v4E413X4H4u3R4g3*4N3,4f4w413=4A1K2_1z2*2T0p1 2Y3R0P2=2t0+1Q1H2^0m2`3b3H054,0,4@4C1:0V110,0F4_4T230Q37543@4f0F11190i2J0L0S0m0f0!0L0P0Y1s2/594~0|10040v5r4m3g5d0f5f0m5x3p5u0o0*3O0K5K0K4O3^0!2j04010%3T2J2e1i0p2g0P1-2G0#0Y0f0t0,0f013O065L5M554 510m534Y5=0|573u5E4P5c042f0f4,0n5k0L2^0X250c5D5`5a235u5w6e5s3q5A5C5 3^5u0C3H5;6f5z045n5p0h6o465G5I4H5:5:5N4f110)682J0u0)5j6s6H230M110N6Q5{016N11436E6F5K6R6v6K5+0h6O0f6W6u0|6T046V4A6t6k0h0i112q6A6g116i2}6X0h6m2J701:5G6:6k6?0A7c5y0|6Z415J6%6`7h0150040F3T7g3K6J795t116r6_6)3C110!0M0n5l5e787B6X0M5}5q7L6;3q6}0427165j0l0Z6d747R6h7x6l047J7!4^6X6C7l7m5L7C7p6J5_2{7n7v040)7u3R6?0N6^7`7?767}6L5p6P6j7o5u6D2{5/7;7m85116x6N6z8b3p6?0e7(860l0O0O270p7(6h737-7R7j4a7#6k6q7 3^8E8z110o0o7:8h7?7q0m1!7_3b7{4P7w7Q7d6U838X8j876,6.8M048e4c8h8i758k5o8m7(8q8s5d8v8x8.0v8B3m7?8L8o3R8I8#7o7e7(968G8c8N8P6$8=8S118U0!7,947.118:4k8=6%8*8l7P9f8p118r973 8~8w0h8y9E6B72932P950)114i9A987z8J467j6#9T6p9h8Q7;8*636567696b9p9O9r5v8}047F7H0L7+8.7A848@6w8_9z8C8H8N5.6G9 9y8n9~7R819W71040(0B8Q9)199+5l9-0)6c919?9{9Kaf9}8)a8a1aaa39g049i8fa77R7q2J0Z66aA3m8Y9Fa06y3Y0d4{4?4ZaV0d4$1z0Z4(a!2W2R0l1+aX4$1F4}7o6M0L0F0l0V0m0L0Y0s111r1t1v1x0K9t9O1M3c2*3p0l0p0u1i2D0)1i0K0!0l0S0M0)5,3c0Ob8babc2E0A0~0Z1{040I0fbi0M0K0b1Kbn040q7G0=0l0P0P0z0=0$0K0k000m6c640)5!0?bK0Y0X5M0l0K5(5^0|0e0e0d0H0E0A0#5n2y5+0L0y5m0M1n1,6c0d11b=5(5*5j0K4i0l049D1N4#4:13aY0-0/0;04.