Arbre généalogique

Un généalogiste amateur décide de représenter ses travaux avec Python.

Arbre généalogique de Carl Gustav Bielke

Etant face à l'arbre généalogique des parents, grands-parents, etc d'un individu, il utilise pour ce faire des arbres binaires représentés ainsi :

  • l'arbre binaire vide est représenté par None ;

  • un arbre binaire non vide est représenté par un tuple de trois éléments (sag, personne, sad) dans lequel :

    • sag est le sous-arbre gauche ;
    • personne est le nom de la personne à la racine de l'arbre ;
    • sad est le sous-arbre droit.

Il suit la convention de la généalogique qui veut que les pères soient placés sur la gauche et les mères sur la droite.

Ainsi l'arbre généalogique de base :

Arbre de base
Pierre         Pauline
    \         /
     \       /
      Jacques

sera représenté en Python par :

Arbre de base en Python
((None, "Pierre", None), "Jacques", (None, "Pauline", None))

Il arrive lors de la construction d'un arbre généalogique que l'on ignore l'ascendance d'une personne : l'arbre est interrompu sur certaines branches et est donc déséquilibré. Par exemple :

Arbre déséquilibré
Pierre      ?    ?         Martine
    \      /      \       /
     \    /        \     /
      Paul          Aline
          \        /
           \      /
            Pierre        ?
                \        /
                 \      /
                  Marion

Dans ce cas, les parents inconnus sont représentés par des arbres vides :

Arbre déséquilibré en Python
((((None, "Pierre", None), "Paul", None), "Pierre", (None, "Aline", (None, "Martine", None))), "Marion", None)

On cherche dans cet exercice à effectuer différents calculs sur des arbres généalogiques.

1. Personnes présentes

Écrire la fonction nb_presents qui prend en paramètre un tuple arbre représentant un arbre généalogique et renvoie le nombre de personnes présentes dans cet arbre.

Exemples
>>> une_gen = (None, "Moi", None)
>>> nb_presents(une_gen)
1
>>> deux_gen = ((None, "Papa", None), "Moi", (None, "Maman", None))
>>> nb_presents(deux_gen)
3
>>> trois_gen = ((None, "Papa", (None, "Mamy P.", None)), "Moi", ((None, "Papy M.", None), "Maman", None))
>>> nb_presents(trois_gen)
5

###(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

.128013ua/(lbw)pgdo kehmf:+v,P1Ssiny0_t54Nr32c=050l0p0G0c0B0f0A0n0N0f0c0A0A0O010G0B0j010406050A0b0r0r0c0K0D040z0m0f0b0)0m0C050d0:0=0@0_0.0j041219051c0d1c1e190.0l0B0v0X0Z0#0%0q0B0k0q0f1s0q0G0,050S0g0f0p1n0!0$011r1t1v1t0G1B1D1z0G0g0m0l0_1A0K1a0G0q0X0|0A0j0c0C0%0M011F1p010s0U0p0C0c0r0p1z1%1)1.1H1;1D1@1_0,0a0n0x0K0m0j0m0A0B0 0C0n0Q1#0K0K0p0N2e121|0C1a0d1Z2r0G1X1W1Y0l1~0%1v0C1?2b1z1k1m0Y1G2B0B2D0C1T1l1z0j2k1a2p2r2V0/1(2f2J1/2O0K0?0f0,0y2o2Z0-2Y1}2#1H2%2)0,0M2-1)2/2p2A012@0c2*040L2{2q0.2~2=0%31330I362}2Z2 3c0,0H3f1b2T122H2u0l2y2 0N1T1`1a3q1d3o2X132.053v0Q2U3h3a010o0,0Q0s3m391o1H0h0,0n3Q3J3S3b0s0,0C0g0F2S0p0A1?0G0A3X2;3Z010+040e3:2!3=0C0,0@0g2k3`2 3@0i0t3f060n493W3R2K3L0,0B3P3D2|4b3Y4d3}043 414i2q4k3;4d0m3U040B3/4r044t3{4d0o0N0,0J100p423K3@464B484a4S2:4E1/3M042k0G0b0K114B4D2 0r0B0,0E474T4c2$0,0A0c0k4M3=3@0w3f4)3K4n0j0p0K0A102D4`4d4|4~4U3i4?0c0l5b4;1H0m0,0O5h4l4=4o0K404L4Q4:5o1H4X4Z4#4%2V4 3=4+2+5n4u1/5k040u5H4V2?3$3(3*3,0C3.581/3@3_4B5c505e4_5!5i0%445N2 5K5M4(5#3|5Q3)2k5T5V5)5w5+0,5Z2X5*305e5g5|5I1H5,4Q123G0p2r3*2r3z2s3s122v2u1S1U2u0c1C6d3p1l2/0d0Q0S0U0A04.
2. Nombre de générations

