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

.1280135tf4)+2r3,sao iug0m1PpNnlhe=cy:v(wS/b_dk050N0B0c0m0p0z0l0o0D0z0m0l0l0C010c0p0w010406050l0q0t0t0m0i0E040J0n0z0q0)0n0y050K0:0=0@0_0.0w041219051c0K1c1e190.0N0p0G0X0Z0#0%0A0p0r0A0z1s0A0c0,050S0L0z0B1n0!0$011r1t1v1t0c1B1D1z0c0L0n0N0_1A0i1a0c0A0X0|0l0w0m0y0%0h011F1p010d0U0B0y0m0t0B1z1%1)1.1H1;1D1@1_0,0a0o0v0i0n0w0n0l0p0 0y0o0Q1#0i0i0B0D2e121|0y1a0K1Z2r0c1X1W1Y0N1~0%1v0y1?2b1z1k1m0Y1G2B0p2D0y1T1l1z0w2k1a2p2r2V0/1(2f2J1/2O0i0?0z0,0u2o2Z0-2Y1}2#1H2%2)0,0h2-1)2/2p2A012@0m2*040j2{2q0.2~2=0%31330e362}2Z2 3c0,0b3f1b2T122H2u0N2y2 0D1T1`1a3q1d3o2X132.053v0Q2U3h3a010O0,0Q0d3m391o1H0I0,0o3Q3J3S3b0d0,0y0L0M2S0B0l1?0c0l3X2;3Z010+040H3:2!3=0y0,0@0L2k3`2 3@0f0F3f060o493W3R2K3L0,0p3P3D2|4b3Y4d3}043 414i2q4k3;4d0n3U040p3/4r044t3{4d0O0D0,0x100B423K3@464B484a4S2:4E1/3M042k0c0q0i114B4D2 0t0p0,0s474T4c2$0,0l0m0r4M3=3@0k3f4)3K4n0w0B0i0l102D4`4d4|4~4U3i4?0m0N5b4;1H0n0,0C5h4l4=4o0i404L4Q4:5o1H4X4Z4#4%2V4 3=4+2+5n4u1/5k040g5H4V2?3$3(3*3,0y3.581/3@3_4B5c505e4_5!5i0%445N2 5K5M4(5#3|5Q3)2k5T5V5)5w5+0,5Z2X5*305e5g5|5I1H5,4Q123G0B2r3*2r3z2s3s122v2u1S1U2u0m1C6d3p1l2/0K0Q0S0U0l04.
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

