Aller au contenu

TP Tri et Diviser pour Régner

Le tri rapide⚓︎

Le tri rapide, utilise la principe diviser pour régner en:

  • Diviser : partitionne une liste grâce à un pivot de la liste: les inférieurs au pivot, le pivot et ceux supérieur au pivot.

  • Régner : Pour trier les parties inférieur et supérieur, on applique récursivement le même partitionnement, jusqu'à obtenir des partitions de 0 ou 1 élément (donc déjà triées).

  • Combiner Cette partie est immédiate.

Avec recopie des tranches de listes⚓︎

Le code le plus simple pour utiliser cet algorithme est de recopier les éléments dans des listes inf et sup, puis d'appeler le tri sur ces fonctions.

Complète le code suivant:

###(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 : 5/5
.128013it3a;dv,n2.S5éwbcy+14qL: f-up08)_9eklohrP=[s6(]/mg7050g0J0c0e0b0L0S0z0r0L0e0S0S0Q010c0b0D010406050S0C0X0X0e0O0s040m0M0L0C0@0M0j050W0~1012140|0D04051k1d1n0W1k0|0g0b0h0,0.0:0=0.0j0Y0C0e0Y0J0B0D0s0c0N1b0z0N0b0Y0N0L1P0N0c0`050%0q0L0J1w0/0;011O1Q1S1Q0c1Y1!1W0c0O1l1K0,170S0D0e0j0=0k011$1y010A0)0J0j0e0X0J1W1{1}221(251!282a0`0a0z0P0O0M0D0M0S0b1a0j0z0#1_0O0O0J0r2v1d2d0j1l0W1K2I1=1@1?1X0g2f1z0b0j272s1W1t1v0-1%2S2U0j0M2Y1W0D2B1l2G2I2/0}1|2w2!232(0O110L1W0e1N2B0A0=030H0H0r2)0J1S2%0M0B0E0B0u0`0z0u1d0e2:2?0{2=2e2^1(2`2|2~300J32013436383a2V3d0B20040z0k3k3m1}3o2G2R013t0e2}1l2 0N313335370#3D2(3F0d3h0d3L2F3n0|3P3r0=3S3U053W3Y3z3!3C2T3E3e0v3h0v3-1e3/3p2@1x3s0M2{3T3v3X3x3Z3B3$3 3(3e0n3h0n452/3:2?3Q3@4f3{3A3#394l3c3e0T3h0T4r473;4a3?4c3u3V3w3y4z3~3b3F0Z3h0Z4I3N4t3q4L3R4N4e4P4g4R3}4k4U3e0F3h0F4Z2H4#492#4(4d3^3`4h3|4j4B4:0B0I3h0I4^3O4u3=4}4O3_4Q4i4A3%4D3f0E0`0u0E5a4`4v4)4 5h525j4C3F0u3g045B5r485t4~4x514S4/403f3H0u3K0W3l3.4!5G5d4w4+4y4.545N0u3*5D3,5S3M4_5W4%5Y5g4,5i4T5%425D445,5U5.4K4|5;504-535k5A4o5D4q5}465V602_5u5J645y550u4F5D4H6b4s5/616g5Z5K5#663e0u4W5D4Y6p4J5c5:6t5=5!655z6y4=5D4@6D6d6F6s5I6u6i5^4m3f575D596Q5 6S6f6U6I6v6K550k5n046:5F6e4b6+635@5M6Y0k5C6 5a1o2-1d2Y2L0g1@2Q5d4A2X1u1l2,0J2.3n5~1l4A7i2e0b0g0=352G5A3v7p7r6.5%212j0J7x6j7z2I5T6^0=0K0`0#0A7k6r230p3h7O7I3R0A0`0w0C0b0r0K0H0S4c0c7T6)1(0_040U7+4$610`0x7;4{237.0y7_4v0q0`1S0S7*6c2H7P7-0`0G7}853o8c5G7w017s2?3F3H5g8g6w6L3G7A297C8h7y6~1W5,0z8z0z877J0`0b7N8c8B7U0j80042i7~5d7.7:8e8J7@8O4%7.0G7k8I7,0=0M0`020L0c0f8Z8C010X0b0`5R2;7U7|7k0|8S4u8n7%8j3e5)8m7q8u7E6Y3*0z7B7D6X5l928y8A9g8.7K042B0c0C0O1c8H8.0j8U8c8{8@8}948i1}3F5`939b6}5l42998s9E5$6Y9C5,9v7j3P8~7t4n7v9y8v5l4o9I2a9K6x0B683L9P3N8f9W9T0B6m9D959c3F4F9!8t8o559;9f8z9r8E0j8G2/8!7=238%040Q8-8^0`0R0V8`7~9S900B6A9=9|5N4W9`9$8pam9 a67`3s0`0~0Dac8#01a9ab9qad04afah8|7o9.ak6Nan9X3F4=ar9?9FaT8x3l9+869RaO9A3e6!aR965l57aVao6Ya+av8.0r5C030z0D1u0M0ca|2B8:0J0O0z0o0L0o2a0j846qaM2waja)5m9Vas6k5na:aS6y6;3L9h8T04a}0ha aCa71(aFbyax3?9t9wbz0=7.0R8V4|8:0`5qbe3Q7.ag9uaia(0j5A5Ca,9@6y3gbna-bYaZ8dbGbfbW5A8l2 8~b)6y20b(b#5Ob+bsaD9j0A4cbC4v0`39c35d0M7R042Tc75:bF9QaDbJbL23bN5Dcj88040y0V8bbdb-0zbgbX6y92b=9Wb@3f989aaW9L5l5(b}9g8A9i8Ea43nawc404c6aHaDa98)8+cd7?bua~bccgbH018_bUbQcw5A9CcAbk5_8r9#cG9%0u9N3lcLc cR5Xa2cP9,7Ua90lcnbE040e0D0D270gd9c+0`8Rcud2cT0Ldh8XaLcuc/6y9)c=c`8p0u9ZcFa;cI9)avb~c*9j390S0Jdp0`cs47c.b/6y9;dwdC5A9_dBbo3f9~c~d0dGbD3Raz0CaBbQc80`d8d.cedbdddfdM7/dh9sdnd`8Yc-dsdR3famdUdZ6zc^9{e7aua!bV7x9/0uaQe6cCehe9c?6Yel7G3IcM7U9j9l9n9pa5a1047Y7!7$7(0Oc(d5chdjd|d3d c!a80`0teNcobKd=c#bvbxeU7{0`bTeyd6ePeRdaeB7#7%7)d`dkc)d)d}aAeMe1e;cve30ua+ejb{e}emdx6ka?eddQefak6:bjf35Nfab`aX3efaeq9id}0b0X2reFdhca8BeY3sd}0O1}0g0M0Xfq7Sft8Ddb0SfB3Id|fvdge_eHaNf8bh6 fbdVfhb%dYcCfRfjbt0e0H1=0bb4e)aE0`aGe$eIaJf*fKdhd7eK9kfx2TeGa$f/e:fNd)cl3jfDdi040idhg20EbPdl8W89f*c0c2cVc*d}0Hf*c9a2f;8Lfw1BdLg48Qg88;5Dgagbe`8Pgegid)bSdr7j0W7m737h757e1d0c78gP2O2J0e1ZgM0W768{0#0%0)0S04.

version tri en place⚓︎

Le point faible principal de la version précédente est la re copie des listes.

On peut éviter cela grâce à des permutations.

On va aussi améliorer en mettant tous les éléments du tableau égal au pivot côte à côte.

On utilise une fonction partition qui partitionne par rapport au pivot (ici premier éléments des éléments à partitionner) les éléments compris entre les indice debut et fin. La méthode utilisée au sein de cette fonction est celle du tri du drapeau hollandais.

Le code suivant utilise des fonctions définies au sein d'une autre fonction.

###(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 : 5/5
.128013it3a;dv,n2.S5wbcy+14qL: f-up08)_j9eklohrP=[s6(]/mg7050g0J0c0e0b0L0S0y0q0L0e0S0S0Q010c0b0C010406050S0B0X0X0e0O0r040m0M0L0B0@0M0j050W0~1012140|0C04051k1d1n0W1k0|0g0b0h0,0.0:0=0.0j0Y0B0e0Y0J0A0C0r0c0N1b0y0N0b0Y0N0L1P0N0c0`050%0p0L0J1w0/0;011O1Q1S1Q0c1Y1!1W0c0O1l1K0,170S0C0e0j0=0k011$1y010z0)0J0j0e0X0J1W1{1}221(251!282a0`0a0y0P0O0M0C0M0S0b1a0j0y0#1_0O0O0J0q2v1d2d0j1l0W1K2I1=1@1?1X0g2f1z0b0j272s1W1t1v0-1%2S2U0j0M2Y1W0C2B1l2G2I2/0}1|2w2!232(0O110L1W0e1N2B0z0=030G0G0q2)0J1S2%0M0A0t3d0`0y0t1d0e2:2?0{2=2e2^1(2`2|2~300J32013436383a2V3d0A20040y0k3j3l1}3n2G2R013s0e2}1l2 0N313335370#3C2(3E0d3g0d3K2F3m0|3O3q0=3R3T053V3X3y3Z3B2T3D3e0u3g0u3,1e3.3o2@1x3r0M2{3S3u3W3w3Y3A3#3~3%3e0n3g0n442/3/2?3P3?4e3`3z3!394k3c3e0T3g0T4q463:493=4b3t3U3v3x4y3}3b3E0Z3g0Z4H3M4s3p4K3Q4M4d4O4f4Q3|4j4T3e0E3g0E4Y2H4!482#4%4c3@3_4g3{4i4A4/0A0I3g0I4@3N4t3;4|4N3^4P4h4z3$4C3d0D0`0t0D594_4u4(4~5g515i4B3E0t0t5n3i0W3k3-4Z475s4}4w504R4.3 3d3G0t3J5E3L4^5I5c4v4*4x4-535P0t3)045)5q5X4$5Z5f4+5h4S5(415+435U5G5W4J4{5:4 4,525j5z4n5+4p5|455H5 2_5t5L635x540t4E5+4G6a4r5.606f5!5M5$653e0t4V5+4X6o4I5b5/6s5;5#645y6x4;5+4?6C6c6E6r5K6t6h5@4l3d565+586P5~6R6e6T6H6u6J540k5m046/5-6d4a6*625?5O6X0k5B6;5D5F6b6%4#6S5e6`5w6W5k0k3G7c6?6(6^775v5N5%6}5*0k3+6$5a756)7i5=796|7b5_0k5{726p6@4L6_7j6v6K3F670k697C6D7s7h4)6+6V7x3E0k6l7X7f7Q7F7u6I6i5P0k6z7+7!4`7t7S787k6w3F6M0k6O7O6Q7#5d7;7H6-7*6Z0k6#7|747/7R5u7v7?7J0d6:8f7.5J7%6,7)6X0d6 8o8i5Y6G7=7I540d3G8x591o2-1d2Y2L0g1@2Q5c4z2X1u1l2,0J2.3m5}1l4z8Q2e0b0g0=352G5z3u8X8Z826X5B0y2j0J8)8m5k6 3,7E010K0`0#0z8S6q230o3g8~8^0j0z0`1|0O0@2E738V890=0_040U937g3=0`0w9j7~9g0x8S0y8 3r0p0`1S0S0c9o9e019g0i9s9u9l040#0p199B3P9q9G949w042T9A9c9H9D0`9F9c9t940`251c9W8^9P9#9X0j9S9U9N5c9g0F9r9c0|9+4t8(018!2?7W8%8Ya08*7b218.8:7aa32I3k0yag9$9k8_8{3w9?4$913Han6096042C0N1}1Far239g9i9}7~0j9maz1(9EaH9I0baK9Y049!2;9%040HaN9^9`6paD2w9 a11}3(a4ab7V3e3)8-298/a68;a(ae3Haha_9/aGaZ9O0`0RaNaF9TaV0`0VaQ3maiaEa|aRaj9gb0a}5Y0`aUbg4$9g0V9Qaj0M0`0Qboba049nbk4{beb1bib404b6bt9Cb2bwbc9pa bAb3bxaAb58S9|bJa!a5a$0j3E5_5fa#a7bYa9a/a*7l5kbZ5UbS8R3Ob#8#4ma)a;acb@a.2ab*7@673Ka`aS0C1u0M9V2/b99Cbq04bs9.aSbIb:bdbLbO3ral9Lc7chbKbDbR9Nb=a24Db^8v5P4Eb|a:cy6X6lc1aha{042,0M0qaw2T0G2T8}cebpbrbF4ucm9M9{ctbV0Gb?0A6zb!c#a=3e4VcBb~7Jc)5Uc2ajb2cKcM0(0jc$0B0CcV5ccbcdc8cI9)csa}cua%4:cxb$dcc/b_a+0A6McGagcI0e2D0B39d14$d3ds60cXco5Hd9c#c%6Zc*c:5456dgcD5kdDc?cH8^8`040o1O1!dv2_0`do0cdq0LdU1(cb020L0c0fd4b8cIc`cNc}0~d0ck9f0`aX46dA8)c%5oddc,5lb(b}dhb+5z6:dla_c93PdP0bcRd5cfbCbfbTcW04dXdZbCbncS7~d%d)0fd#9Ic40hc6bCd`dzekdabX6x8?2 b#e15Ae3cCde3d8?dMeaeacIavax0JbCaCekbhbvbCb73Mdndpdrd@aOe)2Hebe$d/c|cP95bC0Fd8eEdBcv5Qe0b`f1dIeP5S1WeSeTdNc^972pc{cOcQew01cb0sd,3Me=4$0X0b5ne}cpbUd}f05)f2difyf5eL5*e9fafodweme,d!erca0`flfifqfscZd|a6d~bZeJc+f30t41fCf!b-affa9XdP4Aefd-ehe.bze.b2ene-e#blbQfM3Pd3fme;d.c5dy2H9X9-aYe~fwdb3dc0fYdF5(4nf%fAc0f9fGe+dYf`f:cT04fPf~5cfR5+fte*b;e gc6kfze66xcAaae57@gEa@gndO0`390SeYf=d_gzg6gBgbeG3dc)gfgK7J6yeNgg8+c=f*fGdmaSeW1BgTf{by0`e!fuelcggAciaPbMf_fLg_bPh2gv5/fdcLd:c~d?h6aI0`e|fTgafVfxdkg%dJ5z4;gjgG3ddkgmf+c3fehdd=ficb0Ag1aq8^gx5Dg9g}eF5zdDhpf6dHgJhq6xdLg/fH23dP2BdY0O9*egh1g|h0bu9KcYhgd^h8h)bue@fge`gUh=grh@hAe^hCh{e:hHfc04d7h{hjhLh,fvhmgc6/gF7@ifhtihe8b.c!gZ7WeI0yeKf36~g+g(6.eR5FgP9Jame.ap9tf@at0v0B0b0q0Kc$4bg59da~9hbMg gXh1eCiVaE9S9yiPg7hiiX3nfUbW7W3GdEiw7*20ij7J7cf8hXf,alf/ib3PiEb1iHiJiLiN990G2B0qeZiTeBb1i!0b9ze(fib2h.i$9,9Zji9(2Te{i)b/i~hN3e7oigi@a-hTePjxgNhyajedi}g2aSjkhD0`d(d*joi6jqh{jsinidg!7Ajy6.f$jBe1jYjEg:hYcliBcne_jIiQ9@jnh9fIjk0GeyeAi2jQ9)j`g4jhj@dVjRd;c jMccjQ989a0b1bjaf@bbg}j=h|i~e$jLj}kgk5e{gWiQjv7KjZ7*gij$itglhXgOi5iIiKiM0SiOj72Ckfh:3Qkhklf|kkiYbGdxj/k2h?kUj-19k0eziPj+0=hEaNhJkrhkhMgCjXcFhQj%gIb)i:6}cFhxeTcIkFj4kIj6j8kMkihae%kokNb2j j{k(9XfkfQfrgylah}kZj i1kN9^ks5Iku7+kw6}c.kzdilvj)k)kO04l1kHkJl5h{h+kTg~kXl74{gx5pllfn9/i!27l6kQfIiUj;kRi9lmf 0`0AlifSlqhilsgYjW7WhoirfZlAhslzhu7`i_i*hli,jwhPl_g,7bhSk`hU3FhWm1k:ioa,e8k@f38fivmbmla@jtlMku8olw5kmti?8wiyl$4{0Kb20b0X2r99aNj0f@b20O1}0g0M0XmI92e.dP0/mRaqmK0`0O0gl;9~k;3(i.mjdi8xmmePm-a@dn0G1=0b0J0Ok8hGlDf?kYelm!aNcb0lbMmM0j1t0jjlh*k,ljhKlPh7i39XhJ0DlSl/04l(lUiA0z4bjQ0GhDapjSm 5Y9Sn6aylKnc5nnknlnfhhnnfibmls0W8U8B8P8D8M1d0c8GnU2O2J0e1ZnR0W8E9|0#0%0)0S04.

Diviser pour régner et multiplications⚓︎

D'après Wikipédia

Pour multiplier deux nombres de n chiffres, la méthode naïve multiplie chaque chiffre du multiplicateur par chaque chiffre du multiplicande. Cela exige donc \(n^2\) produits de deux chiffres. Le temps de calcul est en \(\mathcal{O}(n^2)\).

En 1960, Karatsuba remarque que pour tout k, le calcul naïf d'un produit :

\(p\times q = (a\times 10^{k}+b)(c\times 10^{k}+d)=ac\times 10^{2k}+(ad+bc)\times 10^{k}+bd\)

est une utilisation de la méthode diviser pour régner : elle effectue 4 multiplications avec des instances de taille environ \(n / 2\). Mais cela ne fait pas gagner en complexité, en effet \(4\times \mathcal{O}((n/ 2)^2) = \mathcal{O}(n^2)\)

Si cette multiplication semble nécessiter les quatre produits \(ac\), \(ad\), \(bc\) et \(bd\), elle peut en fait être effectué seulement avec les trois produits \(ac\), \(bd\) et \((a – b)(c – d)\) en regroupant les calculs sous la forme suivante :

\((a\times 10^{k}+b)(c\times 10^{k}+d)=ac\times 10^{2k}+(ac+bd-(a-b)(c-d))\times 10^{k}+bd\)

Ainsi en calculant et mémorisant \(ac\) et \(bd\), il n y a avec cette méthode que 3 multiplications à effectuer. (les soustractions sont effectués en \(\mathcal{O}(n)\)

Complète le code qui permet de calculer le produit de \(m\) par \(n\)

avec \(m = a\times 10^{k}+b\) avec \(k\) partageant n, tels que \(a\) et \(b\) aient le nombre de chiffres le plus proches.

\(n = c\times 10^{k}+d\)

Astuces
  • le nombre de chiffres de l'écriture décimale d'un nombre m est égal à int(math.log10(n)) + 1
  • utiliser % 10 ** k et // 10 ** k pour calculer a,b,c,d.

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

###(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 : 5/5

.128013it3adv,n2.S5wb*cy+14: f-up08)_9ekl%ohrP=s6(/mg7050f0G0c0e0b0I0P0w0q0I0e0P0P0O010c0b0A010406050P0z0T0T0e0M0r040l0K0I0z0:0K0i050S0`0|0~100^0A04051g191j0S1g0^0f0b0g0(0*0,0.0*0i0U0z0e0U0G0y0A0r0c0L170w0L0b0U0L0I1L0L0c0?050Z0o0I0G1s0+0-011K1M1O1M0c1U1W1S0c0M1h1G0(130P0A0e0i0.0j011Y1u010x0#0G0i0e0T0G1S1@1_1~1!211W24260?0a0w0N0M0K0A0K0P0b160i0w0X1=0M0M0G0q2r19290i1h0S1G2E1.1:1/1T0f2b1v0b0i232o1S1p1r0)1Z2O2Q0i0K2U1S0A2x1h2C2E2+0_1^2s2W1 2!0M0}0I1S0e1J2x0x0.030E0E0q2#0G1O2Z0K0y0j0y0t0?0w0t190e2,2/0@2.2a2;1!2?2^2`2|0G2~01303234362R39393d0j3g3i1_3k2C2N013p0e2_1h2{0L2}2 31330X3z2!3B0d3d0d3F2B3j0^3J3n0.3M3O053Q3S3v3U3y2P3A3a0u3d0u3%1a3)3l2:1t3o0K2@3N3r3R3t3T3x3W3_3Y3a0m3d0m3 2+3*2/3K3.493=3w3V354f383a0Q3d0Q4l413+443-463q3P3s3u4t3^373B0V3d0V4C3H4n3m4F3L4H484J4a4L3@4e4O3a0C3d0C4T2D4V432X4Y473/3;4b3?4d4v4*0y0F3d0F4/3I4o3,4@4I3:4K4c4u3X4x3b0B0?0t0B544;4p4Z4_5b4|5d4w3B0t3c045v5l425n4^4r4{4M4)3`3b1|5x3E0S3h3(4U5A574q4#4s4(4~5H0t3!5x3$5M3G4:5Q4X5S5a4$5c4N5X3|5x3~5$5O5(4E4?5+4`4%4}5e5u4i5x4k5@403H1k2)192U2H0f1:2M574u2T1q1h2(0G2*3j5^1h4u6n2a0b0f0.312C5u3r6u6w5 5t3a3c0w2f0G6C5s4 5w3%5`1 0H0i0?0b0T2n0M0c6p5)4?0n3d6Z6P3o6S040}1G6p0^662D5A6B016x2/3B5J5a6@5V603a1|6H256J6^6D4 6|5$6:2-3J6~0E6y3a5Z6}6v766L5H3!73266K5/4g0y7i5@6)0.0H0?0X0x6(564X6$040w7D4W5{0x0?0T0z0I0:0E0H0~0e0c0`0o0e7J4=1 0=040R7!4p7N7*577%0h7-5*0?186;6s7#1!7%0D0v6/7*7e7g0y5;7j7r5G7t3|7p756 6E831S5$0w8h7I7x3L7?0o321K0x0x2x0P6p8j7E4?0K0?0O8u6!2=0o6T0i6Y7^8C7{0?7)8I8k6+6-0L7;8x0?0k8S2=0?0I0K0U5j8W8K7(8%3-7,8N8w7$0?0D0D8B8k8y040s8?8.1!0T0b5i7 8-6t7k6_1_3B62857l7s5f4i8a865W7t988g8i8J8+040H8{7K1 8^8A7^8v9q3o8m8o0b8q8s9p7`0.8^0S0S9D3K8~0?5L4m80947f6`4y6A9Q7m7t4z9e9a875f4z2E3h7b6o7d9Q824Q4J7e9W5f4Q9Z8c4 9/3F8i9v9E8l047Z9u9l019s9J5R8,2+9~3K9G9Ia38k7%8M7c8|0.9L5x5kafaka50?0p0pa77=9n8*017|91aj936C824,9:9V9b3B4,9^775HaG9|9k8O0?0oav8T049taaa48PaV9r0?0Ja$8(ai9+aqam8$ap9w9Fasaua;9 6+9o929 aA7^9*679,aE9S509U9f70b6aM9=3B519(7HaRaq6+0qa*a?aXbla07@aZ8@0?9Hboahaya/aobraq8^atboa{aya 9Oa}0w81b55jb79!9g5fbNbbaJ6F5hbf9}a!7Aboa6a_7+04bq3jab578^a)b%7.8Lbx8 anb#a@bE0?a|aCa~8:aBa-aD76825vbO9_5X6G6Ib88dc6bfb16=b3c4bM6|2{9;bU5I1}cbbPb90t793hbYaSa1bkbJb-8zb{a1b_04a^bAa=a0cAbIb~bK9-bM7icmaI9#5u7ocrc87t5Y8fcwbhcK6+0o0fcGaYb+bZ04aUb:4XbCcEc,b09Pb4966F84cTcc6M89cYaNc!847ac|cjc~3b98d1cscd9dd5bc6F9ic%8ha47z042x0c0z0Mb*3Hb,aw0ecMc/bscHbvb=cB4XbycGbDc?4?bwdH4?am9NdCbBascEb}c2b 048;cG8`dM8/8)dP8Xczd$cEc+cG0ydFd*cOa8cFd(1!8^d=d+9xc;bGc0d{bmcIdTcKdOd^awdBdxa4d}c_e2d!8=e4ardEeke9dY9Kb@a:cJ9 bCe6edcydXb2aqbHe7eu0?d%etb(d:c{8I0S6r686m6a6j190c6deS2K2F0e1VeP0S6b6:0X0Z0#0P04.