Correspondance Schröder (1)

Série d'exercices

Cet exercice fait partie d'une série :

Généralités

On rappelle qu'un arbre est dit :

  • enraciné : s'il possède au moins un nœud ; la racine
  • sans étiquette : les nœuds ne portent pas ici d'identifiant ni de valeurs
  • ordonné : l'ordre de ses sous-arbres compte

Dans ce cas, un arbre peut être modélisé avec une liste Python :

  • Une feuille (un nœud externe) sera représentée par une liste vide [] ; la liste de ses sous-arbres est vide.
  • Un nœud interne sera représenté par la liste de ses sous-arbres donnés dans l'ordre.
  • Un arbre sera donné par la représentation de sa racine.

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 :

  • un nœud externe (une feuille) ne possède aucun sous-arbre ; (classique)
  • un nœud interne 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.

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)]
###(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 : 10/10
.128013:pbv(40i2edxm3s7= 1o5w_lSnatf-)9h]6,crg.[yPku8/050l0k0C0B0i0y0p0s0L0y0B0p0p0r010C0i0c010406050p0T0n0n0B0M0Q040z0u0y0T0:0u0A050V0`0|0~100^0c04191g051j0V1j1l1g0^0l0i0e0(0*0,0.0H0i0N0H0y1z0H0C0?050Z0d0y0k1u0+0-011y1A1C1A0C1I1K1G0C0d0u0l101H0M1h0C0H0(130p0c0B0A0.0j011M1w010D0#0k0A0B0n0k1G1.1:1^1O1{1K1~200?0a0s0R0M0u0c0u0p0i160A0s0X1,0M0M0k0L2l19230A1h0V1*2y0C1(1%1)0l250.1C0A1}2i1G1r1t0)1N2I0i2K0A1!1s1G0c2r1h2w2y2$0_1/2m2Q1_2V0M0}0y0?0s0t2v2*0@2)242,1O2.2:2=0j2^1:2`2w2H012 0B2;040s0o332x0^362}0.393b0s0g3f352*373l2=0v3p3h3r3j380u2/3a2=0J3w2{2+1v2~3B303c0q3G3i3J3k3L3D3c0U3P3y3R3A3C3m0G3X2|3Z3t040t0h3(3I2R3!3M0t2@1a2_3x3)3;3+0t323_343{3:2-3T3b0t3e413g3H3s460?0t3o4a3q3|453#4f3v4i434d4m3,3F4i1i2!192O2B0l2F370L1!211h4z1k4x2(4v4E0X2#3Y3;0S0?0X0D3p4c3z0w2=4W3Q3}0D0?0~0d2r0x0e0k0M0p0x0L0H0k0n2T4#4Q1_0=040f4{4k2~4)0M4+0k51441O4~0F0b3w0s5f0s4X3Z4S044U58374Z3c5n3z0A4(041/0M4E0T4:0x2Z0k1{0m574v4$4}0?505H4|53044*2r5r3Z4~0K3p5h5I5O4?4^4`5M520.5b5d4p5g5-5X5N3k0?0i5B2r4_4/5W5i3;0u0?0r5{5Y0.4_0?3.5,5.5f5|2-5=0x0X0M0A0i5`4i5/5(015~04606j6a2~0d0?285S3;4~5L2(623854566w5J040F615:6m0?0E6J6l643,5e686k590.5k0D3B6O6V6C040i6F5a0?5V6q6B0A0?0p0u0T4;5Q5G2$6U370u5p5$6`6r3k6t041}0{4/0B0C6_2_71016y6)5;5P555R5%6#5*6S6T5g7c5k0i4V6-6K6/6%6!6|5 6p706.6c5C5_0M7f7d0?5+2$067o7o7c7w5!4_187k7z040O7I7w0B0c0c1}0l7I6y6z7b6B6Q3^6A6K5U7y3z7/7*0?0F6I677O6{3z5k0k1C7t7C7v5=7@3Z6n0r7B2_803*6c6e6g6i7;6l4~7L3`7 687Q0?7S6 7-6K6n7Y7V5s4)7$7(7`4 7,347c7_8A5T6+895}6M7I8K8l7l7{7}7M8q8f4R0?830p7a8I6B8n7n8Y8Z6b048u7U8T7W8z8?8B5P8D0A7)8L6x5K8H2x8J0i0?408_8M046,866P95046698906H8W8p8q8s5v0~5y5A5C5E8(938*5K7Z6:6=6@7i9u4P8m8N7u6l7R4@7T8F9k427N7p7D8:9K8v348.1O8b8O6G0P0I8,9n5w9q4;9s0i5F8F929E6#7!9C8F9b8e9n8;9M9%6B5k2r0C5z8=9`9R9|4p194N0k2y5C2y4I2z4B192C2B1Z1#2B0B1Jab4y1s2`0V0X0Z0#0p04.
Indice 1

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.

Indice 2

On pourra compléter le code suivant

🐍 Script Python
def arbre_vers_chemin(arbre):
    def parcours_prefixe(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_prefixe(..., chemin)

    chemin = []
    parcours_prefixe(arbre, chemin)
    return chemin