.1280135tf4)+2r3,sao iug0xm1PpNnlhe=cy:v(wS/b_dk050O0C0c0m0p0A0l0o0E0A0m0l0l0D010c0p0x010406050l0q0u0u0m0i0F040K0n0A0q0*0n0z050L0;0?0^0`0/0x04131a051d0L1d1f1a0/0O0p0H0Y0!0$0(0B0p0r0B0A1t0B0c0-050T0M0A0C1o0#0%011s1u1w1u0c1C1E1A0c0M0n0O0`1B0i1b0c0B0Y0}0l0x0m0z0(0h011G1q010d0V0C0z0m0u0C1A1(1*1/1I1=1E1^1`0-0a0o0w0i0n0x0n0l0p100z0o0R1$0i0i0C0E2f131}0z1b0L1!2s0c1Y1X1Z0O1 0(1w0z1@2c1A1l1n0Z1H2C0p2E0z1U1m1A0x2l1b2q2s2W0:1)2g2K1:2P0i0@0A0-0v2p2!0.2Z1~2$1I2(2*0-0h2.1*2:2q2B012^0m2+040j2|2r0/2 2?0(32340e372~2!303d0-0b3g1c2U132I2v0O2z300E1U1{1b3r1e3p2Y142/053w0R2V3i3b010P0-0R0d3n3a1p1I0J0-0o3R3K3T3c0d0-0z0M0N0r1@0C0i0m2f0l3Y2=3!010,040I3=2#3@0z0-0^0M2l3|303_0f0G3g060o4b3X3S2L3M0-0p3Q3E2}4d3Z4f3 0441434k2r4m3?4f0n3V040p3;4t044v3}4f0P0E0-0y110C443L3_484D4a4c4U2;4G1:3N042l0c0q0i124D4F300u0p0-0s494V4e2%0-0l0m0r4O3@3_0k3g4+3L4p0x3-0l112E4|4f4~504W3j4^0m0O5c4?1I0n0-0D5i4n4@4q0i424N4S4=5p1I4Z4#4%4)2W513@4-2,5o4w1:5l040g5I4X2@0M0-0@0t591:3_3{4D5d523%3)3+2E3.3:5V1I5X5,3c5f4{5Z5j0(464 4*5!3~5$3*3,5*0p114C2Y5@3^0-5Y655x5:044_5h5?6b67040f0f49133H0C2s2T6p3q1m3s2v2x2t1T1V2v0m1D6s0L3r0/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

.1280135tf4)+2r3,sao iug08m1P6pNnl7he=cy:v(wS/bdk050P0E0c0m0p0B0l0o0G0B0m0l0l0F010c0p0y010406050l0q0u0u0m0i0H040M0n0B0q0+0n0A050N0=0@0_0{0:0y04141b051e0N1e1g1b0:0P0p0J0Z0#0%0)0D0p0r0D0B1u0D0c0.050U0O0B0E1p0$0(011t1v1x1v0c1D1F1B0c0O0n0P0{1C0i1c0c0D0Z0~0l0y0m0A0)0h011H1r010d0W0E0A0m0u0E1B1)1+1:1J1?1F1_1{0.0a0o0w0i0n0y0n0l0p110A0o0S1%0i0i0E0G2g141~0A1c0N1#2t0c1Z1Y1!0P200)1x0A1^2d1B1m1o0!1I2D0p2F0A1V1n1B0y2m1c2r2t2X0;1*2h2L1;2Q0i0^0B0.0v2q2#0/2!1 2%1J2)2+0.0h2/1+2;2r2C012_0m2,040j2}2s0:302@0)33350e382 2#313e0.0b3h3a3j3c320n2*340.0x3o2=2$1q2^3t2`040C3y3b3B3d3D3v040t3h1d2V142J2w0P2A310G1V1|1c3T1f3R2Z152:053Y0S2W3q3J010Q0.0S0d3P3I2M010L0.0o3`3:3|0A0d0.3Y0u0y0c0E412?3;0-040K4c3A430.0_0O2m4i314f0k3h403{2(0.2Q0u4p3r4f0f0I3o0o4G4u421;3?040p3_3*2~4I4d4k044m4o4P2s4R4j1;0n3~4M0l4t3z310Q0G0.0z124b4X3/4S1;4f4E4?064H4~4Z4,0.2m0c0q0i134?503r0u0p0.0s4F4H4+3r0A0.0l0m0r4A4e0.4s585h3;5j040y0E0i0l122F5o3|4r4*4v2^5k0m0P5G4J1J0n0.0F5M4^5I4U0i4n4=2X4}5g5H3d4x5S4!5O5Q5)315b5d5f4G5t3|4L4N5-5i0.5x5z5B5Y2:593;5P040F5R5s5$324x0n4z4?5?4_0.4{5Z4 5#5N5%04572X623|64676q6f1J5/042.4|4~6w0)4L53556p616D6a6o5`630.0g6N4T4749602~6K4f4h6e695v5l5n6!6m015F686*5v4y5D6g040f6R4#6P6^5U6T4a6;1J6Y6 6n5l5L6)5T0)6,6v6#6b6d2Z694C3y0N3-0E2t2U7k3S1n3U2w2y2u1U1W2w0m1E7n0N3T0: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

.1280135[4)2R,a- im16Cl7.e:A;S/dktf+«r3soguûx]PpNOnE»h=céyv(wq_b050z0t0B0i0l0q0H0k0X0q0i0H0H0W010B0l0P010406050H0K0m0m0i0F0Z040x0I0q0K0}0I0S0k020i0m0P0w0k0g0t170F0%0K0t0H050y1416181a120P041y1F051I0y1I1K1F120z0l0!0=0@0_0{0V0l0J0V0q1Y0V0B10050-0)0q0t1T0^0`011X1Z1#1Z0B1+1-1)0B0)0I0z1a1*0F1G0B0V0=1d0H0P0i0S0{0f011/1V010C0/0t0S1l0t1)2a2c2h1;2k1-2n0m2p040a0k0O0F0I0P0I0H0l1g1i0+280F0F0t0X2K1y2r0S1G0y262W0B2423250z2t0{1#0S2m2H1)1Q1S0?1:2*0l2,0S201R1)0P2P1G2U2W31132b1i2=2i2`0F170q100n2T3511342s371;393b100f3f2c3h2U2)013m0i3c040G3q2V123t3k0{3w3y0d3B3s353u3H100b3K3D3M3F3v0I3a3x100o3R3i361U3l3W3n040r3K1H2 1y2:2Z0z2%3u0X202z0*1R1G2~0t303g3.3`0+423j3(0{0A100+0C3.3E49010$100k4f3T4h0S0C100J2m0t0F0i2S1z434g2?010 040#4m484B0S10180)2P4G3%4B4D0h3K4l4A38100S4O3u4D0e0u4T060k4*4U4n4B4b040l4e4y3r4,4H4W044L4N4?2V4^4P2i0I4j4:1x4~04503u0A0X100Q1h0t4Z3U4D4%574)4+5n3$5a102P0B0K0F4Y57595i100c0N3R5o4V3l100H0i0J5h4h4R4T5p3U4J040P4u0H1h2,5L4Q104S5x5P4o5H0i0z5O5F0{0I100W5,4-4`4|5g5l5E5?1;4/4;5=4_5G045w315y4h5/040W5;5$5-010m0l3d5Y2i5j5D5n4+5%4.5r0,5u643g665Z040c6i625T0F5V0S5X576o6j105C5`6n6d4/5s6s6051624s2,4v4x336d4D4F6G6d5R5I5K6$5|0{5N6c6,3v4X6R3u680j6?3U6f6h6+616-100e6`67100D734I4r4t6W0l1h6z704E7e6;045I5+6~6S7f5#656H626t4@7r5.106_6/6 6e6g043e7m4!713#0y45413/7L0y3=1y0B3@7Q2#2X1 212Z0i1,7N3=1E477n012P0m0(0C0i0A0t0(0V0G101q1s1u1w0k5k331L3h1F0p0,0B1.5V1e2K0k1w0B0k4v0P0l2M0i0k0Y0X0F0l2P0k170l0;0S8k1w2I850k0)0t0i0K3`0K0P0k0z000Y0-5T0;2M0E8d2Q2F0l5J1.0U8G1.1#0H850H0s1H81040T1i0t0C0C0,0k0q3W8M1.0X0V0i7{0k0i0P5T0q8d8k5u2I0C0h0k1h0k7.2J4l7K3u1?1!1$1(7(5q046P5v774`6U4u4w7c7t2V7v4C106#6Y6:6(5J7h6.7q6%6=7z7)6^9o1;6|7D9E7H9J6@759M3G796V9s7d7F5z7g9#5(7j5*9Q047p6u9w5R9u589w9L9S6{7C7E9A7A4#3.7J3{040s0k0R0F961-0;0!3x0t938P0S0!0I0Z0Y7|2b0F0=8_8{0C1h2R9t8j0-0S8c0+0;8Y8!960O0Z26980z0I9baI0S0X8|0z1Q2K6V0=0t0qa90j0X0l8$807%0vao8`1v8|8~aU910X934;aDaF0VaHaJayas4l1r9l8Q8f4u8:002m0H1r7!8Waaac931ya}afahaj7|0z2c0;0K2,0k2`0K0!aU1-8:8r8x2M5V160t0sbA0k83281m3W852yax0k5T1f0k0H000i0!0Y2Pan3`0L850K0Ma!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

.1280135[tf4)2r3,sao iug08m1]P6pNnl7h.e=cy:v9(wqS/b_dk050U0G0d0m0p0C0l0o0I0C0m0l0l0H010d0p0z010406050l0q0u0u0m0i0J040Q0n0C0q0:0n0B050R0`0|0~100^0z04191g051j0R1j1l1g0^0U0p0L0(0*0,0.0E0p0r0E0C1z0E0d0?050Z0S0C0G1u0+0-011y1A1C1A0d1I1K1G0d0S0n0U101H0i1h0d0E0(130l0z0m0B0.0h011M1w010e0#0G0B0m0u0G1G1.1:1^1O1{1K1~200?0a0o0x0i0n0z0n0l0p160B0o0X1,0i0i0G0I2l19230B1h0R1*2y0d1(1%1)0U250.1C0B1}2i1G1r1t0)1N2I0p2K0B1!1s1G0z2r1h2w2y2$0_1/2m2Q1_2V0i0}0C0?0o0v2v2*0@2)242,1O2.2:2=0h2^1:2`2w2H012 0m2;040o0j332x0^362}0.393b0o0f3f352*373l2=0b3p3h3r3j380n2/3a2=0y3w2{2+1v2~3B303c0D3G3i3J3k3L3D3c0t3P3y3R3A3C3m0M3X2|3Z3t040v0s3(3I2R3!3M0v2@1a2_3x3)3;3+0v323_341i2!192O2B0U2F370I1!211h461k442(412x054b0X2#3Y3;0V0?0X0e3p3H370O2=4v3Q3}0e0?0r1}0G0i0m2u4j4o3|1_0=040N4A4p2-0?0~0S2r4S4N1O4P0k3p0o4w3z0B0?184L4*3Z4P0g0K4(060o4`4)4B4U040m2t0q0G0C1K4(4:3;0n0?0H564}4#0?0c4Z3:4~4W4Y4/5d0.4P0w3w4{4|4T1O4r040e3B5c5u3k0?0T5A4!0.0n4y042T5F5i2~0S0?4I0B4F5h374P4R5m5B010u0p0?3^2(5n014$5M3s4-5U3z4=4@4L4_5s4{574~2Z2s0G0X0B0d0G5-3z59045b4L5t5G5+5f5q5@5_5`5*5w5y0i643*4V6m585J5L695{2~4V5153555Y6b4P5?2$5^6g5s6u5C040l0m0r5:4;0?4%6t5*4,040z4H0l172K6O3;5,6S5Z6U6L0U6p1_66682$6a5N6J0m5r6G6H6i0?0p4u6(6b6*6M6-1O5I6}0l745H5J2V0d79010V0I0?0A17636A6?6c046D3`6`6`6I380?5}0I5 1}626#6.0?0F7C6v4 0z6W0B6,7m5V0?5X5)6)0?6L6N7N5;0?0g6_7s6=375w6~7e727M6;7u765K78707n7/7c7e7g7i7k7G5o0?7q346F7#6h7S6V2r7y607B7W3Z667F8b3}4V7J1}7,2_7u5W7}7v6K0m8k425*4=7!5_7u6U500d52547l7-5*6/7*7w877z618E7r846b5w2r8B0i4.8F5Z4P5g8f5j8o8Y8o5#5%8$0?6e8W8Q0?6k8I4 7e7/6s8.7n8z6x8D8+048-2_4`7u0I0v0?030o170o2K0o2r0B0L0n0p1L0P520o1K0%2V0u7;6E194m0G2y5}2y4f2z48192C2B1Z1#2B0m1J9v451s2`0R0X0Z0#0l04.

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

.1280135[tf4)+2rR3,sa-o iug0è8àm1]P6pNOnl7h.e=céy:v9(wq;S/b_dk050$0M0d0o0s0I0n0r0O0I0o0n0n0N010d0s0E010406050n0t0z0z0o0j0Q040Y0q0I0t0{0q0H0r020o0z0E0X0r0k0M150j0W0t0M0n050Z12141618100E041w1D051G0Z1G1I1D100$0s0S0:0=0@0_0K0s0u0K0I1W0K0d0~050+0!0I0M1R0?0^011V1X1Z1X0d1)1+1%0d0!0q0$181(0j1E0d0K0:1b0n0E0o0H0_0i011-1T010e0-0M0H1j0M1%282a2f1/2i1+2l0z2n040a0r0C0j0q0E0q0n0s1e1g0)260j0j0M0O2I1w2p0H1E0Z242U0d2221230$2r0_1Z0H2k2F1%1O1Q0;1.2(0s2*0H1~1P1%0E2N1E2S2U2 11291g2:2g2^0j150I0~0r0A2R330 322q351/37393b0i3e2a3g2S2%013l0o3a040r0l3p2T103s3j0_3v3x0r0f3B3r333t3H3b0b3L3D3N3F3u0q383w3b0D3S3h341S3k3X3m3y0J3$3E3)3G3+3Z3y0x3/3U3;3W3Y3I0T3`3i3|3P040A0v413(2;3}3,0A3d1x3f3T424a440A3o4f3q4h49363?3x0A3A4n3C3%3O4s0~0A3K4w2U2|0M2U2.2X0$2#3t0O1~2x0(1P1E4G2~3f3L054O0)4V4i2g0%0~0)0e4X3:4a0V3b4,3{4j0e0~0u2k0M0j0o2Q4E4y3V0}040U4;4$3k0~160!2N554q1/520m3L0r50430~0H5c3t520g0R5h060r5u5i4-360~0E2j5h5j4a0q0~0N5C5x5e0~0c544 5J3G580j5a0M5n510~5g4E5w4=2g0z0s4B5V3|5p0B3S5v5!565Q042N120I0+0d5I5#1/5F045H5Z5D2g520c5-4E5t5v631/4(040V1V1+5|5;3u0!0~2u5*4a525N315P3u5z5B5O5}0_5p6i5d0_5 020u0d0X6B3t5%0~476x6j525r685/5/6b5=0o6o645X6J3V0H0~0s6#3|5 612 5:6C6u045A6h6O6:5 0L6Y576=2D6|6z0~0U0g5.6T5u6V6;0n0o0u70015f6*4j5z4{0n1f2*7d7f626t6%047a0$7g2g6,7v6}6X6S766/3t6d0s4+7p6y6;6)7I6j6,6-3f7D6$5l7n0~6R2 697C6a7q0~5@0t5_4}7d6`7d7r0o0E0E2k7u6^5o727-7i0j7k0H7m7@5W04747B76786d0M0.5U805+7V757Z776t7F7H6.787r7t7y6D4/040s1v7M6_8q2^5{8u7E0O0~0F1f8a6s7J6Q8e8f6U7#6=6w8G7N0~6{8b7h047/7;0H7?8P6:6q6r4W8M8n8T6Z045Y8k8M7L8/7J5 0h8o016L457U82837X8K8g7J8i8_8m7b8_0q8q8s988w0q8y8=6j0%8B048D7 8!7^047W4g916T8l6v6@9n3V7,8+7z7:7=8}0U8%3q9u7s979A718-956(980~8^8z3V8{4e9x8c8~8J867$0*0t0j5m9T5k5?1u7(5`3$0Z4Z4H1F2}1w4J1w0d4L9|2Z2V1}1 2X0o1*9@0Z4J1C4#6:2N0z0#0e0o0%0M0#0K0l0~1o1q1s1u0r9q9H1J3g1D0G1g8x4{0o0raq0r2E9(0r5@7;2P4{0r0I003X0$2N0r0S0q7(0t0r0)0/2^0z0/0$2a0/0=aN8s0d0M0m0r1f0r0M0e0e2O0d1taN1,290j4O9(0/2k0r062?0n0P4|0H0daY00a5aQa}0r7k0t0n0p59aSaR0q2HaYa)aNaC6?a/0r0o0S2abc1+biaVblbn1,0u0o0t0O0Kbx4Obb4|0sad2kbc0yb50O1,aEaOa=agbr0Ka52H1t0I1+2wbb0r0Ub74{2IaY1,aO2kagb:bJbLbNaF0t8sbhbp2H0g8S1M1H04ayaFaV2M0,bcbK0@0s0r1d0-8saM0t1ga b17|aI0P0Ob27Ga?1g2YchbBaN00b|cFb bM1,0$be1}0j0$a:0Ec3a*cM2C2Ha:06bYaDc3aF4{2wbccN0q0!a.0HbSbua,0na.0r2i2lbD1O2NaLb/c+btbD1}1gaQaS0UaUc;a+0A0waS0S7j0sa=2KbY1^1,06aqc@dh0Hc81F3ga80*0,0.04.