On définit le nombre de générations d'un arbre généalogique comme le nombre maximal de personnes rencontrées en remontant depuis la racine de l'arbre jusqu'à un ancêtre. Un arbre généalogique ne comptant qu'une seule personne a donc un nombre de génération égal à 1.

Écrire la fonction nb_generations qui prend en paramètre un tuple arbre représentant un arbre généalogique et renvoie sa hauteur.

Exemples
>>> une_gen = (None, "Moi", None)
>>> nb_generations(une_gen)
1
>>> deux_gen = ((None, "Papa", None), "Moi", (None, "Maman", None))
>>> nb_generations(deux_gen)
2
>>> trois_gen = ((None, "Papa", (None, "Mamy P.", None)), "Moi", ((None, "Papy M.", None), "Maman", None))
>>> nb_generations(trois_gen)
3

###(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

.128013ua/(lbw)pgdo kehmf:+v,P1Ssiny0_t5x4Nr32c=050l0p0G0c0B0f0A0n0O0f0c0A0A0P010G0B0j010406050A0b0r0r0c0L0D040z0m0f0b0*0m0C050d0;0?0^0`0/0j04131a051d0d1d1f1a0/0l0B0v0Y0!0$0(0q0B0k0q0f1t0q0G0-050T0g0f0p1o0#0%011s1u1w1u0G1C1E1A0G0g0m0l0`1B0L1b0G0q0Y0}0A0j0c0C0(0N011G1q010s0V0p0C0c0r0p1A1(1*1/1I1=1E1^1`0-0a0n0x0L0m0j0m0A0B100C0n0R1$0L0L0p0O2f131}0C1b0d1!2s0G1Y1X1Z0l1 0(1w0C1@2c1A1l1n0Z1H2C0B2E0C1U1m1A0j2l1b2q2s2W0:1)2g2K1:2P0L0@0f0-0y2p2!0.2Z1~2$1I2(2*0-0N2.1*2:2q2B012^0c2+040M2|2r0/2 2?0(32340J372~2!303d0-0H3g1c2U132I2v0l2z300O1U1{1b3r1e3p2Y142/053w0R2V3i3b010o0-0R0s3n3a1p1I0h0-0n3R3K3T3c0s0-0C0g0F0k1@0p0L0c2f0A3Y2=3!010,040e3=2#3@0C0-0^0g2l3|303_0i0t3g060n4b3X3S2L3M0-0B3Q3E2}4d3Z4f3 0441434k2r4m3?4f0m3V040B3;4t044v3}4f0o0O0-0K110p443L3_484D4a4c4U2;4G1:3N042l0G0b0L124D4F300r0B0-0E494V4e2%0-0A0c0k4O3@3_0w3g4+3L4p0j3-0A112E4|4f4~504W3j4^0c0l5c4?1I0m0-0P5i4n4@4q0L424N4S4=5p1I4Z4#4%4)2W513@4-2,5o4w1:5l040u5I4X2@0g0-0@0I591:3_3{4D5d523%3)3+2E3.3:5V1I5X5,3c5f4{5Z5j0(464 4*5!3~5$3*3,5*0B114C2Y5@3^0-5Y655x5:044_5h5?6b67040i0i49133H0p2s2T6p3q1m3s2v2x2t1T1V2v0c1D6s0d3r0/6F0S0U0W04.
3. Compter les prénoms identiques

Il arrive que certains prénoms apparaissent plusieurs fois dans un arbre généalogique.

Écrire la fonction compte qui prend en paramètre un tuple arbre représentant un arbre généalogique ainsi qu'un nom (au format str) et renvoie le nombre d'apparitions de ce nom dans l'arbre généalogique.

Exemples
>>> une_gen = (None, "Pierre", None)
>>> compte(une_gen, "Pierre")
1
>>> compte(une_gen, "Martin")
0
>>> deux_gen = ((None, "Paul", None), "Pierre", (None, "Jacqueline", None))
>>> compte(deux_gen, "Pierre")
1
>>> trois_gen = (((None, "Pierre", (None, "Jacqueline", None)), "Paul", None), "Pierre", ((None, "Pierre", None), "Jacqueline", None))
>>> compte(trois_gen, "Pierre")
3
>>> compte(trois_gen, "Jacqueline")
2

###(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

.128013ua/(lbw8p)gdo 7ekhmf:+v,P1Ssiny0t54Nr32c6=050m0q0H0c0D0f0C0o0O0f0c0C0C0Q010H0D0j010406050C0b0t0t0c0L0F040B0n0f0b0+0n0E050d0=0@0_0{0:0j04141b051e0d1e1g1b0:0m0D0x0Z0#0%0)0s0D0l0s0f1u0s0H0.050U0g0f0q1p0$0(011t1v1x1v0H1D1F1B0H0g0n0m0{1C0L1c0H0s0Z0~0C0j0c0E0)0N011H1r010u0W0q0E0c0t0q1B1)1+1:1J1?1F1_1{0.0a0o0z0L0n0j0n0C0D110E0o0S1%0L0L0q0O2g141~0E1c0d1#2t0H1Z1Y1!0m200)1x0E1^2d1B1m1o0!1I2D0D2F0E1V1n1B0j2m1c2r2t2X0;1*2h2L1;2Q0L0^0f0.0A2q2#0/2!1 2%1J2)2+0.0N2/1+2;2r2C012_0c2,040M2}2s0:302@0)33350J382 2#313e0.0I3h3a3j3c320n2*340.0P3o2=2$1q2^3t2`040p3y3b3B3d3D3v040i3h1d2V142J2w0m2A310O1V1|1c3T1f3R2Z152:053Y0S2W3q3J010r0.0S0u3P3I2M010h0.0o3`3:3|0E0u0.3Y0t0j0H0q412?3;0-040e4c3A430.0_0g2m4i314f0y3h403{2(0.2Q0t4p3r4f0k0v3o0o4G4u421;3?040D3_3*2~4I4d4k044m4o4P2s4R4j1;0n3~4M0C4t3z310r0O0.0K124b4X3/4S1;4f4E4?064H4~4Z4,0.2m0H0b0L134?503r0t0D0.0G4F4H4+3r0E0.0C0c0l4A4e0.4s585h3;5j040j0q0L0C122F5o3|4r4*4v2^5k0c0m5G4J1J0n0.0Q5M4^5I4U0L4n4=2X4}5g5H3d4x5S4!5O5Q5)315b5d5f4G5t3|4L4N5-5i0.5x5z5B5Y2:593;5P040Q5R5s5$324x0n4z4?5?4_0.4{5Z4 5#5N5%04572X623|64676q6f1J5/042.4|4~6w0)4L53556p616D6a6o5`630.0w6N4T4749602~6K4f4h6e695v5l5n6!6m015F686*5v4y5D6g040k6R4#6P6^5U6T4a6;1J6Y6 6n5l5L6)5T0)6,6v6#6b6d2Z694C3y0d3-0q2t2U7k3S1n3U2w2y2u1U1W2w0c1E7n0d3T0:7A0T0V0X04.
4. Extraire une génération

On appelle génération \(n\) dans un arbre, l'ensemble des personnes définies comme suit :

  • la personne à la racine de l'arbre forme la génération \(1\) ;
  • ses parents forment la génération \(2\) ;
  • ses grands-parents la génération \(3\) ;
  • ...

Écrire la fonction generation qui prend en paramètre un tuple arbre représentant un arbre généalogique ainsi qu'un entier strictement positif n et renvoie la liste des noms des personnes situés à la génération n.

La liste sera ordonnée de façon à correspondre à la représentation graphique de l'arbre : le nom d'une personne apparaissant sur la gauche sera placé plus tôt dans la liste que le nom d'une personne apparaissant sur la droite.

Exemples
>>> une_gen = (None, "Moi", None)
>>> generation(une_gen, 1)
['Moi']
>>> deux_gen = ((None, "Papa", None), "Moi", (None, "Maman", None))
>>> generation(deux_gen, 2)
['Papa', 'Maman']
>>> trois_gen = ((None, "Papa", (None, "Mamy P.", None)), "Moi", ((None, "Papy M.", None), "Maman", None), )
>>> generation(trois_gen, 3)
['Mamy P.', 'Papy M.']

###(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]é(wdef+nO»5xr-3EuRa;/qlbC)pg[o 7khm:v,PA1Ssûi.y_t4N2c6=«050f0g0Y0u0U0y0S0G0$0y0u0S0S0(010Y0U0C010406050S0s0K0K0u0o0W040R0F0y0s0}0F0j0G020u0K0C0v0G0t0g170o0x0s0g0S050w1416181a120C041y1F051I0w1I1K1F120f0U0M0=0@0_0{0J0U0D0J0y1Y0J0Y10050-0z0y0g1T0^0`011X1Z1#1Z0Y1+1-1)0Y0z0F0f1a1*0o1G0Y0J0=1d0S0C0u0j0{0#011/1V010h0/0g0j1l0g1)2a2c2h1;2k1-2n0K2p040a0G0O0o0F0C0F0S0U1g1i0+280o0o0g0$2K1y2r0j1G0w262W0Y2423250f2t0{1#0j2m2H1)1Q1S0?1:2*0U2,0j201R1)0C2P1G2U2W31132b1i2=2i2`0o170y100Q2T3511342s371;393b100#3f2c3h2U2)013m0u3c040q3q2V123t3k0{3w3y0Z3B3s353u3H100m3K3D3M3F3v0F3a3x100%3R3i361U3l3W3n040H3K1H2 1y2:2Z0f2%3u0$202z0*1R1G2~0g303g3.3`0+423j3(0{0I100+0h3.3E49010e100G4f3T4h0j0h100D2m0g0o0u2S1z434g2?010 040d4m484B0j10180z2P4G3%4B4D0N3K4l4A38100j4O3u4D0B0L4T060G4*4U4n4B4b040U4e4y3r4,4H4W044L4N4?2V4^4P2i0F4j4:1x4~04503u0I0$100!1h0g4Z3U4D4%574)4+5n3$5a102P0Y0s0o4Y57595i100E0b3R5o4V3l100S0u0D5h4h4R4T5p3U4J040C4u0S1h2,5L4Q104S5x5P4o5H0u0f5O5F0{0F100(5,4-4`4|5g5l5E5?1;4/4;5=4_5G045w315y4h5/040(5;5$5-010K0U3d5Y2i5j5D5n4+5%4.5r0,5u643g665Z040E6i625T0o5V0j5X576o6j105C5`6n6d4/5s6s6051624s2,4v4x336d4D4F6G6d5R5I5K6$5|0{5N6c6,3v4X6R3u680p6?3U6f6h6+616-100B6`67100i734I4r4t6W0U1h6z704E7e6;045I5+6~6S7f5#656H626t4@7r5.106_6/6 6e6g043e7m4!713#0w45413/7L0w3=1y0Y3@7Q2#2X1 212Z0u1,7N3=1E477n012P0K0X0h0u0I0g0X0J0q101q1s1u1w0G5k331L3h1F0A0,0Y1.5V1e2K0G1w0Y0G4v0C0U2M0u0G0c0$0o0U2P0G170U0;0j8k1w2I850G0z0g0u0s3`0s0C0G0f000c0-5T0;2M0)8d2Q2F0U5J1.0l8G1.1#0S850S0V1H81040r1i0g0h0h0,0G0y3W8M1.0$0J0u7{0G0u0C5T0y8d8k5u2I0h0N0G1h0G7.2J4l7K3u1?1!1$1(7(5q046P5v774`6U4u4w7c7t2V7v4C106#6Y6:6(5J7h6.7q6%6=7z7)6^9o1;6|7D9E7H9J6@759M3G796V9s7d7F5z7g9#5(7j5*9Q047p6u9w5R9u589w9L9S6{7C7E9A7A4#3.7J3{040V0G0k0o961-0;0M3x0g938P0j0M0F0W0c7|2b0o0=8_8{0h1h2R9t8j0-0j8c0+0;8Y8!960O0W26980f0F9baI0j0$8|0f1Q2K6V0=0g0ya90p0$0U8$807%0Pao8`1v8|8~aU910$934;aDaF0JaHaJayas4l1r9l8Q8f4u8:002m0S1r7!8Waaac931ya}afahaj7|0f2c0;0s2,0G2`0s0MaU1-8:8r8x2M5V160g0VbA0G83281m3W852yax0G5T1f0G0S000u0M0c2Pan3`0T850s0na!1O3;0,0.0:04.

On peut résoudre cet exercice à l'aide d'un parcours en largeur de l'arbre.

Pour ce faire on crée une liste actuelle qui contient tous les nœuds non vides de la génération actuelle.

On met alors à jour cette liste en remontant à la génération précédente jusqu'à atteindre le rang de la génération souhaité.

###(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]ua/q(lbw8p)g[do 7ekhmf:v,P1Ssin9.y0_t54Nr32c6=050p0t0M0d0F0h0E0r0T0h0d0E0E0V010M0F0l010406050E0c0w0w0d0Q0J040D0q0h0c0:0q0G050e0`0|0~100^0l04191g051j0e1j1l1g0^0p0F0z0(0*0,0.0v0F0n0v0h1z0v0M0?050Z0i0h0t1u0+0-011y1A1C1A0M1I1K1G0M0i0q0p101H0Q1h0M0v0(130E0l0d0G0.0S011M1w010x0#0t0G0d0w0t1G1.1:1^1O1{1K1~200?0a0r0B0Q0q0l0q0E0F160G0r0X1,0Q0Q0t0T2l19230G1h0e1*2y0M1(1%1)0p250.1C0G1}2i1G1r1t0)1N2I0F2K0G1!1s1G0l2r1h2w2y2$0_1/2m2Q1_2V0Q0}0h0?0r0C2v2*0@2)242,1O2.2:2=0S2^1:2`2w2H012 0d2;040r0R332x0^362}0.393b0r0O3f352*373l2=0N3p3h3r3j380q2/3a2=0U3w2{2+1v2~3B303c0s3G3i3J3k3L3D3c0k3P3y3R3A3C3m0H3X2|3Z3t040C0K3(3I2R3!3M0C2@1a2_3x3)3;3+0C323_341i2!192O2B0p2F370T1!211h461k442(412x054b0X2#3Y3;0u0?0X0x3p3H370j2=4v3Q3}0x0?0n1}0t0Q0d2u4j4o3|1_0=040g4A4p2-0?0~0i2r4S4N1O4P0A3p0r4w3z0G0?184L4*3Z4P0m0y4(060r4`4)4B4U040d2t0c0t0h1K4(4:3;0q0?0V564}4#0?0o4Z3:4~4W4Y4/5d0.4P0b3w4{4|4T1O4r040x3B5c5u3k0?0L5A4!0.0q4y042T5F5i2~0i0?4I0G4F5h374P4R5m5B010w0F0?3^2(5n014$5M3s4-5U3z4=4@4L4_5s4{574~2Z2s0t0X0G0M0t5-3z59045b4L5t5G5+5f5q5@5_5`5*5w5y0Q643*4V6m585J5L695{2~4V5153555Y6b4P5?2$5^6g5s6u5C040E0d0n5:4;0?4%6t5*4,040l4H0E172K6O3;5,6S5Z6U6L0p6p1_66682$6a5N6J0d5r6G6H6i0?0F4u6(6b6*6M6-1O5I6}0E745H5J2V0M79010u0T0?0P17636A6?6c046D3`6`6`6I380?5}0T5 1}626#6.0?0I7C6v4 0l6W0G6,7m5V0?5X5)6)0?6L6N7N5;0?0m6_7s6=375w6~7e727M6;7u765K78707n7/7c7e7g7i7k7G5o0?7q346F7#6h7S6V2r7y607B7W3Z667F8b3}4V7J1}7,2_7u5W7}7v6K0d8k425*4=7!5_7u6U500M52547l7-5*6/7*7w877z618E7r846b5w2r8B0Q4.8F5Z4P5g8f5j8o8Y8o5#5%8$0?6e8W8Q0?6k8I4 7e7/6s8.7n8z6x8D8+048-2_4`7u0T0C0?030r170r2K0r2r0G0z0q0F1L0f520r1K0%2V0w7;6E194m0t2y5}2y4f2z48192C2B1Z1#2B0d1J9v451s2`0e0X0Z0#0E04.

On peut résoudre cet exercice à l'aide d'un parcours en profondeur de l'arbre.

Pour ce faire on utilise une structure de pile dans laquelle on ajoute initialement la racine de l'arbre ainsi que sa hauteur 1.

Attention toutefois à l'ordre dans lequel on empile les différents nœuds : une pile répond au modèle « Dernier Entré, Premier Sorti » !

###(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]uRéa;/q(lbàwp8)g[èdo 7ekhmf:+v,P1Ssin9.Oy0_t54Nr-32c6=050u0y0T0f0L0k0K0w0#0k0f0K0K0%010T0L0o010406050K0c0B0B0f0X0Q040J0v0k0c0{0v0M0w020f0B0o0g0w0d0y150X0i0c0y0K050h12141618100o041w1D051G0h1G1I1D100u0L0F0:0=0@0_0A0L0r0A0k1W0A0T0~050+0l0k0y1R0?0^011V1X1Z1X0T1)1+1%0T0l0v0u181(0X1E0T0A0:1b0K0o0f0M0_0!011-1T010C0-0y0M1j0y1%282a2f1/2i1+2l0B2n040a0w0H0X0v0o0v0K0L1e1g0)260X0X0y0#2I1w2p0M1E0h242U0T2221230u2r0_1Z0M2k2F1%1O1Q0;1.2(0L2*0M1~1P1%0o2N1E2S2U2 11291g2:2g2^0X150k0~0w0I2R330 322q351/37393b0!3e2a3g2S2%013l0f3a040w0Z3p2T103s3j0_3v3x0w0V3B3r333t3H3b0U3L3D3N3F3u0v383w3b0$3S3h341S3k3X3m3y0x3$3E3)3G3+3Z3y0p3/3U3;3W3Y3I0N3`3i3|3P040I0R413(2;3}3,0I3d1x3f3T424a440I3o4f3q4h49363?3x0I3A4n3C3%3O4s0~0I3K4w2U2|0y2U2.2X0u2#3t0#1~2x0(1P1E4G2~3f3L054O0)4V4i2g0z0~0)0C4X3:4a0n3b4,3{4j0C0~0r2k0y0X0f2Q4E4y3V0}040j4;4$3k0~160l2N554q1/520G3L0w50430~0M5c3t520q0D5h060w5u5i4-360~0o2j5h5j4a0v0~0%5C5x5e0~0s544 5J3G580X5a0y5n510~5g4E5w4=2g0B0L4B5V3|5p0b3S5v5!565Q042N120k0+0T5I5#1/5F045H5Z5D2g520s5-4E5t5v631/4(040n1V1+5|5;3u0l0~2u5*4a525N315P3u5z5B5O5}0_5p6i5d0_5 020r0T0g6B3t5%0~476x6j525r685/5/6b5=0f6o645X6J3V0M0~0L6#3|5 612 5:6C6u045A6h6O6:5 0O6Y576=2D6|6z0~0j0q5.6T5u6V6;0K0f0r70015f6*4j5z4{0K1f2*7d7f626t6%047a0u7g2g6,7v6}6X6S766/3t6d0L4+7p6y6;6)7I6j6,6-3f7D6$5l7n0~6R2 697C6a7q0~5@0c5_4}7d6`7d7r0f0o0o2k7u6^5o727-7i0X7k0M7m7@5W04747B76786d0y0.5U805+7V757Z776t7F7H6.787r7t7y6D4/040L1v7M6_8q2^5{8u7E0#0~0W1f8a6s7J6Q8e8f6U7#6=6w8G7N0~6{8b7h047/7;0M7?8P6:6q6r4W8M8n8T6Z045Y8k8M7L8/7J5 0E8o016L457U82837X8K8g7J8i8_8m7b8_0v8q8s988w0v8y8=6j0z8B048D7 8!7^047W4g916T8l6v6@9n3V7,8+7z7:7=8}0j8%3q9u7s979A718-956(980~8^8z3V8{4e9x8c8~8J867$0*0c0X5m9T5k5?1u7(5`3$0h4Z4H1F2}1w4J1w0T4L9|2Z2V1}1 2X0f1*9@0h4J1C4#6:2N0B0S0C0f0z0y0S0A0Z0~1o1q1s1u0w9q9H1J3g1D0P1g8x4{0f0waq0w2E9(0w5@7;2P4{0w0k003X0u2N0w0F0v7(0c0w0)0/2^0B0/0u2a0/0=aN8s0T0y0G0w1f0w0y0C0C2O0T1taN1,290X4O9(0/2k0w062?0K0e4|0M0TaY00a5aQa}0w7k0c0K0Y59aSaR0v2HaYa)aNaC6?a/0w0f0F2abc1+biaVblbn1,0r0f0c0#0Abx4Obb4|0Lad2kbc0mb50#1,aEaOa=agbr0Aa52H1t0k1+2wbb0w0jb74{2IaY1,aO2kagb:bJbLbNaF0c8sbhbp2H0q8S1M1H04ayaFaV2M0,bcbK0@0L0w1d0-8saM0c1ga b17|aI0e0#b27Ga?1g2YchbBaN00b|cFb bM1,0ube1}0X0ua:0oc3a*cM2C2Ha:06bYaDc3aF4{2wbccN0v0la.0MbSbua,0Ka.0w2i2lbD1O2NaLb/c+btbD1}1gaQaS0jaUc;a+0I0taS0F7j0La=2KbY1^1,06aqc@dh0Mc81F3ga80*0,0.04.