From d4f8e7665e6f0ea3794218820c72b6ac505cf06a Mon Sep 17 00:00:00 2001 From: Xavier Dupre Date: Thu, 29 Aug 2024 16:45:01 +0200 Subject: [PATCH 1/3] Add feuille de route 2024 --- _doc/articles/2022/2022-01-01-assurance.rst | 4 +- _doc/articles/2023/2023-11-31-route2023.rst | 2 +- _doc/articles/2024/2024-09-04-ensae.rst | 69 ++++++++++++++++++ _doc/articles/2024/2024-11-31-route2024.rst | 32 ++++++++ _doc/articles/2024/sudoku.png | Bin 0 -> 49413 bytes _doc/articles/index.rst | 1 + _doc/examples/prog/plot_einstein_riddle.py | 61 ++++++++-------- .../prog/plot_float_and_double_rouding.py | 10 +-- _doc/examples/prog/plot_gil_example.py | 10 +-- _doc/examples/prog/plot_hypercube.py | 28 +++---- _doc/examples/prog/plot_lambda_function.py | 10 +-- _doc/examples/prog/plot_matador.py | 2 +- _doc/examples/prog/plot_pandas_groupby.py | 2 +- _doc/examples/prog/plot_partie_dame.py | 38 +++++----- _doc/examples/prog/plot_tarabiscote.py | 12 +-- _doc/examples/prog/plot_tsp.py | 34 ++++----- _latex/ensae/td_note_2006.py | 13 ++-- _latex/ensae/td_note_2007.py | 8 +- _latex/ensae/td_note_2008.py | 5 +- _latex/ensae/td_note_2009.py | 8 +- _latex/ensae/td_note_2010.py | 28 +++---- _latex/ensae/td_note_2010_rattrape.py | 4 +- _latex/ensae/td_note_2011.py | 2 +- _latex/ensae/td_note_2012.py | 4 +- _latex/ensae/td_note_2012_enonce.py | 14 ++-- _latex/ensae/td_note_2013.py | 10 +-- _latex/ensae/td_note_2013_M.py | 2 +- .../ensae/td_note_2013_novembre_2012_exoM.py | 45 ++++++------ .../ensae/td_note_2013_novembre_2012_exoS.py | 8 +- _latex/ensae/td_note_2013_preparation1.py | 2 +- _latex/ensae/td_note_2013_preparation1c.py | 2 +- _latex/ensae/td_note_2013_r.py | 25 +++---- _latex/ensae/td_note_2013_rattrapage.py | 15 ++-- .../ut_examples/test_classique_permutation.py | 8 +- _unittests/ut_faq/test_faq_missing.py | 2 +- _unittests/ut_practice/test_rue_paris.py | 2 +- _unittests/ut_practice/test_tsp_bresenham.py | 4 +- _unittests/ut_tools/test_graphviz.py | 2 +- .../test_documentation_examples.py | 4 +- .../test_documentation_notebook.py | 6 +- pyproject.toml | 32 +++++++- teachpyx/datasets/wines.py | 5 +- teachpyx/examples/classiques.py | 1 - teachpyx/examples/construction_classique.py | 12 +-- teachpyx/ext_test_case.py | 9 +-- teachpyx/faq/faq_geo.py | 18 +++-- teachpyx/faq/faq_python.py | 9 +-- teachpyx/practice/rues_paris.py | 15 +++- teachpyx/practice/tsp_kohonen.py | 14 ++-- teachpyx/practice/tsp_kruskal.py | 36 ++++----- teachpyx/tools/blockdiag_helper.py | 13 ++-- teachpyx/tools/display/pygame_helper.py | 2 +- teachpyx/tools/profiling.py | 4 +- teachpyx/video/tsp_kruskal_pygame.py | 10 +-- 54 files changed, 424 insertions(+), 294 deletions(-) create mode 100644 _doc/articles/2024/2024-09-04-ensae.rst create mode 100644 _doc/articles/2024/2024-11-31-route2024.rst create mode 100644 _doc/articles/2024/sudoku.png diff --git a/_doc/articles/2022/2022-01-01-assurance.rst b/_doc/articles/2022/2022-01-01-assurance.rst index 3f8f25fc..3bfeaad0 100644 --- a/_doc/articles/2022/2022-01-01-assurance.rst +++ b/_doc/articles/2022/2022-01-01-assurance.rst @@ -1,6 +1,6 @@ -Assurance auto -============== +2022 - Assurance auto +===================== J'avoue que je ne savais pas trop où allait partir cette séance de cours quand je l'ai commencée avec seulement diff --git a/_doc/articles/2023/2023-11-31-route2023.rst b/_doc/articles/2023/2023-11-31-route2023.rst index 1c17fc25..4d79ad9e 100644 --- a/_doc/articles/2023/2023-11-31-route2023.rst +++ b/_doc/articles/2023/2023-11-31-route2023.rst @@ -1,4 +1,4 @@ -_l-feuille-route-2023: +.. _l-feuille-route-2023: 2023-11-31 : rappel feuille de route 2023 ========================================= diff --git a/_doc/articles/2024/2024-09-04-ensae.rst b/_doc/articles/2024/2024-09-04-ensae.rst new file mode 100644 index 00000000..4b67604a --- /dev/null +++ b/_doc/articles/2024/2024-09-04-ensae.rst @@ -0,0 +1,69 @@ +2024-09-04 : ENSAE +================== + +**Notions à maîtriser** + +* éléments de bases du langages (boucles, listes, tests, fonctions) +* classes (attributes, méthodes, opérateurs, héritages) +* graphes, arbre +* numpy (opérations standard, broadcasting) +* format de données (JSON, XML, HTML, csv) +* tests unitaires (package unittest, git, pull request) +* algorithmes + * tri fusion + * recherche dichotomique + * graphes (composantes connexes, Kruskal, ...) + * programmation dynamique (chemin plus court dans un graphe, distance d'édition) + * problème NP-complet tels que le voyageur de commerce + +**Notions non abordées** + +Elles le seront en seconde année et non en première année : manipulation de données, pandas, machine learning. + +**Evaluation** + +1 TD noté. Les classes seront abordées et un problème algorithmique. +Voir aussi les précédents énoncés : :ref:`l-exams`. + +**Ressources** + +* Ce site : `sdpython.github.io/doc/teachpyx/dev/ `_ +* :ref:`l-book-python` +* exercices sur le langage :ref:`l-python` +* exercices sur des algortihmes :ref:`l-algo` +* examens passés :ref:`l-exams` +* :ref:`Plan suivi en 2023 ` +* `Des aspects plus mathématiques d'algorithmes `_ + +**Problème** + +Comment écrire un algorithme capable de créer une grille de sudoku ? + +.. image:: sudoku.png + +**Getting Started** + +* `cheat sheet python `_ +* `Anaconda `_, + `miniconda `_, + `mamba `_ +* `Visual Studio Code `_ +* `git `_, `github `_ +* `notebook `_ + +**Sujets connexes** + +* Open source et économie du logiciel... +* Ingéniérie logicielle ou comment produire un logiciel fiable en collaboration... +* Notion de `test unitaire `_, + `intégration continue `_. + +**Demain** + +* Intelligence artificielle et puissance de calcul, NVidia +* Objets connectés... +* Quantique... + +**Hier** + +:ref:`l-feuille-route-2023` diff --git a/_doc/articles/2024/2024-11-31-route2024.rst b/_doc/articles/2024/2024-11-31-route2024.rst new file mode 100644 index 00000000..7193fd3a --- /dev/null +++ b/_doc/articles/2024/2024-11-31-route2024.rst @@ -0,0 +1,32 @@ +2024-11-31 : rappel feuille de route 2024 +========================================= + +Séance 1 +++++++++ + +Séance 2 +++++++++ + +Séance 3 +++++++++ + +Séance 4 +++++++++ + +Séance 5 +++++++++ + +Séance 6 +++++++++ + +Séance 7 +++++++++ + +Séance 8 +++++++++ + + +TD noté 1h30 en seconde partie. +Classes et un algorithme. +Enoncés des années précédentes : +:ref:`l-exams`. diff --git a/_doc/articles/2024/sudoku.png b/_doc/articles/2024/sudoku.png new file mode 100644 index 0000000000000000000000000000000000000000..a9e1c7e17ed85516c5a22894672b88f9f7e2df4b GIT binary patch literal 49413 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

F8oY?+GUKcthjkE~pPL`&^=y!_hN`U5Cck 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 literal 0 HcmV?d00001 diff --git a/_doc/articles/index.rst b/_doc/articles/index.rst index 5f51f0c7..42e95b81 100644 --- a/_doc/articles/index.rst +++ b/_doc/articles/index.rst @@ -9,6 +9,7 @@ Ou *blog*. :caption: 2024 :maxdepth: 1 + 2024/2024-11-31-route2024 2024/2024-03-01-route2024 2024/2024-01-18-wsl diff --git a/_doc/examples/prog/plot_einstein_riddle.py b/_doc/examples/prog/plot_einstein_riddle.py index e3560abd..da1de5f9 100644 --- a/_doc/examples/prog/plot_einstein_riddle.py +++ b/_doc/examples/prog/plot_einstein_riddle.py @@ -11,12 +11,12 @@ Implémentatin d'une solution à base de règles. Je la reproduis ici : - -Il y a cinq maisons de cinq couleurs différentes. Dans chacune de ces maisons, -vit une personne de nationalité différente. + +Il y a cinq maisons de cinq couleurs différentes. Dans chacune de ces maisons, +vit une personne de nationalité différente. Chacune de ces personnes boit une boisson différente, fume un cigare différent et a un animal domestique différent. - + 1. L'Anglais vit dans la maison rouge. 2. Le Suédois a des chiens. 3. Le Danois boit du thé. @@ -32,58 +32,57 @@ 13. L'Allemand fume des prince. 14. Le Norvégien vit juste à côté de la maison bleue. 15. L'homme qui fume des Blend a un voisin qui boit de l'eau. - + **Question : Qui a le poisson ?** - + Après quelques essais, une bonne feuille de papier, on arrive à -reconstituer la solution après de nombreuses déductions logiques +reconstituer la solution après de nombreuses déductions logiques et quelques essais. On peut voir aussi ce jeu comme un puzzle : chaque configuration est un pièce du puzzle dont la forme des bords est définie par toutes ces règles. Il faut trouver le seul emboîtement -possible sachant que parfois, une pièce peut s'emboîter avec plusieurs +possible sachant que parfois, une pièce peut s'emboîter avec plusieurs mais qu'il n'existe qu'une façon de les emboîter toutes ensemble. Ecrire un programme qui résoud ce problème revient à s'intéresser à deux problèmes : - + 1. Comment définir une pièce du puzzle ? 2. Comment parcourir toutes les combinaisons possibles ? - + Chaque règle ou pièce de puzzle peut être exprimer comme une `clause `_. -Pour notre problème, chaque pièce du puzzle est simplement décrite par +Pour notre problème, chaque pièce du puzzle est simplement décrite par un attribut (rouge, norvégien) et un numéro de maisons (1 à 5). Les règles définissent la compatibilité de deux pièces. On peut regrouper ces règles en cinq catégories : - + 1. Un attribut est à la position p (règle 9). 2. Deux attributs sont équivalents (règle 1). 3. Deux attributs sont voisins (règle 11). 4. Deux attributs sont ordonnés par rapport aux positions (règle 4). 5. Deux attributs font partie du même ensemble et sont exclusives : on ne peut pas être l'un et l'autre à la fois (rouge et jaune par exemple). - -Une fois que chaque règle a été exprimée dans une de ces cinq catégories, + +Une fois que chaque règle a été exprimée dans une de ces cinq catégories, il faut définir l'association de deux règles (ou clause) pour former une clause plus complexe. Trois cas possibles : - + 1. Deux clauses sont compatibles : on peut avoir l'une et l'autre. 2. Deux clauses sont incompatibles : on ne peut avoir l'une et l'autre. - -Dans le premier cas, la clause résultante est simplement qu'on peut la clause A -et la clause B : :math:*A* et *B*. Dans le second cas, il existe deux + +Dans le premier cas, la clause résultante est simplement qu'on peut la clause A +et la clause B : *A* et *B*. Dans le second cas, il existe deux possibilités, on peut avoir l'une et l'opposé de l'autre ou l'inverse : -:math:`(A \, et\, non \, B) \, ou\, (non \, A \, et\, B)`. +:math:`(A \\, et\\, non \\, B) \\, ou\\, (non \\, A \\, et\\, B)`. -Avec cette description, il est plus facile d'exprimer le problème avec des +Avec cette description, il est plus facile d'exprimer le problème avec des objets informatiques ce que fait le programme suivant. Il explicite ensuite toutes les configurations compatibles avec une règle donnée (mais pas toutes ensembles). - + .. note:: L'énigme d'Einstein est une énigme comme celle que résoud Hermionne dans le premier tome de Harry Potter (voir :ref:`l-enigme-hermionne`). - On commence par la fonction `permutation`: qui énumère les permutations d'un ensemble : @@ -100,7 +99,7 @@ def permutation(nb): per = [] - p = [i for i in range(0, nb)] + p = list(range(nb)) while p[0] < nb: cont = False for i in range(1, nb): @@ -263,7 +262,7 @@ def genere(self): overrides method ``genere`` """ li = [] - for i in range(0, 5): + for i in range(5): li.append([(i, self.set[0]), (i, self.set[1])]) return li @@ -282,7 +281,7 @@ def genere(self): overrides method ``genere`` """ li = [] - for i in range(0, 4): + for i in range(4): li.append([(i, self.set[0]), (i + 1, self.set[1])]) li.append([(i + 1, self.set[0]), (i, self.set[1])]) return li @@ -303,7 +302,7 @@ def genere(self): """ li = [] for j in range(1, 5): - for i in range(0, j): + for i in range(j): li.append([(i, self.set[0]), (j, self.set[1])]) return li @@ -325,7 +324,7 @@ def genere(self): per = permutation(5) for p in per: tl = [] - for i in range(0, len(p)): + for i in range(len(p)): tl.append((i, self.set[p[i]])) li.append(tl) return li @@ -337,7 +336,7 @@ def genere(self): def find(p): - for i in range(0, len(ensemble)): + for i in range(len(ensemble)): if p in ensemble[i]: return (p, i) return None @@ -447,14 +446,14 @@ def find(self, p): :param p: clause :return: tuple (clause, position) """ - for i in range(0, len(ensemble)): + for i in range(len(ensemble)): if p in ensemble[i]: return (p, i) return None def to_dataframe(self): sr = [] - matrix = [list(" " * 5) for _ in range(0, 5)] + matrix = [list(" " * 5) for _ in range(5)] for row in self.solution: i = row[0] j = row[1][1] @@ -465,7 +464,7 @@ def to_dataframe(self): text = "\n".join(sr) return pandas.read_csv(StringIO(text), header=None) - def solve(self, solution=[], logf=print): # solution = [ ]) : + def solve(self, solution=[], logf=print): # noqa: B006 """ Solves the enigma by eploring in deepness, the method is recursive diff --git a/_doc/examples/prog/plot_float_and_double_rouding.py b/_doc/examples/prog/plot_float_and_double_rouding.py index 95fe5ffa..d6d09f1f 100644 --- a/_doc/examples/prog/plot_float_and_double_rouding.py +++ b/_doc/examples/prog/plot_float_and_double_rouding.py @@ -3,15 +3,15 @@ ================ Float Conversion ================ - -I came up with the following question -:math:`(float64)x < (float64)y \Longrightarrow (float32) x < (float32)y`? + +I came up with the following question +:math:`(float64)x < (float64)y \\Longrightarrow (float32) x < (float32)y`? What is the probability this holds? Probability (float64)x == (float32)x ==================================== -Let's evaluate how many time we draw a random double +Let's evaluate how many time we draw a random double number equal to its float conversion. """ @@ -66,7 +66,7 @@ # We finally check that double operations between float numpers remain floats. -for i in range(0, 100000): +for i in range(100000): i, j = random.randint(0, len(rnd32) - 1), random.randint(0, len(rnd32) - 1) d32 = numpy.float64(rnd32[i] * rnd32[j]) d64 = numpy.float64(rnd32[i]) * numpy.float64(rnd32[j]) diff --git a/_doc/examples/prog/plot_gil_example.py b/_doc/examples/prog/plot_gil_example.py index 935cf4c6..4e64c814 100644 --- a/_doc/examples/prog/plot_gil_example.py +++ b/_doc/examples/prog/plot_gil_example.py @@ -5,15 +5,15 @@ ====== Le GIL -====== +====== Le GIL ou `Global Interpreter Lock `_ -est un verrou unique auquel l'interpréteur Python fait appel constamment +est un verrou unique auquel l'interpréteur Python fait appel constamment pour protéger tous les objets qu'il manipule contre des accès concurrentiels. Deux listes en parallel ======================= - + On mesure le temps nécessaire pour créer deux liste et comparer ce temps avec celui que cela prendrait en parallèle. """ @@ -39,7 +39,7 @@ def create_list(n): def run2(nb): with ThreadPoolExecutor(max_workers=2) as executor: - for res in executor.map(create_list, [nb, nb + 1]): + for _res in executor.map(create_list, [nb, nb + 1]): pass @@ -74,7 +74,7 @@ def attendre(t=0.009): def run3(t): with ThreadPoolExecutor(max_workers=2) as executor: - for res in executor.map(attendre, [t, t + 0.001]): + for _res in executor.map(attendre, [t, t + 0.001]): pass diff --git a/_doc/examples/prog/plot_hypercube.py b/_doc/examples/prog/plot_hypercube.py index c1c06fb0..3c1fc300 100644 --- a/_doc/examples/prog/plot_hypercube.py +++ b/_doc/examples/prog/plot_hypercube.py @@ -11,7 +11,7 @@ Q1 - triple récursivité ======================= - + Réécrire la fonction ``u`` de façon à ce qu'elle ne soit plus récurrente. """ @@ -237,7 +237,7 @@ def hyper_cube_liste(n, m=None): def hyper_cube_dico(n): r = {} - ind = [0 for i in range(0, n)] + ind = [0 for i in range(n)] while ind[0] <= 1: cle = tuple(ind) # conversion d'une liste en tuple r[cle] = 0 @@ -276,7 +276,7 @@ def occurrence(li, n): def occurrence(tu, n): d = hyper_cube_dico(n) - for i in range(0, len(tu) - n): + for i in range(len(tu) - n): cle = tu[i : i + n] d[cle] += 1 return d @@ -291,7 +291,7 @@ def occurrence(tu, n): def occurrence2(tu, n): d = {} - for i in range(0, len(tu) - n): + for i in range(len(tu) - n): cle = tu[i : i + n] if cle not in d: d[cle] = 0 @@ -312,10 +312,10 @@ def occurrence2(tu, n): def occurrence3(li, n): d = hyper_cube_liste(n) - for i in range(0, len(li) - n): + for i in range(len(li) - n): cle = li[i : i + n] t = d # - for k in range(0, n - 1): # point clé de la fonction : + for k in range(n - 1): # point clé de la fonction : t = t[cle[k]] # accès à un élément t[cle[n - 1]] += 1 return d @@ -328,7 +328,7 @@ def occurrence3(li, n): # Une autre écriture... -def hyper_cube_liste2(n, m=[0, 0], m2=[0, 0]): +def hyper_cube_liste2(n, m=[0, 0], m2=[0, 0]): # noqa: B006 if n > 1: m[0] = list(m2) m[1] = list(m2) @@ -339,11 +339,11 @@ def hyper_cube_liste2(n, m=[0, 0], m2=[0, 0]): def occurrence4(li, n): d = hyper_cube_liste2(n) # * remarque voir plus bas - for i in range(0, len(li) - n): + for i in range(len(li) - n): cle = li[i : i + n] t = d # - for k in range(0, n - 1): # point clé de la fonction : - t = t[cle[k]] # accès à un élément + for k in range(n - 1): # point clé de la fonction : + t = t[cle[k]] # accès à un élément t[cle[n - 1]] += 1 return d @@ -355,7 +355,7 @@ def occurrence4(li, n): # Et si on remplace ``list(m2)`` par ``m2``. -def hyper_cube_liste3(n, m=[0, 0], m2=[0, 0]): +def hyper_cube_liste3(n, m=[0, 0], m2=[0, 0]): # noqa: B006 if n > 1: m[0] = m2 m[1] = m2 @@ -366,11 +366,11 @@ def hyper_cube_liste3(n, m=[0, 0], m2=[0, 0]): def occurrence5(li, n): d = hyper_cube_liste3(n) # * remarque voir plus bas - for i in range(0, len(li) - n): + for i in range(len(li) - n): cle = li[i : i + n] t = d # - for k in range(0, n - 1): # point clé de la fonction : - t = t[cle[k]] # accès à un élément + for k in range(n - 1): # point clé de la fonction : + t = t[cle[k]] # accès à un élément t[cle[n - 1]] += 1 return d diff --git a/_doc/examples/prog/plot_lambda_function.py b/_doc/examples/prog/plot_lambda_function.py index 7ad4fdf4..29261fa9 100644 --- a/_doc/examples/prog/plot_lambda_function.py +++ b/_doc/examples/prog/plot_lambda_function.py @@ -27,19 +27,19 @@ def oneargs(x): ################ # Et dans une liste, cela donne ce qui suit. -print([oneargs(a) for a in range(0, 3)]) +print([oneargs(a) for a in range(3)]) ####################### # Dans le cas présent, cela revient à écrire cela # ce qui est quand même plus simple. -fcts = [a + 5 for a in range(0, 3)] +fcts = [a + 5 for a in range(3)] print(fcts) ####################### # Ou encore... -fcts = [oneargs(a) for a in range(0, 3)] +fcts = [oneargs(a) for a in range(3)] print(fcts) ####################### @@ -48,7 +48,7 @@ def oneargs(x): # La première liste définit le calcul dans des # lambda fonctions. La seconde les exécute. -fcts_a = [lambda: oneargs(a) for a in range(0, 3)] +fcts_a = [lambda: oneargs(a) for a in range(3)] # noqa: B023 fcts_b = [f() for f in fcts_a] print(fcts_b) @@ -62,6 +62,6 @@ def oneargs(x): # Une solution consiste à conserver chaque valeur # distincte de a dans une valeur par défaut. -fcts_a = [lambda a=a: oneargs(a) for a in range(0, 3)] +fcts_a = [lambda a=a: oneargs(a) for a in range(3)] fcts_b = [f() for f in fcts_a] print(fcts_b) diff --git a/_doc/examples/prog/plot_matador.py b/_doc/examples/prog/plot_matador.py index 2f8b3fde..ff31e4d9 100644 --- a/_doc/examples/prog/plot_matador.py +++ b/_doc/examples/prog/plot_matador.py @@ -25,7 +25,7 @@ total = 28 solution = [] -parentheses = [(i, j) for i in range(0, 3) for j in range(i + 1, 4)] +parentheses = [(i, j) for i in range(3) for j in range(i + 1, 4)] # permutations sur les nombres for pn in permutations(nombres): diff --git a/_doc/examples/prog/plot_pandas_groupby.py b/_doc/examples/prog/plot_pandas_groupby.py index 44da9176..34c74a7f 100644 --- a/_doc/examples/prog/plot_pandas_groupby.py +++ b/_doc/examples/prog/plot_pandas_groupby.py @@ -3,7 +3,7 @@ ================= Pandas et groupby ================= - + Petit tour de passe passe autour d'un :meth:`pandas.DataFrame.groupby` et des valeurs manquantes qui ne sont plus prises en compte depuis les dernières versions. diff --git a/_doc/examples/prog/plot_partie_dame.py b/_doc/examples/prog/plot_partie_dame.py index aca73568..0698277d 100644 --- a/_doc/examples/prog/plot_partie_dame.py +++ b/_doc/examples/prog/plot_partie_dame.py @@ -9,19 +9,19 @@ Exercice de programmation sur les tableaux. -Q1 +Q1 == - -Une partie de dames met en jeu quarante pions, vingt noirs, vingt blancs, + +Une partie de dames met en jeu quarante pions, vingt noirs, vingt blancs, chacun sur des cases différentes. L'objectif est de savoir si un pion est en mesure d'en prendre un autre. On ne traitera pas le cas des dames. Chaque pion est défini par : - + * deux coordonnées entières, chacune comprise entre 1 et 10 * une couleur, noir ou blanc On propose deux représentations de l'ensemble de pions : - + * Un tableau de 40 pions indicés de 0 à 39 inclus, chaque pion étant défini par : * deux coordonnées comprises entre 1 et 10, ou (0,0) si le pion n'est plus sur le damier @@ -31,7 +31,7 @@ * soit 1 si la case contient un pion blanc * soit 2 si la case contient un pion noir -Y a-t-il d'autres représentations de ces informations ? Si on considère +Y a-t-il d'autres représentations de ces informations ? Si on considère que l'efficacité d'une méthode est reliée à sa vitesse - autrement dit aux coûts des algorithmes qu'elles utilisent -, parmi ces deux représentations, quelle est celle qui semble la plus efficace pour savoir si un pion donné @@ -41,34 +41,34 @@ La seconde représentation sous forme de tableau à deux dimensions est plus pratique pour effectuer les tests de voisinages. Chaque case a -quatre voisines aux quatre coins, il est ensuite facile de déterminer +quatre voisines aux quatre coins, il est ensuite facile de déterminer si ces quatre voisines sont libres ou si elles contiennent un pion. On sait rapidement le contenu d'une case. - + Avec la première représentation - le tableau des pions - pour savoir s'il existe un pion dans une case voisine, il faut passer en revue tous les pions pour savoir si l'un d'eux occupe ou non cette case. -Avec la seconde représentation - le tableau à deux dimensions - -on accède directement à cette information sans avoir à la rechercher. +Avec la seconde représentation - le tableau à deux dimensions - +on accède directement à cette information sans avoir à la rechercher. On évite une boucle sur les pions avec la seconde représentation. Q2 == Comment représenter un tableau d'entiers à deux dimensions en -langage python à l'aide des types standards qu'il propose, +langage python à l'aide des types standards qu'il propose, à savoir t-uple, liste ou dictionnaire ? **réponse** Pour représenter le tableau en deux dimensions, il existe trois solutions : -* Une liste de listes, chaque ligne est représentée par une liste. +* Une liste de listes, chaque ligne est représentée par une liste. Toutes ces listes sont elles-mêmes assemblées dans une liste globale. * Une seule liste, il suffit de numéroter les cases du damier de 0 à 99, en utilisant comme indice pour la case :math:`(i,j)` : :math:`k = 10*i+j`. - Réciproquement, la case d'indice $k$ aura pour coordonnées - :math:`(k / 10, \, k \% 10)`. + Réciproquement, la case d'indice $k$ aura pour coordonnées + :math:`(k / 10, \\, k \\% 10)`. * Un dictionnaire dont la clé est un couple d'entiers. Q3 @@ -76,17 +76,17 @@ On cherche à écrire l'algorithme qui permet de savoir si un pion donné est un mesure de prendre un pion. Quels sont les paramètres -d'entrées et les résultats de cet algorithme ? +d'entrées et les résultats de cet algorithme ? **réponse** On désire savoir si le pion de la case :math:`(i,j)` -peut en prendre un autre. On suppose que le tableau à deux dimensions +peut en prendre un autre. On suppose que le tableau à deux dimensions est une liste de dix listes appelée ``damier``. ``damier[i][j]`` -est donc la couleur du pion de la case :math:`(i,j)`, +est donc la couleur du pion de la case :math:`(i,j)`, à savoir 0 si la case est vide, 1 si le pion est blanc, 2 si le pion est noir. -Pour ces deux derniers cas, la couleur des pions de l'adversaire sera donc -``3 - damier[i][j]``. Les entrées de la fonctions sont donc les indices +Pour ces deux derniers cas, la couleur des pions de l'adversaire sera donc +``3 - damier[i][j]``. Les entrées de la fonctions sont donc les indices ``i``, ``j`` et le damier ``damier``. La sortie est une variable booléenne qui indique la possibilité ou non de prendre. On ne souhaite pas déplacer les pions. diff --git a/_doc/examples/prog/plot_tarabiscote.py b/_doc/examples/prog/plot_tarabiscote.py index f7bce5dc..a68fbaba 100644 --- a/_doc/examples/prog/plot_tarabiscote.py +++ b/_doc/examples/prog/plot_tarabiscote.py @@ -13,7 +13,7 @@ =============== La fonction ``somme`` est censée faire la concaténation de toutes les -listes contenues dans ``ens``. Le résultat retourné est effectivement +listes contenues dans ``ens``. Le résultat retourné est effectivement celui désiré mais la fonction modifie également la liste ``ens``, pourquoi ? """ import math @@ -60,7 +60,7 @@ def somme(tab): def somme(tab): li = [] ###### ligne modifiée - for i in range(0, len(tab)): ###### ligne modifiée + for i in range(len(tab)): ###### ligne modifiée li += tab[i] return li @@ -79,7 +79,7 @@ def somme(tab): li = ["un", "deux", "trois", "quatre", "cinq"] -for i in range(0, len(li)): +for i in range(len(li)): mi = i for j in range(i, len(li)): if li[mi] < li[j]: @@ -98,7 +98,7 @@ def somme(tab): li = ["un", "deux", "trois", "quatre", "cinq"] -for i in range(0, len(li)): +for i in range(len(li)): mi = i for j in range(i, len(li)): if li[mi] < li[j]: @@ -321,7 +321,7 @@ def surface(self): x = 1.0 -for i in range(0, 19): +for i in range(19): x = x / 10 print(i, "\t", 1.0 - x, "\t", x, "\t", x ** (0.5)) @@ -337,7 +337,7 @@ def surface(self): x = numpy.float32(1.0) -for i in range(0, 19): +for i in range(19): x = x / numpy.float32(10) print(i, "\t", 1.0 - x, "\t", x, "\t", x ** (0.5)) diff --git a/_doc/examples/prog/plot_tsp.py b/_doc/examples/prog/plot_tsp.py index b4d0a257..94876e4d 100644 --- a/_doc/examples/prog/plot_tsp.py +++ b/_doc/examples/prog/plot_tsp.py @@ -36,7 +36,7 @@ # Un parcours aléatoire de tous les noeuds de graphe # donnera quelque chose de très éloigné de la solution optimale : -plt.plot(x + [x[0]], y + [y[0]], "o-") +plt.plot([*x, x[0]], [*y, y[0]], "o-") ############################################# @@ -78,7 +78,7 @@ def permutation(x, y, ordre): it += 1 print("iteration", it, "d=", d) d0 = d - for i in range(0, len(ordre) - 1): + for i in range(len(ordre) - 1): for j in range(i + 2, len(ordre)): r = ordre[i:j].copy() r.reverse() @@ -92,8 +92,8 @@ def permutation(x, y, ordre): ordre = permutation(x, y, list(range(len(x)))) print("longueur min", longueur(x, y, ordre)) -xo = [x[o] for o in ordre + [ordre[0]]] -yo = [y[o] for o in ordre + [ordre[0]]] +xo = [x[o] for o in [*ordre, ordre[0]]] +yo = [y[o] for o in [*ordre, ordre[0]]] plt.plot(xo, yo, "o-") ####################################################### @@ -179,8 +179,8 @@ def permutation(x, y, ordre): ordre = permutation(x, y, list(range(len(x)))) print("longueur min", longueur(x, y, ordre)) -xo = [x[o] for o in ordre + [ordre[0]]] -yo = [y[o] for o in ordre + [ordre[0]]] +xo = [x[o] for o in [*ordre, ordre[0]]] +yo = [y[o] for o in [*ordre, ordre[0]]] plt.plot(xo, yo, "o-") plt.text(xo[0], yo[0], "0", color="r", weight="bold", size="x-large") plt.text(xo[-2], yo[-2], "N-1", color="r", weight="bold", size="x-large") @@ -225,8 +225,8 @@ def permutation(x, y, ordre): ordre = permutation(x, y, list(range(len(x)))) print("longueur min", longueur(x, y, ordre)) -xo = [x[o] for o in ordre + [ordre[0]]] -yo = [y[o] for o in ordre + [ordre[0]]] +xo = [x[o] for o in [*ordre, ordre[0]]] +yo = [y[o] for o in [*ordre, ordre[0]]] plt.plot(xo, yo, "o-") plt.text(xo[0], yo[0], "0", color="r", weight="bold", size="x-large") plt.text(xo[-2], yo[-2], "N-1", color="r", weight="bold", size="x-large") @@ -264,7 +264,7 @@ def permutation_rnd(x, y, ordre): print("iteration", it, "d=", d, "ordre[0]", ordre[0]) d0 = d for i in range(1, len(ordre) - 1): - for j in range(i + 2, len(ordre) + 1): + for _j in range(i + 2, len(ordre) + 1): ik = random.randint(1, len(ordre) - 1) il = random.randint(ik + 1, len(ordre)) r = ordre[ik:il].copy() @@ -279,8 +279,8 @@ def permutation_rnd(x, y, ordre): ordre = permutation_rnd(x, y, list(range(len(x)))) print("longueur min", longueur(x, y, ordre)) -xo = [x[o] for o in ordre + [ordre[0]]] -yo = [y[o] for o in ordre + [ordre[0]]] +xo = [x[o] for o in [*ordre, ordre[0]]] +yo = [y[o] for o in [*ordre, ordre[0]]] plt.plot(xo, yo, "o-") plt.text(xo[0], yo[0], "0", color="r", weight="bold", size="x-large") plt.text(xo[-2], yo[-2], "N-1", color="r", weight="bold", size="x-large") @@ -293,8 +293,8 @@ def permutation_rnd(x, y, ordre): ordre = permutation_rnd(x, y, list(range(len(x)))) print("longueur min", longueur(x, y, ordre)) -xo = [x[o] for o in ordre + [ordre[0]]] -yo = [y[o] for o in ordre + [ordre[0]]] +xo = [x[o] for o in [*ordre, ordre[0]]] +yo = [y[o] for o in [*ordre, ordre[0]]] plt.plot(xo, yo, "o-") plt.text(xo[0], yo[0], "0", color="r", weight="bold", size="x-large") plt.text(xo[-2], yo[-2], "N-1", color="r", weight="bold", size="x-large") @@ -313,7 +313,7 @@ def permutation_rnd(x, y, ordre, miniter): it += 1 d0 = d for i in range(1, len(ordre) - 1): - for j in range(i + 2, len(ordre) + 1): + for _j in range(i + 2, len(ordre) + 1): ik = random.randint(1, len(ordre) - 1) il = random.randint(ik + 1, len(ordre)) r = ordre[ik:il].copy() @@ -330,7 +330,7 @@ def n_permutation(x, y, miniter): ordre = list(range(len(x))) bordre = ordre.copy() d0 = longueur(x, y, ordre) - for i in range(0, 20): + for i in range(20): print("iteration", i, "d=", d0) random.shuffle(ordre) ordre = permutation_rnd(x, y, ordre, 20) @@ -351,8 +351,8 @@ def n_permutation(x, y, miniter): ordre = n_permutation(x, y, 20) print("longueur min", longueur(x, y, ordre)) -xo = [x[o] for o in ordre + [ordre[0]]] -yo = [y[o] for o in ordre + [ordre[0]]] +xo = [x[o] for o in [*ordre, ordre[0]]] +yo = [y[o] for o in [*ordre, ordre[0]]] plt.plot(xo, yo, "o-") plt.text(xo[0], yo[0], "0", color="r", weight="bold", size="x-large") plt.text(xo[-2], yo[-2], "N-1", color="r", weight="bold", size="x-large") diff --git a/_latex/ensae/td_note_2006.py b/_latex/ensae/td_note_2006.py index 19d5470b..4dc25a05 100644 --- a/_latex/ensae/td_note_2006.py +++ b/_latex/ensae/td_note_2006.py @@ -1,11 +1,10 @@ # coding: utf-8 # question 1 def lit_fichier(file): - f = open(file, "r") - mot = [] - for li in f: - mot.append(li.replace("\n", "")) - f.close() + with open(file, "r") as f: + mot = [] + for li in f: + mot.append(li.replace("\n", "")) return mot @@ -16,7 +15,7 @@ def lit_fichier(file): def est_trie(mot): - for i in range(1, len(mot)): + for i in range(1, len(mot)): # noqa: SIM110 if mot[i - 1] > mot[i]: return False return True @@ -29,7 +28,7 @@ def est_trie(mot): def cherche(mot, m): - for i in range(0, len(mot)): + for i in range(len(mot)): if mot[i] == m: return i return -1 diff --git a/_latex/ensae/td_note_2007.py b/_latex/ensae/td_note_2007.py index cf6eb5cd..4d937ab3 100644 --- a/_latex/ensae/td_note_2007.py +++ b/_latex/ensae/td_note_2007.py @@ -5,9 +5,9 @@ # question 1 -def numero(jour, mois, duree=[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]): +def numero(jour, mois, duree=(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)): s = 0 - for i in range(0, mois - 1): + for i in range(mois - 1): s += duree[i] s += jour - 1 return s + 1 @@ -70,7 +70,7 @@ def __init__(self, jour, mois): # question 5 def numero(self): s = 0 - for i in range(0, self.mois - 1): + for i in range(self.mois - 1): s += self.duree[i] s += self.jour - 1 return s + 1 @@ -142,7 +142,7 @@ def __init__(self, jour, mois): # question 5 def numero(self): s = 0 - for i in range(0, self.mois - 1): + for i in range(self.mois - 1): s += self.duree[i] s += self.jour - 1 return s + 1 diff --git a/_latex/ensae/td_note_2008.py b/_latex/ensae/td_note_2008.py index 6499e133..af1414c5 100644 --- a/_latex/ensae/td_note_2008.py +++ b/_latex/ensae/td_note_2008.py @@ -12,9 +12,8 @@ # question 1 def lit_fichier(file): - f = open(file, "r") - li = f.readlines() # d�coupage sous forme de lignes - f.close() + with open(file, "r") as f: + li = f.readlines() # d�coupage sous forme de lignes res = [] for i in li: s = i.replace("\n", "") diff --git a/_latex/ensae/td_note_2009.py b/_latex/ensae/td_note_2009.py index 22c052f8..8d16ec19 100644 --- a/_latex/ensae/td_note_2009.py +++ b/_latex/ensae/td_note_2009.py @@ -113,13 +113,13 @@ def decomposer_optimal(montant, pieces): if montant in pieces: return [montant] else: - r = [1 for m in range(0, montant)] + r = [1 for m in range(montant)] for p in pieces: if montant > p: # si ce test n'est pas fait, la r�currence peut �tre infinie # car les montants n�gatifs ne sont pas pris en compte # par le premier test - dec = decomposer_optimal(montant - p, pieces) + [p] + dec = [*decomposer_optimal(montant - p, pieces), p] if len(dec) < len(r): r = dec @@ -133,7 +133,7 @@ def decomposer_optimal(montant, pieces): def decomposer_optimal(montant, pieces): - memo = [[1 for li in range(0, m)] for m in range(0, montant + 1)] + memo = [[1 for li in range(m)] for m in range(montant + 1)] # memo [i] contient la pire d�composition du montant i (que des pi�ces de un) # pour les pi�ces de pieces, on sait faire plus court @@ -192,7 +192,7 @@ def maximum_piece(pieces): ensemble = [3, 4, 6, 7, 8, 9] for ajout in [3, 4, 6, 7, 8, 9]: - pieces = [1, 2, 5, 10, 20, 50] + [ajout] + pieces = [1, 2, 5, 10, 20, 50] + [ajout] # noqa: RUF005 pieces.sort(reverse=True) print("maximum_piece (" + str(pieces) + ") = ", maximum_piece(pieces)) diff --git a/_latex/ensae/td_note_2010.py b/_latex/ensae/td_note_2010.py index 022fb509..4dee78d0 100644 --- a/_latex/ensae/td_note_2010.py +++ b/_latex/ensae/td_note_2010.py @@ -34,7 +34,7 @@ def dessin_classes(nuage, classes, image=None): x = {} y = {} - for i in range(0, len(nuage)): + for i in range(len(nuage)): cl = classes[i] if cl not in x: x[cl] = [] @@ -63,7 +63,7 @@ def sous_nuage(nb, x, y): - la seconde aux ordonn�es """ res = [] - for i in range(0, nb): + for _i in range(nb): xx = random.gauss(0, 1) yy = random.gauss(0, 1) res.append([x + xx, y + yy]) @@ -78,7 +78,7 @@ def n_sous_nuages(nb_class, nb_point): - la premi�re correspond aux abscisses, - la seconde aux ordonn�es""" res = [] - for c in range(0, nb_class): + for _c in range(nb_class): x = random.gauss(0, 1) * 5 y = random.gauss(0, 1) * 5 res += sous_nuage(nb_point, x, y) @@ -92,7 +92,7 @@ def random_class(nuage, n): @return une liste d'entiers """ res = [] - for p in nuage: + for _p in nuage: c = random.randint(0, n - 1) res.append(c) return res @@ -106,7 +106,7 @@ def proche_barycentre(point, barycentres): @return un entier qui correspond � l'index du barycentre le plus proche""" dmax = 1e6 - for i in range(0, len(barycentres)): + for i in range(len(barycentres)): b = barycentres[i] dx = point[0] - b[0] dy = point[1] - b[1] @@ -151,7 +151,7 @@ def barycentre_classe(points, classes, numero_class): """ mx, my = 0.0, 0.0 nb = 0 - for i in range(0, len(points)): + for i in range(len(points)): p = points[i] c = classes[i] if c != numero_class: @@ -170,7 +170,7 @@ def tous_barycentres(points, classes): """ mx = max(classes) + 1 barycentre = [] - for m in range(0, mx): + for m in range(mx): b = barycentre_classe(points, classes, m) barycentre.append(b) return barycentre @@ -184,15 +184,15 @@ def numpy_tous_barycentres(points, classes): mat = numpy.matrix(points) vec = numpy.array(classes) clas = numpy.zeros((len(points), nbcl)) - for i in range(0, nbcl): + for i in range(nbcl): clas[vec == i, i] = 1.0 nb = clas.sum(axis=0) - for i in range(0, nbcl): + for i in range(nbcl): clas[vec == i, i] = 1.0 / nb[i] ba = mat.transpose() * clas ba = ba.transpose() ba = ba.tolist() - barycentre = [b for b in ba] + barycentre = list(ba) return barycentre @@ -205,7 +205,7 @@ def numpy_tous_barycentres2(points, classes): matt = mat.transpose() matcl = numpy.matrix(classes).transpose() barycentre = [] - for c in range(0, nbcl): + for c in range(nbcl): w = numpy.matrix(matcl) w[matcl == c] = 1 w[matcl != c] = 0 @@ -227,21 +227,21 @@ def nuees_dynamiques(points, nbcl): classes = random_class(points, nbcl) # on a le choix entre la version sans numpy - for i in range(0, 10): + for i in range(10): print("iteration", i, max(classes) + 1) barycentres = tous_barycentres(points, classes) # ou l'un classes = association_barycentre(points, barycentres) cl1 = classes # ou la premi�re version avec numpy - for i in range(0, 10): + for i in range(10): print("iteration", i, max(classes) + 1) barycentres = numpy_tous_barycentres(points, classes) # ou l'autre classes = association_barycentre(points, barycentres) cl2 = classes # ou la seconde version avec numpy - for i in range(0, 10): + for i in range(10): print("iteration", i, max(classes) + 1) barycentres = numpy_tous_barycentres2(points, classes) # ou l'autre classes = association_barycentre(points, barycentres) diff --git a/_latex/ensae/td_note_2010_rattrape.py b/_latex/ensae/td_note_2010_rattrape.py index 7db150b0..acb0016c 100644 --- a/_latex/ensae/td_note_2010_rattrape.py +++ b/_latex/ensae/td_note_2010_rattrape.py @@ -66,7 +66,7 @@ def distance(tour, i, j): def longueur_tour(tour): # n villes = n segments d = 0 - for i in range(0, len(tour) - 1): + for i in range(len(tour) - 1): d += distance(tour, i, i + 1) # il ne faut pas oublier de boucler pour le dernier segment d += distance(tour, 0, -1) @@ -220,7 +220,7 @@ def enchaine(tour): break else: nom += 1 - for k in range(0, 3): + for _k in range(3): i = random.randint(0, len(tour) - 2) j = random.randint(i + 1, len(tour) - 1) e = tour[i] diff --git a/_latex/ensae/td_note_2011.py b/_latex/ensae/td_note_2011.py index b46760f3..5676a02d 100644 --- a/_latex/ensae/td_note_2011.py +++ b/_latex/ensae/td_note_2011.py @@ -26,7 +26,7 @@ def lit_fichier(): def compte_restaurant(mat): # simple comptage, voir le chapitre 3... compte = {} - for cp, x, y in mat: + for cp, _x, _y in mat: if cp not in compte: compte[cp] = 0 compte[cp] += 1 diff --git a/_latex/ensae/td_note_2012.py b/_latex/ensae/td_note_2012.py index d8311525..42a8f62d 100644 --- a/_latex/ensae/td_note_2012.py +++ b/_latex/ensae/td_note_2012.py @@ -105,7 +105,7 @@ def distance(u, t): def somme_ecart(temperature, t1, t2, T): s = 0 - for i in range(0, len(temperature)): + for i in range(len(temperature)): if t1 < i < t2: s += distance(temperature[i][3], T) # charleville else: @@ -119,7 +119,7 @@ def somme_ecart(temperature, t1, t2, T): def minimisation(temperature, T): best = 1e10 t1t2 = None - for t1 in range(0, len(temperature)): + for t1 in range(len(temperature)): for t2 in range(t1 + 1, len(temperature)): d = somme_ecart(temperature, t1, t2, T) if best is None or d < best: diff --git a/_latex/ensae/td_note_2012_enonce.py b/_latex/ensae/td_note_2012_enonce.py index 26f6c528..5895f87c 100644 --- a/_latex/ensae/td_note_2012_enonce.py +++ b/_latex/ensae/td_note_2012_enonce.py @@ -6,19 +6,17 @@ def charge_donnees(nom="donnees_enquete_2003_television.txt"): if os.path.exists(nom): - # si le fichier existe (il a d�j� �t� t�l�charg� une fois) - f = open(nom, "r") - text = f.read() - f.close() + # si le fichier existe (il a déjà été téléchargé une fois) + with open(nom, "r") as f: + text = f.read() else: # si le fichier n'existe pas link = "???" + "python_td_minute/data/examen/" + nom url = urllib.urlopen(link) text = url.read() - # on enregistre les donn�es pour �viter de les t�l�charger une seconde fois - f = open(nom, "w") - f.write(text) - f.close() + # on enregistre les données pour éviter de les télécharger une seconde fois + with open(nom, "w") as f: + f.write(text) lines = text.split("\n") lines = [li.split("\t") for li in lines if len(li) > 3] diff --git a/_latex/ensae/td_note_2013.py b/_latex/ensae/td_note_2013.py index 2516aeae..6864a89b 100644 --- a/_latex/ensae/td_note_2013.py +++ b/_latex/ensae/td_note_2013.py @@ -34,16 +34,16 @@ def fonction_coloriage(matrice, i0, j0): # �tage 1 acolorier = [(i0, j0)] while len(acolorier) > 0: - # �tape 2 + # étape 2 for i, j in acolorier: matrice[i][j] = 2 - # �tape 3 + # étape 3 acolorier = tous_voisins_a_valeurs_nulle(matrice, acolorier) - # on enl�ve les doublons car sinon cela prend trop de temps + # on enlève les doublons car sinon cela prend trop de temps d = {} for i, j in acolorier: d[i, j] = 0 - acolorier = [(i, j) for i, j in d] + acolorier = [(i, j) for i, j in d] # noqa: C416 # question 5, exo S (version 1) @@ -74,7 +74,7 @@ def fonction_coloriage_1000(matrice, i0, j0): d = {} for i, j in acolorier: d[i, j] = 0 - acolorier = [(i, j) for i, j in d] + acolorier = [(i, j) for i, j in d] # noqa: C416 # question 4, exo S (1 ou 4) diff --git a/_latex/ensae/td_note_2013_M.py b/_latex/ensae/td_note_2013_M.py index baa8bc5c..84948655 100644 --- a/_latex/ensae/td_note_2013_M.py +++ b/_latex/ensae/td_note_2013_M.py @@ -19,7 +19,7 @@ comptage = {} for i in range(intitule3.shape[0]): comptage[intitule3[i, 2]] = 0 -departements = [k for k in comptage] +departements = list(comptage) departements.sort() # question 3, exo M (2 ou 3) diff --git a/_latex/ensae/td_note_2013_novembre_2012_exoM.py b/_latex/ensae/td_note_2013_novembre_2012_exoM.py index 6a821e40..63f4dcaa 100644 --- a/_latex/ensae/td_note_2013_novembre_2012_exoM.py +++ b/_latex/ensae/td_note_2013_novembre_2012_exoM.py @@ -18,16 +18,14 @@ def import_module_or_file_from_web_site(module): f = urllib2.urlopen(url, "rb") t = f.read() f.close() - f = open(module, "wb") - f.write(t) - f.close() + with open(module, "wb") as f: + f.write(t) else: f = urllib2.urlopen(url) t = f.read() f.close() - f = open(module, "w") - f.write(t) - f.close() + with open(module, "w") as f: + f.write(t) return module @@ -47,23 +45,22 @@ def unzip_fichier(fichier_zip): res = filename if not os.path.exists(filename): data = file.read(filename) - f = open(filename, "w") - if sys.version.startswith("3."): - data = str(data, encoding="iso-8859-1") - data = data.replace("\r", "").split("\n") - data = [_ for _ in data if len(_) > 1] - data = "\n".join(data) - f.write(data) - f.close() + with open(filename, "w") as f: + if sys.version.startswith("3."): + data = str(data, encoding="iso-8859-1") + data = data.replace("\r", "").split("\n") + data = [_ for _ in data if len(_) > 1] + data = "\n".join(data) + f.write(data) file.close() return res -# construit le tableau extrait du fichier pr�c�dent -# les deux premi�res lignes contiennent la description des colonnes -# les autres lignes contiennent les donn�es elles-m�me -# pour aller plus vite � chaque ex�cution, on peut limiter le nombre de lignes -# il faudra toutes les utiliser pour l'ex�cution final +# construit le tableau extrait du fichier précédent +# les deux premières lignes contiennent la description des colonnes +# les autres lignes contiennent les données elles-même +# pour aller plus vite à chaque exécution, on peut limiter le nombre de lignes +# il faudra toutes les utiliser pour l'exécution final def construit_matrice(fichier, stop_apres=-1): @@ -73,11 +70,11 @@ def float_except(x): except Exception: return -1 - f = open(fichier, "r") - lines = [ - line.replace("\n", "").split("\t")[:107] for line in f.readlines()[:stop_apres] - ] - f.close() + with open(fichier, "r") as f: + lines = [ + line.replace("\n", "").split("\t")[:107] + for line in f.readlines()[:stop_apres] + ] colonne = lines[:2] lines = lines[2:] lines = [ diff --git a/_latex/ensae/td_note_2013_novembre_2012_exoS.py b/_latex/ensae/td_note_2013_novembre_2012_exoS.py index fc172501..c16fb0f9 100644 --- a/_latex/ensae/td_note_2013_novembre_2012_exoS.py +++ b/_latex/ensae/td_note_2013_novembre_2012_exoS.py @@ -6,7 +6,7 @@ def construit_matrice(nb): - mat = [[0 for x in range(0, nb)] for y in range(0, nb)] + mat = [[0 for x in range(nb)] for y in range(nb)] def pointij(nb, r, th, mat, c, phase): i, j = r * th * math.cos(th + phase), r * th * math.sin(th + phase) @@ -18,7 +18,7 @@ def pointij(nb, r, th, mat, c, phase): r = 3.5 t = 0 - for tinc in range(nb * 100000): + for _tinc in range(nb * 100000): t += 1.0 * nb / 100000 th = t * math.pi * 2 i, j = pointij(nb, r, th, mat, 1, 0) @@ -39,8 +39,8 @@ def dessin_matrice(matrice): import pylab colors = {1: "blue", 2: "red"} - for i in range(0, len(matrice)): - for j in range(0, len(matrice[i])): + for i in range(len(matrice)): + for j in range(len(matrice[i])): if matrice[i][j] in colors: pylab.plot( [ diff --git a/_latex/ensae/td_note_2013_preparation1.py b/_latex/ensae/td_note_2013_preparation1.py index 3127e124..54a2e8b5 100644 --- a/_latex/ensae/td_note_2013_preparation1.py +++ b/_latex/ensae/td_note_2013_preparation1.py @@ -19,7 +19,7 @@ def sequence(): def moyenne(nb_tirage): somme = 0.0 - for i in range(nb_tirage): + for _i in range(nb_tirage): s = sequence() somme += len(s) return somme / nb_tirage diff --git a/_latex/ensae/td_note_2013_preparation1c.py b/_latex/ensae/td_note_2013_preparation1c.py index 6f0e5dcf..af986e72 100644 --- a/_latex/ensae/td_note_2013_preparation1c.py +++ b/_latex/ensae/td_note_2013_preparation1c.py @@ -24,7 +24,7 @@ def sequence(a, b, c): def moyenne(nb_tirage, a, b, c): somme = 0.0 - for i in range(nb_tirage): + for _i in range(nb_tirage): s = sequence(a, b, c) somme += len(s) return somme / nb_tirage diff --git a/_latex/ensae/td_note_2013_r.py b/_latex/ensae/td_note_2013_r.py index 3d2d8f4b..58766db8 100644 --- a/_latex/ensae/td_note_2013_r.py +++ b/_latex/ensae/td_note_2013_r.py @@ -8,18 +8,17 @@ def recupere_donnees(): """ - 0 S�ance - 1 R�f�rence - 2 Entit� d�positaire - 3 Elu d�positaire + 0 Séance + 1 Référence + 2 Entité dépositaire + 3 Elu dépositaire 4 Objet 5 Type 6 Rapporteur """ file = importme.import_module("td_note_2013_ordre_du_jour_conseil_municipal.zip")[0] - f = open(file, "r") - lines = f.readlines() - f.close() + with open(file, "r") as f: + lines = f.readlines() lines = [_ for _ in lines if len(_) > 0] lines = [_.split("\t") for _ in lines][1:] lines = [(_[0], _[4]) for _ in lines if len(_) > 5] @@ -36,9 +35,9 @@ def extrait_montant(objet): print("probl�me ", objet) return None - """Subvention � l'Association des Commer�ants de la rue - Mesnil (16e) pour les illuminations � l'occasion - des f�tes de fin d'ann�e 2007, dans le cadre de - l'op�ration "Paris Illumine Paris". - - Montant : 7.000 euros. - PJ Mme Lyne COHEN-SOLAL (2�me Commission) rapporteure.""" + """Subvention à l'Association des Commerçants de la rue + Mesnil (16e) pour les illuminations à l'occasion + des fêtes de fin d'année 2007, dans le cadre de + l'opération "Paris Illumine Paris". - + Montant : 7.000 euros. + PJ Mme Lyne COHEN-SOLAL (2ème Commission) rapporteure.""" diff --git a/_latex/ensae/td_note_2013_rattrapage.py b/_latex/ensae/td_note_2013_rattrapage.py index db5cc9b1..a4b2c285 100644 --- a/_latex/ensae/td_note_2013_rattrapage.py +++ b/_latex/ensae/td_note_2013_rattrapage.py @@ -4,17 +4,16 @@ def lit_fichier(file): """ - 0 S�ance - 1 R�f�rence - 2 Entit� d�positaire - 3 Elu d�positaire + 0 Séance + 1 Référence + 2 Entité dépositaire + 3 Elu dépositaire 4 Objet 5 Type 6 Rapporteur """ - f = open(file, "r") - lines = f.readlines() - f.close() + with open(file, "r") as f: + lines = f.readlines() lines = [_ for _ in lines if len(_) > 0] lines = [_.split("\t") for _ in lines][1:] lines = [(_[0], _[4]) for _ in lines if len(_) > 5] @@ -56,7 +55,7 @@ def extrait_date(date): def compte_annee(lines): compte = {} - for a, b, c, d in lines: + for a, b, _c, d in lines: a = d[0] if d is not None else None compte[a] = compte.get(a, 0) + b return compte diff --git a/_unittests/ut_examples/test_classique_permutation.py b/_unittests/ut_examples/test_classique_permutation.py index d83de773..e3d9e1fc 100644 --- a/_unittests/ut_examples/test_classique_permutation.py +++ b/_unittests/ut_examples/test_classique_permutation.py @@ -10,16 +10,16 @@ class TestClassiquesPermutation(unittest.TestCase): def test_permutation(self): self.maxDiff = None ens = list(range(5)) - lt = list(tuple(p) for p in enumerate_permutations_recursive(ens)) + lt = [tuple(p) for p in enumerate_permutations_recursive(ens)] self.assertEqual(len(lt), 120) - res = list(tuple(p) for p in itertools.permutations(ens)) + res = [tuple(p) for p in itertools.permutations(ens)] self.assertEqual(len(res), 120) self.assertEqual(set(res), set(lt)) - res = list(tuple(p) for p in enumerate_permutations(ens)) + res = [tuple(p) for p in enumerate_permutations(ens)] self.assertEqual(len(res), 120) self.assertEqual(set(res), set(lt)) - res = list(tuple(p) for p in enumerate_permutations([1])) + res = [tuple(p) for p in enumerate_permutations([1])] self.assertEqual(res, [(1,)]) diff --git a/_unittests/ut_faq/test_faq_missing.py b/_unittests/ut_faq/test_faq_missing.py index 6ff7e586..44e6ce4e 100644 --- a/_unittests/ut_faq/test_faq_missing.py +++ b/_unittests/ut_faq/test_faq_missing.py @@ -41,7 +41,7 @@ def test_faq_pythonm_pip(self): list_of_installed_packages() except ImportError as e: if "cannot import name 'get_installed_distributions'" in str(e): - warnings.warn("This should be fixed in a future release.") + warnings.warn("This should be fixed in a future release.", stacklevel=0) return res = information_about_package("pip") self.assertNotEmpty(res) diff --git a/_unittests/ut_practice/test_rue_paris.py b/_unittests/ut_practice/test_rue_paris.py index 11610691..47d555fc 100644 --- a/_unittests/ut_practice/test_rue_paris.py +++ b/_unittests/ut_practice/test_rue_paris.py @@ -1050,7 +1050,7 @@ def test_algo_euler4(self): vertices = {} for e in edges: - for i in range(0, 2): + for i in range(2): _ = e[i] p = e[i + 3] vertices[_] = p diff --git a/_unittests/ut_practice/test_tsp_bresenham.py b/_unittests/ut_practice/test_tsp_bresenham.py index beeaace1..d38b9dba 100644 --- a/_unittests/ut_practice/test_tsp_bresenham.py +++ b/_unittests/ut_practice/test_tsp_bresenham.py @@ -7,7 +7,7 @@ class TestTspBresenham(ExtTestCase): def test_bresenham(self): x, y = 500, 500 - for n in range(0, 10): + for _n in range(10): x1 = random.randint(0, x - 1) y1 = random.randint(0, y - 1) x2 = random.randint(0, x - 1) @@ -23,7 +23,7 @@ def test_bresenham(self): def test_bresenham_ellipses(self): x, y = 500, 500 - for n in range(0, 10): + for _n in range(10): x1 = random.randint(0, x - 1) y1 = random.randint(0, y - 1) xa = random.randint(50, 100) diff --git a/_unittests/ut_tools/test_graphviz.py b/_unittests/ut_tools/test_graphviz.py index 3228afec..2b2e477c 100644 --- a/_unittests/ut_tools/test_graphviz.py +++ b/_unittests/ut_tools/test_graphviz.py @@ -15,7 +15,7 @@ def test_draw_graph_graphviz(self): ) except FileNotFoundError as e: if "No such file or directory: 'dot'" in str(e): - warnings.warn(str(e)) + warnings.warn(str(e), stacklevel=0) return raise e diff --git a/_unittests/ut_xrun_doc/test_documentation_examples.py b/_unittests/ut_xrun_doc/test_documentation_examples.py index b68f03ae..c7a4a4f0 100644 --- a/_unittests/ut_xrun_doc/test_documentation_examples.py +++ b/_unittests/ut_xrun_doc/test_documentation_examples.py @@ -43,7 +43,7 @@ def run_test(self, fold: str, name: str, verbose=0) -> int: out, err = res st = err.decode("ascii", errors="ignore") if "No such file or directory" in st: - raise FileNotFoundError(st) + raise FileNotFoundError(st) # noqa: B904 if len(st) > 0 and "Traceback" in st: if '"dot" not found in path.' in st: # dot not installed, this part @@ -51,7 +51,7 @@ def run_test(self, fold: str, name: str, verbose=0) -> int: if verbose: print(f"failed: {name!r} due to missing dot.") return -1 - raise AssertionError( + raise AssertionError( # noqa: B904 f"Example {name!r} (cmd: {cmds!r} - " f"exec_prefix={sys.exec_prefix!r}) " f"failed due to\n{st}" diff --git a/_unittests/ut_xrun_doc/test_documentation_notebook.py b/_unittests/ut_xrun_doc/test_documentation_notebook.py index 064871d0..3fe66dfe 100644 --- a/_unittests/ut_xrun_doc/test_documentation_notebook.py +++ b/_unittests/ut_xrun_doc/test_documentation_notebook.py @@ -74,7 +74,7 @@ def run_test(self, nb_name: str, verbose=0) -> int: out, err = res st = err.decode("ascii", errors="ignore") if "No such file or directory" in st: - raise FileNotFoundError(st) + raise FileNotFoundError(st) # noqa: B904 if len(st) > 0 and "Traceback" in st: msg = ( f"Example {nb_name!r} (cmd: {cmds} - " @@ -82,9 +82,9 @@ def run_test(self, nb_name: str, verbose=0) -> int: f"failed due to\n{st}" ) if "CERTIFICATE_VERIFY_FAILED" in st and sys.platform == "win32": - warnings.warn(msg) + warnings.warn(msg, stacklevel=0) else: - raise AssertionError(msg) + raise AssertionError(msg) # noqa: B904 dt = time.perf_counter() - perf if verbose: diff --git a/pyproject.toml b/pyproject.toml index e9385bf7..0ac380cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -127,16 +127,42 @@ exclude = [ ".git", "build", "dist", + "*.ipynb", ] # Same as Black. line-length = 88 -[tool.ruff.lint.mccabe] -# Unlike Flake8, default to a complexity level of 10. -max-complexity = 10 +[tool.ruff.lint] +select = [ + "B", # flake8-bugbear + "C4", # flake8-comprehensions + #"D", # pydocstyle + "E", # pycodestyle + "F", # Pyflakes + "G", # flake8-logging-format + #"I", # isort + "ISC", # flake8-implicit-str-concat + "LOG", # flake8-logging + #"N", # pep8-naming + #"NPY", # modern numpy + #"PERF", # Perflint + "PIE", # flake8-pie + "PYI", # flake8-pyi + "RUF", # Ruff-specific rules + "SIM", # flake8-simplify + "SLOT", # flake8-slot + "T10", # flake8-debugger + #"TID", # Disallow relative imports + #"TRY", # flake8-try-except-raise + #"UP", # pyupgrade + "W", # pycodestyle + "YTT", # flake8-2020 +] [tool.ruff.lint.per-file-ignores] +"**" = ["C401", "C408", "C413", "RUF012", "RUF100", "RUF010", "SIM108", "SIM102", "SIM114", "SIM103", "UP015", "UP027", "UP031", "UP034", "UP032"] +"**/plot*.py" = ["B018", "B010"] "_doc/conf.py" = ["F821", "E501"] "teachpyx/__init__.py" = ["E501"] "teachpyx/datasets/__init__.py" = ["F401"] diff --git a/teachpyx/datasets/wines.py b/teachpyx/datasets/wines.py index 55c6691c..e7b534df 100644 --- a/teachpyx/datasets/wines.py +++ b/teachpyx/datasets/wines.py @@ -74,7 +74,10 @@ def load_wine_dataset( fold = get_data_folder() data = os.path.join(fold, "wine.data.txt") df = pandas.read_csv(data, header=None) - s = "index Alcohol Malica_cid Ash Alcalinity_of_ash Magnesium Total_phenols Flavanoids" + s = ( + "index Alcohol Malica_cid Ash Alcalinity_of_ash " + "Magnesium Total_phenols Flavanoids" + ) s += " Nonflavanoid_phenols Proanthocyanins Color_intensity Hue" s += " OD280_OD315_diluted_wine Proline" df.columns = s.split() diff --git a/teachpyx/examples/classiques.py b/teachpyx/examples/classiques.py index 645a071c..6378df0f 100644 --- a/teachpyx/examples/classiques.py +++ b/teachpyx/examples/classiques.py @@ -46,7 +46,6 @@ def commentaire_accentues(): C'est pourquoi il est préférable d'utiliser celui-ci pour partager son code via une page Web. """ - pass def dix_entiers_carre(): diff --git a/teachpyx/examples/construction_classique.py b/teachpyx/examples/construction_classique.py index a5b2039e..868e0eee 100644 --- a/teachpyx/examples/construction_classique.py +++ b/teachpyx/examples/construction_classique.py @@ -483,9 +483,9 @@ def mat2vect(mat): Dans un langage comme le *C++*, il arrive fréquemment qu'une matrice ne soit pas - représentée par une liste de listes mais par une seule + représentée par une liste de listes mais par une seule liste car cette représentation - est plus efficace. Il faut donc convertir un indice + est plus efficace. Il faut donc convertir un indice en deux indices ligne et colonne. Il faut bien sûr que le nombre de colonnes sur chaque ligne soit constant. Le premier programme convertit une liste de listes en une seule liste. @@ -546,7 +546,7 @@ def vect2mat(vect, ncol): print(mat) """ - return [vect[i * ncol : (i + 1) * ncol] for i in range(0, len(vect) // ncol)] + return [vect[i * ncol : (i + 1) * ncol] for i in range(len(vect) // ncol)] def integrale(fonction, a, b, n): @@ -596,7 +596,7 @@ def calcul_n_valeur(l,f): print(l2) # affiche [0, 1, 8, 27] """ h = (b - a) / n - return sum(fonction(a + h / 2 + h * i) for i in range(0, n)) * h + return sum(fonction(a + h / 2 + h * i) for i in range(n)) * h def construit_matrice_carree(n): @@ -620,11 +620,11 @@ def enumerate_permutations_recursive(ensemble): if len(ensemble) == 1: yield ensemble else: - for i in range(0, len(ensemble)): + for i in range(len(ensemble)): ensemble[0], ensemble[i] = ensemble[i], ensemble[0] per = enumerate_permutations_recursive(ensemble[1:]) for p in per: - yield [ensemble[0]] + p + yield [ensemble[0], *p] ensemble[0], ensemble[i] = ensemble[i], ensemble[0] diff --git a/teachpyx/ext_test_case.py b/teachpyx/ext_test_case.py index 54fe5e54..dde0057e 100644 --- a/teachpyx/ext_test_case.py +++ b/teachpyx/ext_test_case.py @@ -206,7 +206,7 @@ def assertRaise(self, fct: Callable, exc_type: Exception): fct() except exc_type as e: if not isinstance(e, exc_type): - raise AssertionError(f"Unexpected exception {type(e)!r}.") + raise AssertionError(f"Unexpected exception {type(e)!r}.") # noqa: B904 return raise AssertionError("No exception was raised.") @@ -231,7 +231,7 @@ def assertStartsWith(self, prefix: str, full: str): @classmethod def tearDownClass(cls): for name, line, w in cls._warns: - warnings.warn(f"\n{name}:{line}: {type(w)}\n {str(w)}") + warnings.warn(f"\n{name}:{line}: {type(w)}\n {str(w)}", stacklevel=0) def capture(self, fct: Callable): """ @@ -242,7 +242,6 @@ def capture(self, fct: Callable): """ sout = StringIO() serr = StringIO() - with redirect_stdout(sout): - with redirect_stderr(serr): - res = fct() + with redirect_stdout(sout), redirect_stderr(serr): + res = fct() return res, sout.getvalue(), serr.getvalue() diff --git a/teachpyx/faq/faq_geo.py b/teachpyx/faq/faq_geo.py index ec7275c7..3a94ef67 100644 --- a/teachpyx/faq/faq_geo.py +++ b/teachpyx/faq/faq_geo.py @@ -15,7 +15,8 @@ class constants93: def lambert93_to_WGPS(lambertE: float, lambertN: float) -> Tuple[float, float]: """ Converts coordinates given in - `Lambert 93 `_ + `Lambert 93 + `_ system, this system is used by `IGN `_ and their :epkg:`GEOFLA` file format. @@ -24,18 +25,23 @@ def lambert93_to_WGPS(lambertE: float, lambertN: float) -> Tuple[float, float]: :return: longitude, latitude The function is inspired from - `lam93toLatLon.py `_. + `lam93toLatLon.py + `_. .. faqref:: :tag: geo :title: Les fichiers GEOFLA ne contiennent pas de longitude, latitude ? Les coordonnées contenues dans les fichiers :epkg:`GEOFLA` - ne sont pas toujours des longitudes, latitudes mais des coordonnées exprimées dans un système - de projection conique `Lambert 93 `_. - Il faut convertir les coordonnées avant de pouvoir tracer la carte ou changer la projection + ne sont pas toujours des longitudes, + latitudes mais des coordonnées exprimées dans un système + de projection conique `Lambert 93 + `_. + Il faut convertir les coordonnées avant de + pouvoir tracer la carte ou changer la projection utilisée par :epkg:`cartopy` : - `Lambert Conformal Projection `_. + `Lambert Conformal Projection + `_. """ delX = lambertE - constants93.XS diff --git a/teachpyx/faq/faq_python.py b/teachpyx/faq/faq_python.py index b36762cb..9e4fa380 100644 --- a/teachpyx/faq/faq_python.py +++ b/teachpyx/faq/faq_python.py @@ -55,7 +55,6 @@ def entier_grande_taille(): il faut aller dans le menu Options / Change Indentation Settings... Tous les éditeurs ont une option similaire. """ - pass def difference_div(): @@ -401,7 +400,6 @@ def norm2(self): On fait cela parce que l'écriture est plus courte et que cela évite certaines erreurs. """ - pass def enumerate_regex_search(exp, text): @@ -470,7 +468,6 @@ def __lt__(self, autre_instance): else: return False """ - pass class PQPipError(Exception): @@ -520,9 +517,9 @@ def __getattr__(self, attr): return getattr(self.__dict__["dist"]._dist, attr) except AttributeError as e: if attr == "project_name": - return getattr(self.__dict__["dist"]._dist, "name") + return getattr(self.__dict__["dist"]._dist, "name") # noqa: B009 if attr == "py_version": - return getattr(self.__dict__["dist"]._dist, "version") + return getattr(self.__dict__["dist"]._dist, "version") # noqa: B009 if attr in {"platform", "extras"}: return None raise AttributeError( @@ -824,7 +821,7 @@ def get(cls, index): return A1 if index == 2: return A2 - assert False + raise AssertionError(f"Unexpected index={index}") @classmethod def __class_getitem__(cls, index): diff --git a/teachpyx/practice/rues_paris.py b/teachpyx/practice/rues_paris.py index e5439580..0053ec8f 100644 --- a/teachpyx/practice/rues_paris.py +++ b/teachpyx/practice/rues_paris.py @@ -93,7 +93,7 @@ def get_data( new_vertices = {} already_added = set() new_edges = [] - for _ in range(0, int(keep**0.5) + 1): + for _ in range(int(keep**0.5) + 1): for edge in edges: if edge[:2] in already_added: continue @@ -277,7 +277,7 @@ def kruskal( additions.update({(k[1], k[0]): v for k, v in additions.items()}) degre: Dict[Tuple[int, int], int] = {} - for k, v in original.items(): # original est symétrique + for k, _v in original.items(): # original est symétrique degre[k[0]] = degre.get(k[0], 0) + 1 tri = [ @@ -303,7 +303,12 @@ def kruskal( # itération degre[a[0]] += 1 degre[a[1]] += 1 - added_edges.append(a + (v,)) + added_edges.append( + ( + *a, + v, + ) + ) impairs -= 2 if impairs <= 0: break @@ -344,7 +349,9 @@ def eulerien_extension( init = bellman( edges, max_iter=max_iter, - allow=lambda e: e in possibles or e[0] in allowset or e[1] in allowset, + allow=lambda e, allowset=allowset: ( + e in possibles or e[0] in allowset or e[1] in allowset + ), init=init, verbose=verbose, ) diff --git a/teachpyx/practice/tsp_kohonen.py b/teachpyx/practice/tsp_kohonen.py index f7262822..809b9da3 100644 --- a/teachpyx/practice/tsp_kohonen.py +++ b/teachpyx/practice/tsp_kohonen.py @@ -58,7 +58,7 @@ def construit_liste_neurones(villes: ENSEMBLE, nb: int = 0) -> ENSEMBLE: if nb > 1: # dispose les neurones en ellipse n = [] - for i in range(0, nb): + for i in range(nb): x = maxx + maxx * math.cos(math.pi * 2 * float(i) / nb) / 4 y = maxy + maxy * math.sin(math.pi * 2 * float(i) / nb) / 4 n.append((x, y)) @@ -160,7 +160,7 @@ def deplace_neurone( neurones[i] = n # déplacement des voisins - for k in range(0, len(forces)): + for k in range(len(forces)): i1 = (i + k + 1) % len(neurones) i2 = (i - k - 1 + len(neurones)) % len(neurones) n1 = neurones[i1] @@ -205,7 +205,7 @@ def iteration( :return: indices de la ville et du neurone le plus proche """ m = min(compte_v) - ind = [i for i in range(0, len(villes)) if compte_v[i] == m] + ind = [i for i in range(len(villes)) if compte_v[i] == m] n = random.randint(0, len(ind) - 1) n = ind[n] compte_v[n] += 1 @@ -223,7 +223,7 @@ def cmp_add(i, j): if nb_sel > 0: # supprime les neurones les moins sollicités - sup = [i for i in range(0, len(neurones)) if compte[i] == 0] + sup = [i for i in range(len(neurones)) if compte[i] == 0] if len(sup) > 0: sup.sort() sup.reverse() @@ -233,7 +233,7 @@ def cmp_add(i, j): # on ajoute un neurone lorsque max (compte) >= 2 * min (compte) add = [] - for i in range(0, len(compte)): + for i in range(len(compte)): if compte[i] > nb_sel: d1 = math.sqrt( distance_euclidienne_carree( @@ -261,7 +261,7 @@ def cmp_add(i, j): compte.insert(a[0], a[2]) # on remet les compteurs à zéros - for i in range(0, len(compte)): + for i in range(len(compte)): compte[i] = 0 @@ -290,7 +290,7 @@ def distance_chemin(p: ENSEMBLE) -> float: Calcule la distance du chemin. """ d = 0 - for i in range(0, len(p)): + for i in range(len(p)): d += ((p[i][0] - p[i - 1][0]) ** 2 + (p[i][1] - p[i - 1][1]) ** 2) ** 0.5 return d diff --git a/teachpyx/practice/tsp_kruskal.py b/teachpyx/practice/tsp_kruskal.py index 77d8cfa9..09f291e2 100644 --- a/teachpyx/practice/tsp_kruskal.py +++ b/teachpyx/practice/tsp_kruskal.py @@ -124,7 +124,7 @@ def repartition_zone( # attribution des zones zone = [] Zmax = 0 - for i in range(0, len(villes)): + for i in range(len(villes)): v = villes[i] x = int((v[0] - mx) / zone_taille) y = int((v[1] - my) / zone_taille) @@ -134,7 +134,7 @@ def repartition_zone( # rangement par zone Zmax += 1 - zones = [[] for i in range(0, Zmax)] + zones = [[] for i in range(Zmax)] for z in zone: zones[z[0]].append((z[1], z[2], z[3])) @@ -205,7 +205,7 @@ def tri_distance(u, v): # calcul des distances li = [] - for z in range(0, len(zones)): + for z in range(len(zones)): voisin = voisinage_zone(z, Zmax, X, Y) for v in zones[z]: for zz in voisin: @@ -220,18 +220,18 @@ def tri_distance(u, v): nb_comp = len(villes) # indice de la composante d'une ville - num_comp = [i for i in range(0, len(villes))] + num_comp = list(range(len(villes))) # liste des voisins pour chaque ville - arbre = [[] for i in range(0, len(villes))] + arbre = [[] for i in range(len(villes))] # liste des villes par composante connexe - list_comp = [[i] for i in range(0, len(villes))] + list_comp = [[i] for i in range(len(villes))] while nb_comp > 1: iii = 0 for c in li: - iii += 1 + iii += 1 # noqa: SIM113 i, j = c[0], c[1] if num_comp[i] != num_comp[j]: # on relie les villes i et j car elles appartiennent @@ -279,7 +279,7 @@ def circuit_hamiltonien(chemin: List[int]) -> List[int]: """ nb = max(chemin) + 1 res = [] - coche = [False for i in range(0, nb)] + coche = [False for i in range(nb)] for c in chemin: if coche[c]: continue @@ -329,7 +329,7 @@ def longueur_chemin(chemin: ENSEMBLE, distance: DISTANCE) -> float: """ s = 0 nb = len(chemin) - for i in range(0, nb): + for i in range(nb): s += distance(chemin[i], chemin[(i + 1) % nb]) return s @@ -407,7 +407,7 @@ def retournement( nb_change = 0 for t in range(1, taille + 1): retour[t] = 0 - for i in range(0, nb): + for i in range(nb): j = (i + t) % nb b = retournement_essai(chemin, i, j, distance=distance) if b: @@ -494,7 +494,7 @@ def echange_position_essai( bp = (a + le - b - 1) % nb chemin[bp] = chemin[ll] - for le in range(0, len(ech)): + for le in range(len(ech)): chemin[(x + le - diff + 1 + nb) % nb] = ech[le] return True @@ -549,7 +549,7 @@ def echange_position_essai( bp = (a + le - b - 1) % nb chemin[bp] = chemin[ll] - for le in range(0, len(ech)): + for le in range(len(ech)): chemin[(x + le - diff + 1 + nb) % nb] = ech[le] return True @@ -566,11 +566,11 @@ def dessin_arete_zone( *Y* est le nombre de zones verticalement, *taille_zone* est la longueur du côté du carré d'une zone. """ - res = [[[] for j in range(0, Y + 1)] for i in range(0, X + 1)] + res = [[[] for j in range(Y + 1)] for i in range(X + 1)] nb = len(chemin) mx = min(_[0] for _ in chemin) my = min(_[1] for _ in chemin) - for i in range(0, nb): + for i in range(nb): a = chemin[i] b = chemin[(i + 1) % nb] x1, x2 = int((a[0] - mx) // taille_zone), int((b[0] - mx) // taille_zone) @@ -643,7 +643,7 @@ def tri_arete(x, y): # list des arêtes triés par ordre décroissant la = [] - for i in range(0, nb): + for i in range(nb): im = (i + 1) % nb la.append((i, im, distance(chemin[i], chemin[im]))) la = list(sorted(la, key=functools.cmp_to_key(tri_arete))) @@ -787,7 +787,7 @@ def supprime_croisement( zone = dessin_arete_zone(chemin, taille_zone, X, Y) nbtout = 0 - for i in range(0, nb): + for i in range(nb): im = (i + 1) % nb a = chemin[i] b = chemin[im] @@ -952,7 +952,7 @@ def circuit_eulerien( # on choisit une ville qui est une extrémité et parmi celle-là on la # choisit au hasard has = [] - for i in range(0, len(villes)): + for i in range(len(villes)): n = len(arbre[i]) if n == 1: has.append(i) @@ -983,7 +983,7 @@ def circuit_eulerien( bvec = vec opvec = oppose_vecteur(vec) bl = None - for k in range(0, len(arbre[bm])): + for k in range(len(arbre[bm])): la = arbre[bm][k] vec2 = vecteur_points(v, villes[la]) if vec2 == (0.0, 0.0): diff --git a/teachpyx/tools/blockdiag_helper.py b/teachpyx/tools/blockdiag_helper.py index a437bf9d..37a22451 100644 --- a/teachpyx/tools/blockdiag_helper.py +++ b/teachpyx/tools/blockdiag_helper.py @@ -88,12 +88,13 @@ def _detectfont(font): if fontpath is None: globber = (glob.glob(d) for d in fontdirs) - for fontdir in sum(globber, []): - for root, _, files in os.walk(fontdir): - for font_ in fontfiles: - if font_ in files: - fontpath = os.path.join(root, font_) - break + for folders in globber: + for fontdir in folders: + for root, _, files in os.walk(fontdir): + for font_ in fontfiles: + if font_ in files: + fontpath = os.path.join(root, font_) + break return fontpath diff --git a/teachpyx/tools/display/pygame_helper.py b/teachpyx/tools/display/pygame_helper.py index 5511537a..56142d34 100644 --- a/teachpyx/tools/display/pygame_helper.py +++ b/teachpyx/tools/display/pygame_helper.py @@ -297,7 +297,7 @@ def build_diff_image( else: color = colors.get("black", (0, 0, 0)) - for i in range(0, len(seq2)): + for i in range(len(seq2)): text = seq2[i] text = font.render(text, True, color) screen.blit(text, (10, h * pos)) diff --git a/teachpyx/tools/profiling.py b/teachpyx/tools/profiling.py index b8dfc280..534f7cd0 100644 --- a/teachpyx/tools/profiling.py +++ b/teachpyx/tools/profiling.py @@ -472,7 +472,7 @@ def add_rows(rows, d): def profile2df( ps: Stats, as_df: bool = True, - clean_text: bool = None, + clean_text: Optional[bool] = None, verbose: bool = False, logf=None, ): @@ -739,7 +739,7 @@ def fct4(): node.add_called_by(child) child.add_calls_to(node, vv) - for k, v in nodes.items(): + for _k, v in nodes.items(): root = v.get_root() break diff --git a/teachpyx/video/tsp_kruskal_pygame.py b/teachpyx/video/tsp_kruskal_pygame.py index 26681cea..5e330aac 100644 --- a/teachpyx/video/tsp_kruskal_pygame.py +++ b/teachpyx/video/tsp_kruskal_pygame.py @@ -88,7 +88,7 @@ def distance(p1, p2): pygame.display.flip() if images is not None: c = screen.copy() - for i in range(0, 5): + for _i in range(5): images.append(c) if verbose > 0: print(f"[tsp_kruskal_algorithm] circuit_eulerien X={X} Y={Y}") @@ -105,7 +105,7 @@ def distance(p1, p2): pygame.display.flip() if images is not None: c = screen.copy() - for i in range(0, 5): + for _i in range(5): images.append(c) if verbose > 0: @@ -180,7 +180,7 @@ def display_arbre(villes, arbre, mult=1, screen=None, pygame=None): li = 1 color = 0, 0, 255 - for i in range(0, len(villes)): + for i in range(len(villes)): for j in arbre[i]: v = (villes[i][0] * mult, villes[i][1] * mult) vv = (villes[j][0] * mult, villes[j][1] * mult) @@ -202,7 +202,7 @@ def circuit_eulerien( # on choisit une ville qui est une extrémité et parmi celle-là on la # choisit au hasard has = [] - for i in range(0, len(villes)): + for i in range(len(villes)): n = len(arbre[i]) if n == 1: has.append(i) @@ -233,7 +233,7 @@ def circuit_eulerien( bvec = vec opvec = oppose_vecteur(vec) bl = None - for k in range(0, len(arbre[bm])): + for k in range(len(arbre[bm])): la = arbre[bm][k] vec2 = vecteur_points(v, villes[la]) if vec2 == (0.0, 0.0): From cf8f9883929fa1ad0338d9b03483879fb5928b98 Mon Sep 17 00:00:00 2001 From: Xavier Dupre Date: Thu, 29 Aug 2024 17:01:43 +0200 Subject: [PATCH 2/3] fix issues --- _doc/articles/index.rst | 1 + _doc/conf.py | 1 - _doc/practice/exams.rst | 2 +- ...e_2023-2024_rattrapage_sans_correction.pdf | Bin 0 -> 73412 bytes _latex/ensae/td_note_2013_r.py | 18 ++++++++++++------ 5 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 _doc/practice/exams/td_note_2023-2024_rattrapage_sans_correction.pdf diff --git a/_doc/articles/index.rst b/_doc/articles/index.rst index 42e95b81..9960bcfc 100644 --- a/_doc/articles/index.rst +++ b/_doc/articles/index.rst @@ -10,6 +10,7 @@ Ou *blog*. :maxdepth: 1 2024/2024-11-31-route2024 + 2024/2024-09-04-ensae 2024/2024-03-01-route2024 2024/2024-01-18-wsl diff --git a/_doc/conf.py b/_doc/conf.py index f02ebaeb..ebc1dfb7 100644 --- a/_doc/conf.py +++ b/_doc/conf.py @@ -102,7 +102,6 @@ "scipy": ("https://docs.scipy.org/doc/scipy/reference", None), "skl2onnx": ("https://onnx.ai/sklearn-onnx/", None), "sklearn": ("https://scikit-learn.org/stable/", None), - "sklearn-onnx": ("https://onnx.ai/sklearn-onnx/", None), "torch": ("https://pytorch.org/docs/stable/", None), } diff --git a/_doc/practice/exams.rst b/_doc/practice/exams.rst index cf952f65..776d5f49 100644 --- a/_doc/practice/exams.rst +++ b/_doc/practice/exams.rst @@ -36,7 +36,7 @@ Enoncés * :download:`td_note_2022_rattrapage2 ` * :download:`td_note_2023 ` * :download:`td_note_2023-2024 ` -* :download:`td_note_2023-2024_rattrapage ` +* :download:`td_note_2023-2024_rattrapage ` Corrections +++++++++++ diff --git a/_doc/practice/exams/td_note_2023-2024_rattrapage_sans_correction.pdf b/_doc/practice/exams/td_note_2023-2024_rattrapage_sans_correction.pdf new file mode 100644 index 0000000000000000000000000000000000000000..45c77f797789c4a93ca826926eb4928cfbff0c63 GIT binary patch literal 73412 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 z zl7ES`^}EqNb}tigc_%n^Ik~J!rNX153JpT@ew=f~jXVuv#hwErk+VBXbxD@Fi=Wop zvg2-iJM<`Bk!xni%eoXZs-*Q~bq%vnDiIEHh&N=5(hfCpv| zBza3dO8VPHj`B;nQ0s(hjhu$c#ujm3ArK&8v;pYz76;*g{QJn?GSRly=kacwKlE+z zXESB)?ivg1=y;9ydq9j?8GjfP6}iZt13#RmR&R7c`OozJ2XFbuN&W?+qGMwIPZ$;Z ze={6EMmEpe#Qf^ttD&AI_%gDU1JibLS*=zN=*It}12eoVB*Qche z;fG#q_E$`}GMyn_aV6#lYc_{O(pxDD0eWpc+G|l4i|DrrZr)z!F z^nOA`e4>uI(pFE+npc-l_$}1+ou1ri9QXShowI+|Q_UVL@Oob}#C{?IJe;bit~~nu z=?C+pA@9=FmaO)9>>>#Kq#+(Q065FGL6vNjW_ zrlM|stEK`o;i%n6nUmR;*tHF1!our8*a@`5uKBsr+H@WTH?O)9@m#Yo2Tyd3?TxvEfki>g;wBK; z)&Sk7nf}O~J2T<261g=YPY~O7_)41VZ*_Eg5p>=;Cf%Jo@XPG<*t zHZ@AsQDDh!7_Y?sl}qdhVje?h@x=4FJRNJM_KV)HzE#}Db`RSxdopZ1z?IG3RB5Ts zSX}Kf$aPOcLfM)AFS&^MusL{B3d1DZBn*n9QOTr{iHnBEoORCYi;WyJTkH+o5v|p{ zFO#~fiI{j}%!{%lRBtHc0P&HLS>evr5QB2LeX3{djZ<`6n|4MSYV7Ixz~YLV#ze$d zAwp6S?RsFAMtt)!yus@Ek$Rtg3fhth>FEIFtekx*{FwPoEQwpnUK#Fpvx{L>g;-r8 zWTE?q$>3S2)g3RzG0HA!$}!P3(K?xDFJQ`1bi!H`pd;mnZli}_qu;LD1hny|=g9{& z19nj`q~qu&Fst?lk{V#q&Coqr zQ6~q@OdSLzG39iV=W3)lmQec7R`8L8f^DflFhmGOKI0tMrWTn zIJh-H2f4a>X*sgOe)KHyTRALNt;F^{hsKbw(iNSDsQTQ>!^dTTt}}p#Xg(Cf1M$V` zeJ+o&etfr!Z)!GZ@?2i}XobHix=#{Qbes`Q5N1Regf9$nazUsh6bvi`b_5LUJvXb( zsQLDATO9^7#x<`CWALs$-;}v^7n00G*SA95JQs4ISK*YH<77o!%cLG- zd4(mj?G8nFX6D+^C%)jQ6rH1&5C51Ktw=%kjzAJHsZ--Nbr`bdCh08CWv1EdQwB_k zops*V1oFdXSV<$Nd@aqn>eaoF*9R1qnEY}cDiDKH)?Ry>ME>|0kg(ZVf+BSMW!ue2 z;CZ=NW@&5uj+f+ajip^9;BEUS`i{&_Rc@=gMZ$Z4}g;mvLrHND4=CNU-+JlLuu!6F>y79c6qo{NChQ6&s z$LPmgjJ#{;Fed`FmxM?r=Y@A-{6Hz*v3Ora%^G6M;}Av>Nk=jc;XPPMfwcBy{hEcW z;;a$foN4n5xJZcgS6bRt-_&+?wyCLMx{u`m@8UA|_2jh6^q*jlwE>b&#O$e<4yo@4 z^@h_^-%1OMiUIYiN+4C75>u*YnCCyX{M-i8h1JD+19jJNJLTbS!;r1(6~(0OZR!`n zoUIW!g*n33fBCGZJ3ZJvF4rIjNKEEj73;mi$9cE)IG5%z7r=r2`Acm}HWRICTtqMl ztdp&)Kl8R-g_QHT%c@=2*Df#$$I&fzHjU?1hMX)Sm(^4a={DX_YI^N4wN>aTG~IUt zPzWe%;w{^GPS-w_${zWWGDI)2-_P3zgc){Lli9WYpgC*(v;$yUDw4Zk1hI_j{CyOJ z;~qCUXw9<69|Y>SdSd>RVFY5jgW*ERvog$NwPM^gj5~jLOI>jzX#J)vKRRrjH84zGvwF(`~&` zxyYRPQSwKkVy@|>4OOPu_%Qz*Cvzp4E#Cs$YGre<#>}Btf(BEWtgA5cI$36MT#I1S z2Dj6dz>UCBj~3nb!dcb%Zso|oo*&-_uHZJk;1+~ZyUZnl|Hn9JdvHr_hxtEu3a1Qv z%esG{DLCKIXeYG;rn8-|-S7J^qVPKxh-zyof#!+XEA20w_x4~g9{cAp^CN3eqK++iC2cw)EHagkZr4`AP+X${*4wuvW2 zB@#aXxMz6r*(^X_yS!KyUis4o~q9T@r7?su;@?qU;k#A=3EeebgnC>X-Q` zQ}DW%GfS)i+8uUFpbd%8L0%a`=PgmdJS6d#XxY;=ITDcB#A@wfEMPb0?_Vz zegF@k)COH^m0kTFaXkmwi#2*Zf1&ZqPyl?RzYWa%h}87ObYQTx4{>!H1u1h6T?TcvU| zt(MHeDQa}FrY=MJnm+oeUOEZ3>jFXuaHYfZ0i7+^yCcFF?Vqq-O+LX+H!X{;%vFaQ z;!VP1fquINREEE2f}|ktCks>95ezfuX$&ZdP0G$r#fwmfsx*W^N`=lrL^cB0G>~6! zmbjWE1Hn~oMuXt4kxGn1jXP(zXTHd@)Dh4{i?MQ3D9Xd4&{lTR#7^m1QfQaAIV_MX zOq8o?Q060uy&#h_MqUfc^v`^g-YJA$_jbC@9vjS3^_~e1xCl?)*<7BNRC3p&zx3%( z)Q=p?l=(bSZo`nhI`Lf24x*oe>@0oXZrvO1qjSe`LVN+odk{YVhfMfiDegb1Fas+C z-G8RS^z{Fg3;zquDq?HnBxLMp=wNQ=Wc$Mc{|ROEt&M4g`Tu!P%Gf&DD(c%fO557l zQY#pnI$P;GK>kAvH+95g`q}t7TtL9qO_Q31o&}GZk&PXXo{f$UkDh^%PMcQTN#Dxc zkl)7C${3Fhl9u1m@E@2fJp%(fiSa3XnfJ`F}8G=^6g(TKTZ7m5 zRU7Ty=(hlbCxW6>)yLw)tvn&a9%Z)Q9o4N4XBQdpD4COu4V zVA^B`M00f$oU@x>~=i-TEiF7Q6Q9yevg3u|*x4tYq(IJ1Km~_XZAWMQH z(HSoxp5LLM58;=#=V40{-S*?pWqVOek;v>%ZE>W z)4!9w#G3m)mP)1JK!?Y~~9kL#g&@A6pG*ZogQ{0~C#4}bnYHTRz+U?m4<7A(`*q84mi_1L z<|+pI_6(ndK|+nd31%qdhU2|k^A|oXJkU!`HsL30Mo$CCzG4tv?K7-3dfW9p3@%~; zheX)RSju&$Cn}D%qIj4&C%&VSH+TIFuq^H`LJ;3*hpHa`_*$Xr zT{q-Ov0Sev?j7XF>TESX=~(@@1phVF5T8CUG=T{_sR6hVFpmLIUmwgAR(OLh2eKSA z_lz!1ez9Xthp#!iS-GET@Ls7gNMw8~>;r(mN3p;7qqR)bk~IpK&tXIo*A0%XUZ6u4 zk6+vvy}$WX=#X-f6Ej&&ZG8Ck<&AbeL5GQpp(at1b?eeT|31j;N@fw&=txvec#ni~ zi*+603y|z2N-DaR`y4#}P1QO(!@hzim`#|?Lql`;WfbSKAboK3n*nTiQFG9sY_y{` z0a1-ttOk_2{nASbAEaGR1oFCRTXj702<{a7o8W)Siuv+;@Txcmia=bZ_n+KEw%n}bVu?=d`uO(%B zf@^^8kX28gcVS!B;Euz=ox1b0>*0;pYfZ%1V-R|VjeG|9JQhuVdT=n}~tKaRy`?UA&;v1sSo%Em&MjkTiTV8;7$ z<%Nanijrz|nHG%_m1c+0J?L@d1WL+GE-E<%Ra$mxCL?7QHlzm@%Zvp*CX7e6N})=9 zSuYUJulWn2%)w0ygZ&G;s+Kyx+LtF~WE7=P%K~wp5z_no37FLt1tqqWqe3qRRNQ*= zGc$$0l)VkSK>+7s4*upsbb@O!uT?M0ZYJ9MmQ4kmi5;L%H*dgnaen3-K7f`T_LZ&I9 z!|5uc9f{JGn-!H_`EhD$a;Z&0m1fB5{Ng0clnELV3Ad^0q^gghP%+Wkj!A@>g>NM{ zcCJ=}nhDYRyYwv{R#%zgnm!IPZ4~ULvz$0t?y?PdTFTi|spT~~tn4!v<@osJGy4Od zYos8hh(3S2)6>!d=8x=h;nAfSC==>xsEK^Nn8_~d>oe$d8Bwq!v9r;(u}<3W*7Ot2 zt;#Tlr873-hUUX_wXP*sv4)}wh1r_MP#dIM z%->a)L52ec_AgikP!E-=riw3{$#Gp=)E zh-}x`*kDRlI9zlLE|c9?8jjCTn`vtr4+pgu9pm=MxlP#|P7)GWPZFv+Z-03yWJd}N z=qz&PZI5Y>uxZqN5pjgL813@*zb`7X|BGh6p*G{j#_&#CT5I#?FsuD{uOI@HuFE6=_sKtp? zDOQU!4_{QA7AsfUtJHL_y%ImV$bn5g>qe?&$Sg1j_ zK8H1|=Lel+J;)!zmsdA6RolSU>TK?`i0Kn4<0mQ}E9DB3Y@JBP^8-s=I5>G>9vTW; zjo}B>^5bc>gWQT+$H3CUg38o4?5oi1Z}y2URL4gjVfA#BN|=+Tn!+njo-`G(NJ|r< z#?M4(=!!uX^8|xJt2|EhtqGDsHM3|3+dxt}ndMSikV~W#i?Vq1P;Vik40?Mhm{}yA zl0=3|s3U+Sw-;2Vpck7D2++sFtCT`D&?Pdz^_&k#*AyL(8(gz5JD*$lNTKR%bCDpz zQG)z(&`Bj~_yrYd#d8651d1)PJL%X~bRK}iNd@s>aMQ_0^1J2|2a2_oI=^~8*K4^| z6lYRKW$+?pVgSg=IyrRE?s#JmNNas-=fx1#aF9}S1INHm9ibWtZg!xf1@|!s0%>wg z4V@g-tsPHMBNPX=7|r7#UI@(w0@N%f(NoN^f`cb z*#Josf*iKiDjTDtx%*ll@n(+4W7MDG7%n5S6fQY>Q-XPy8gqi!U{_5k2^G^m-{KB8 z0bVD>;wRe_VJa!Y-%?Cx3ZXRi3XZB3+h=Cbi6nuf>ANW``zRqALz$aL86X}v{a#=l z>87=m5GrLD`BKG~xYCKjvQbz)sL>($(=1fYg3j!LJ@23)GHcQ70VCgdfe`;37vY6T z{-T5=%E4+))snh-C1*oPlfz3pdJUbNvffn8K0F2Y&0zEP*jabl!9V-{jPr8)T-_@Q z$VTVE5n-qno~=d9lzB~pX!F7XW!hY!l$GLalt#@WsnoP-)mN^pk(jLfb4QxVkNe!u z8y3x(FA*37{0?>x%WeX26x+`4AQX#k77+9Nv|uSz35l@M=I0)jyHH4EygI9cWn*e8 zt(xELgTs-g2_~V+1P`WxKTJP=c`c@l087_8=l9-q;o%|bU@_^wn6`Gd?DLFzFI?^% z{&wjE7O#-r0b!fCvAzSHq9de-93xuKr<##C(Jt69OA<7maq{sMr_{{z>SX$yRaCnc z+TTm@+BzU%Yq|?27=n-kvIDSqXOd{UK8TMfI*T9@LI@Et{Q?mPjQu2p82PDZkuo}g zAvWuk!KXwOc^?VZ#ENlBnErg~gl<;I)D}+)O74nP?&Ps&0rOuUITNA|<6aF(SHCHs zO$=ITX_#qE&>U$dPu&L{Pf?KWbb1WZv(cO>m`AD2kOm!3+Sor8!GYpQ==W4^#hHruH?0z1xU!@bGFiqLgfsnD#m+>wDR+x(aDGq0X>}`Ytw#6`0HBenrV1^+qkhnX80Pj(Bbo0 zb#y_FVRkgZWyW!^YuDU$Fa>Rr8(<_XZCRJxcLQopy2|$&RB2Zq*6RR0txz|fo4?z> z4J4V!R(YAzqKNQlVuJEfm_Z_OahObY3K(Rl_t|r+j_2EQqV1Q8hok#q2C?KNCguM0 zeJs!0XCoZ%$KBBD&D&w;>o*_liGR}mMr{4;;d>Mm7Ci=gv_>@;<79a@&FXx(p}_rT zg2utX*4%LWNqdHt{AwKKIma=_;ew`mXf?l+T69*hB|NnZ@Vtx}f8~MQv$arf9E&iY z?Yz5uPuBx{#?l*uQXO?xYW4g^iPh8aHC&BWo0%Um99C7V%9UE0#=dfKH zMOX&6s7%g4xoOzDnY)ijQlZD6?0QSK3YtRWwX+733DMCA5mP?l7rPs3%R@xG5U@qe2MHU{su9TAB$~O1~^m zA|pmAWFPZHxHkuik>#$aTtciHGA6T7{6u@)2Zujgx1P2fp`avIjjmm<#OXFuPP-o@ zcK^7hsybB9SYhEhS}8+KQ1IQLyoU|$GhaIGRO#V0@UC! zHU`WgfQZ5?@i%SZaUljx2GIQuD#4=@fIk7G)l~|!4hR!UeyMvkXF#2oS1lje^%HB zOXB^Aop`aUermnHRlFC~U@?xR&2_RT$6WP7T(!pMB9JQM&f(LGS+>AyG?}KK3P(bo zvWADMY6QZm)R)=G0;6BdI$biULR{8}fvHCPHF+J?cLLEQlt%&tMHq((Xb8d+)5nSM zM;jz3vhNF_jTuN)NRJ3;`#fa_qKshfb-u}kbwQ*Xfvi-C>AZq4X~-C1P5h%amQNhS zM7R&xpI3OV+$pezQ2MjlUDR-2U;a+A)*9ANytx#ue2?9X1vEk)N zAlI=?%PR5AA>B&lDNF@-9E=CE&5BR&{@%)LBE)b#ZYl(LolYoHfMse@#pO0SQIfFR zwe)r|h+j4IYHQM}p-}c$K~s^H1Grr(^59MMrh_K1GIe)mx}@i*Y%Ds*)Eex7DmSAI7 zuj8JUpR_$kIT+&fRy5@pBF>dr8yZYSsp|=kcoO}l(@U}1O-1?vd zb;8_CJHj6SgdLdYPZdRu&07qd;mOUClag6#t#CgYEi(%)pl0gPI>Xdi209IP*io~k zKj%!`Yo8&dk#Z&Le#*_8PY-=qVSX^(-~j$cq`9kDMo%YE4xyk-E4M&mWc)RXz7mlY z*@huJkPSOv8*nEC4-2Yq3xB|W1}!k0l$*%A2!tz3K zhZ0QUOde-kDD!B(v|TJN3NqTqfMs*rqB8@Ioe@K*blIjQ!&q|3m^mCQJMx|-JZN7G z;t#wX{#N1~jo=(ofFZtE$Q~a=h?zV@f7e{+glR_s!pg!h|qXoXhLx&J? zfAyw~_euCJ?rw)RBa2UmE0h;V ztD?uMp|nfu7x4o^_B2+ec5a+R>CD8z2a=Vf)Jqq{%;{ac4XYtNh+5=ku+$K1cxIUZ z7fH4R@XE}GJtdr|6MiN*c$5dfqDTl?^u3ZMAjOc>m4eSS9(7Kb3jAi_<9rf#&2fe@ zzl8+57UY5ANjyPIK#Y)N`gQnCqU~FYKN)!0TE4SzuUgv+shaMO&W6395g)zbUpXwu689WVRe-NR-5f3~Xa!9UY+ zwyLUJ3P-M;3MaBXNG*#$ma71qK>82>lmSvr0djuz83UsI;#2%5I04<00+0d4L-+f! zJK%rWogNuLeBWP_kMD$D8TJd`cF#ghoQ!sN%9=l1ny*E-!U$!$sQ{!B7?@D*eVI)1#Je;6y2;87tPrPIl~;uC5lsW>#>Vw!aCXI(qQa4N;D{? z_OzBN^EXI~T@&Nw$8Tr(M69@0XTIo%{rB6hxJER=>vWRu5FW3RFbimAwC%SUU#;HR z>O{z6M z+I<&xXov-ZlY9U`okDr+ty8qgZQc}-4XKJcr+nuF4aQOwr~<%E)W97m)OpKhf>*%0 zpLX8c{+N}mE!3LGQ@wTPD=&$@mF;iW&)ZY2J}vn-HMrc)<9*2K>9YM^ov-oW@3>v3 z^BDBUx@I+nI-<~L`X*4YnHyqDL)Y`_zYAn0*?tooa?A1z1UH~#n$qg%fx~wD12w{l zH`DgMY=o!EirKDI{eZ-lsx`*9ICY@5=YTBnNW4WkKqC7{yeYWxzd(d9r0(}b*}L;= z1aPXz%B{L#nN%3d&_)VWHrbkI1~k+!Wt!Yl=F^%nz>JmUvu0kmhs&YcwoX*ClBkWK zk|)&L5hdu(O*M;pV|xdz*zALu^x|j&Ci!W<5TADSZQl+wX&J5sw+~$lYv#U{ZVSKO z#+U^fM=O`rtXO7_>;UXAYANxco`AkejfySipLlBa=}C6Ch=8bx^w&bQbOj|?;hv;duUp-#s|&?zWI z$c!jQK0DK3g5hwKuCMk&b$DVrlgPk|ZDWBKm3HFoRq7?r`&X$G4n@j8QtlhKN*B_s z5;>BdN!$K@j0MRVvRX!wIGcn_oZek9@Ku5ZuAWZS)mv20TS5GJ<5Tpj2h$_%h`$7O z1&0My;}_{hX2aGK^Mj&OLx^h}g|-*8=2{jQc?4|veP0;hd;XxogXf9?a|MM3Wd;HQ zi)TlXm%_=T)l-zhb4ptzt3Q)fpz)+Y1mLk^_1XZ7>fyH4uuQS1C6hcd_TIOOchSf3 zbvCLk!=JHme0plzMWzeJvfu`ckI52;%P5p7kKtgkZS4LanCoEduJJx62>(6ryBy2n zKS$*a>9|QO__y2EDj}ws&;JRb)B4R}SF+YEmDW{aRuU?EGPQG*^lpY9sYiOX8_Tgt zk+(-`%*C9_q*3CeGILWFVlH zA)M4F!uJeLp((~=kW?v7AlJ%eeWuNAouiPWC-``un{_T~2`C#KH@URw&=nKf%94}I ziqdESGjlekrK*bvFobYnnEuP8TvZ20$b(vl`~9vQPNTR$*}QqPOz*5Iv3}_?x|2v2 zRX~wIqBR&r*$Em=fR@js@Zm2Y9+ygyQ zvUX{~SvezV#_;KS#I}PHNiIn~mSTJpBeB986DVbRFSmQs_q>>~jhowjaP{TL%dO96 z2{muk5%5?1#>KO$mnGa(_v0o$XWZmK{4#2i@(Jn=J(q{%-e5o9%)!Az#dKj0xd^zEJuw0otH> z4YZ5_J1XdLIxL7mcxp)fG}Ld``3-3B>NQx#bowJ2P-2e|B`RuLf~j#~$&1LC-n)}~ z|2DA2OX>yb1?0?)j1^X$g6|H}(;$yA#9N6UJG#T3OmSmdcd{B8=v`X*dzytmnZ@pSEqd z%CETFP(0xm->cBk&pW*8whcJckNm(EwX0Bw>qpj&Yt<(8is=@oOh{fj6<(=7`%Snz z4}-R!c4Kg!U+}Mjq}YI#ll3=kxH)%&JiJVA{C9&~ymvl$O{6dEd>>i&gJrk{=QgKU z9Wzo6$BCW3iD0@<#ZMtfvNhx#^@VVdlkM3C5oJjLW1&1tzqZ}CooBf=ngt--9y)T} z4p#0JyRDR+b!O{P8D(JHNNO%HUB~Ycw|P5@2`^gdX6z1WUcmQFN>#4$)lHb?XD8_4 zVX?_ik+OPZQS!MxAUpR5KJCvhW29 zhE5*nwKeLP`2iD6OOx_ z)whM~qcw{|i-F~Q&+c=vIi4Cv;poBB0vEg&@W(yA779C_L-K094q4H|`ZdnQ&zaWr z(WyWKpWu-0hlD72=CYbj3zEX6CEeN}F~majKzcb)e}CiMA6QBL`d)ml*KH0rm)DK$ zS5m8Eq^cwlDkPrzhNUENfX0uHUc|N%F&7#8^>G{O=M-pxNTS5PFj{VJ{$0_7GdhfH zx)^t*9mEz(r{1D9HSZHxBv!6kRZDJUYBX#K8{rZU%+VzZcjC3g|yP zdd|Q9q$ofIDdFZbLqFz@DDAY)G*L``Jh1f3Pvw`Zd^`KpdQ8vOi(g$mB}We`cB=l% zbTjSe(;(|@ybmDm_n*9J7M@&B1!O1M)Sgay3<|F2anS{EW!)6wi@2@;M`3IQdmmy- zChZi&#NF$Crl8`6XK~pIjB0jrIcyks`2DRmEf>EBi{6mJeO-?p}$LP=ViD`SY zreY?iS;ZC^x3fR9lpCj}$SbX?t+3YJhsy~t=#wg@oo=^RDaXpd4{J|ZBHpwQ7WrK> zB&3R60i!8U7O}dQS^2J<7hf#T-DtbWzjRXOCu(2AcKXa}5q~{a!%i2yqaIN{w9E4A^f;Y<>rTDQx!3l0osqJIt{ZjB z#hJQJLmC;co7Q76&RZ}U&1`XXPTOqaZ(Lj9ac*Y9H#S${<6EfHrgQMtm&T%$B(y&% z9n}dT&&(J`8q<=16C;pG%Mxbqjw8-jtmTU3{yioYmBy5yx!UqR?#qeCuWvRz9I%jj z^suc8E`8Moywuy9KQ$G6u6(rZ^>{7jxVFhQSyc@Y5kybBGu|i?t?}xk7u_Kx*-`8j zcs@ul67B6;I96&30`bFNTNP+jh46rhj27Xi1tin$s(=6ztL1ei4lfnet?|!ih-e7 zBgp*)am~oL^6Sl~l{1m~j9q2c1XLTHh!9_)lXd_7*^H}4yFj$Ce`+N!T>+7suut1$ zguW`lDewVSOeGPEYhytK#UaEBYJUm*Hs_0SS!%~_KG!9xMhol8#E0Yi4rk?K%5k=r zhH~gQFadbgG$Z{;a{&`w5E^6o%cgA|X4yu| z@IjKM5rZ`=N(Nz=!P%q`3x9FR{!nC#iZ#a(zFg+q)SokO1i2i3V@2{HdU4BhNJW>5t;|g64w#x%PQ9v7?L__~4^r zPlARh69YU{OLz$9LZL4Wo_(rJv8&fYhZ0F=P70{E{OYnopbYIJX+o+@M^K0+3 z)~Mbuue+Y755(ocuiX9(MqIwdQt!cKTd`i*X!&qMrg{1XkVc$71Nq8pbTEMuF!56R z$vz#8fuoaT6Mt-12x(){t~R5(L)6~eOHauP+!}U3c3*eg2Hi^Zofp~jyN}Xh!QA2z zytdKt-GSyf!vWT&sGR||sx0A3Q*`7-JPc(OY{1oPEUhViaByX;sRO>@eoic|!TxS6 ztr7lLrq2UcG8B2(jWgqo8!?P^flME%${nd!R5ra6`#wiM{|%AjIK7Lni6}DjhhPc& z;idl2299O@yzna8XT1s+$xe#>>wGv}+@J#r@Xg46gOfkG=~7-C3a1CR^|N`{9&`=r zlt+d!75Fh$yyGIbER>_jTlgB<{HQfpsgcZRR=?&A_)b&ce*;$;Q-OsE{J{>a>=Q^8K+%v;laJeE}7$zo+IUPM=I4Y**G?k)Gtua8W@^#$vpI z&=AQah4UrL=T^{%b`!896d6t)DC1FDw`~t)b%zmM%k%ST zj)!-b`B%qANAqQ7Kr&@ev1E!W)YUGyE!-*Y+s5JOo@Jrv$z)9w6dkK1{RWlh)R zORe^ZiMQeE%w!E#LT_q4#OW)rK99ZborO@c>JPb?A<}cIB%35*j`r}|gFsB;(*-Nt* zT~&|dEupB%Cdo{a4_!~5cm1xDZ=A2&O)p`2#y-WK?N8RdVeKS06-d*`eXrvz)?Vjy z!Se*z@|V?{!j{stWlF)O;E6P#GL2tZ!f85n3mF^x1Om$#(9~Bn_Og$aUFA9I#ii3`qarG9GBfUh&l`Ta{IjWim8 zoA{Gd;_;@Q{w%TtIx?Kl_PVBWM|wVJCGnIFgEAeZ2FgB1Z37(@5)4bE(BD~}OSoUM zy;XHNi>*S=V^^-WP>sVOo#@DEA?Y1DQNAV7k7>FbN^2=wj-ax5oe;Nv=?6zZR(x+I*}4rSkd*ezn6 zzx9B-8oj^non?}|p%O;DuBg^@d_~J#Cdi7>J#VIwdet+YTiG52H3>aRPm6n~%#ev) zmBNTGEA~Ff`J6L7s~3=u9)-nuF7uMYwr562c?~5cu7_!csRDaalMg!JKYIUGAQr1X z`6zb?4EJtK;+Rp|LW4UH2E*%8zQ$Wg0@$e#@pEXa7sW zJ5wrhfGL@j#~pfT)Bck)Zid*cI{rgnn{(jOuFIy%cC=DK*j>~IV%^`#-AiS^IqdCw z$UGPhTrtLjM#-edZ!6e07XFtFNVvIa!W6oTShMVO*=yPE9Ftj$C1#VTGnjVw4F`82 zZ$T=wBs3hlWAttM4Fk7<$KX@^x-ky(t^tqUclH~wWJ&RmLt?U;WwmCttbJqK^HwrT zboH!D2x zKro~gkPusN>6cL8<;XUvYI51N_SNs2ZQDp6zED}bhf-6u%m#Xf*zrI(MKat<`@`v zZJ$YlvTrz$rdas5tn!!UyXgDtlhfmNef&>Kio3zR)mv;El)KFws!M14&E;dv)nn`l z*Gs^|g@hXu{WJ<52~9a;-QuSkN@QV32le>REc9rHCz!$D<{!6PDVIO{ zIn-a_@j3cJFK`dl!qdWDidIFYc0sW)E|1iS*qEN4A3x~RhDuX6qLAoALhrH173{&U z@SATM_a>qFBc+mG#qLF>rf|I^EDQ^YVQ?xVzu8b6Ru*{CWRdPV-`_jm|7h2P>~1HX z?J|TVXSzNze%z^H4z@$Xj<^zxXLEy&x!&5z7S#IMLFMKJh(Di*z8ere6oGq)gnV=w zY_{HtOv6Cy*G`vJXnzrUv)%E@2H2jh57$P*4T1IQCK-SlFGdC&e}IRC9CDJ!28Y+| z=j8BXQLSKaZuNHif|NfGhZt&;(IaX4ss>1afcC=;gF#igLXU=e#4SRpuE;VAfhjIX z4Yl45#UHN(a&vD#gpIw-xR+AVsoIrJ&cW=gt49D0&Is6#9ZI)2;ee{uGX;h8mCzi(`I(y?vZ z>e%VnHafO#8y(x`9d>Lx9oyzfKks_hS?j!OpLg&5;l8SBR?RVL-d9arbN+v0q&6K3 z)5w_+J0tL+$GREu>F}tBRc@;Ra9?hWzSHN(wt+ zk;?kswZ(JsUaWtu967qpNHe}2T2mv}QN$W@KqfUL$oMns1{~N@o87cqd0Ar$(YJ1s)7q@)tnJDe4YA1MCb8)|s4PJZo%IoE z$Hgftnv!|zi5kBFv2OH9blqmm{%gZN-{ugCtJCR>$5APH#NH?0jJkqLz>2G5eoN>; z#16U}-yzCYwc*Y#*lM7R9|jzk0x%R$i$&vbd=S9h<}*)t50oxA9ndH(PY17|_Q(Z| z)kO|!z)!G$1iC+;OHY(<5XvRocqTvS_pS=xZ#zNJqdn`v4vT0dvIvly2kjYALOr5F z36S!s>ZyC9^(ZohpCuD{V(Q>GhOyRf7uhc6OPii9Nh~M)2G9MrQf&ST-|tTR5(B9>L) zxsekwUu{$sevH?S+fhMGPsHmLOWUD9W!&zkcVd60Zh3%c%ID?BFo&GMvo^hN%rQ6h zKZ{kcvQ^$0Qx+c{fmnuVii@gWte30N(7q{?uYn%!$G&IN+U%}U$3&>o7>2BDB$&gh zWMv%+buzXi-KoB7Yzxn-WUFbiA6QUfnbJ-P_ei zJO1=k9%DhiP$_GX!4+?3%v7x21#7vQkWQUY(Ab%O#?bAwy|<_%MFm=(0GqxVKkeJX zwH)P30GbbF=hsK4NJ;jE_~{lj?DaLy(_i(y2#l6o)LG9waQA@xO9Qx$8ioWA(U(xU zEfjq%4yGh9649xHNC7^Hp+%@0D;hd0R+HiK8u(B|J0t5`q1dPlqECh@U3>^O}fPjOO@n84>CPub@;|CZR*kS1Z z6Fz0z zDV^P1*K1&m6}$q*pKLmh7qiWD5(P9?S#)KR#ZuZ5UQ4*Y^d-C>OS#)f`49~+)~(xK zCI-k|Fn|j{wgJd65RnM!93hd`ll|d#KBz z_k3W-fO%0O?Ni=(+kDA*JK6AYjL2U9ymKD>?hISxQ+hS8`!WTf=)Rqtk9ud_C%Cnp z(pB+kfqugt&;3Bl7V_yC3wnQHXLtj@L4Vd9(>=8PO?ErUBJ0!R8TgL&@b%d=UCu{= z{W;=!3eew4^HzEN?7gLTlw*jH{Ep^z%H?xgd-Bo)NBhRSHaY{C!+B^K ze6J8+Tkk|X$%QTT@QcC_eQ+^7Fc(dF_Xf3@KKJ}j>!0Hv>;Hd~TKNB8@BfinVEtUV z|D+aJKdA+FCME(VRtADUbtZQ9zsf&#md|tJPn(&UnShm*jez4H<)8XzAIzWf&$vJ3 z9~*zw|Fl1UY;6D4_s7Pc{r@mJf5!c(vwzzB?1%Z&_YYft`TuJUpJV=Y4u8h}J-0tT z{<8IF9t@uujQ>Br{GVOia|u)%$Fu|6&8XyjWXvNkjS<>O@7^h;pu<`Nb9=Xt}fY>r-Tx;6O7h&UiC}`bqr?De} zZa(v7teX%9{KLazfPMKJd$r*^$Nr@C$?^=-Srj=Qu@U8h7(|;!Riul9DpTN`s-DiF z&5^~+>xOQVL024-wQfgoH6Uq?L3U{6VDH-1R?~ApJ0oY{)rU9`R|I1#=5<^kJKEuy6-h7;s|4UuwnZ` zh0@^DQl@FwSIkzvMhQ+khLlULeUCnMw2JJDV|zESt?2LS*ku{5bOmHP7ZR#cm9LWT zP?9IWLj8r<>>?QptX10eTy++E1Jqc_^yRu(Rpr`>^=cJ54R$@R5oP=1SxTJkG-?`5 zmd_1&y}p3%11Gge2rrvxHqC@Wl`EW4pfpkv0+kd!Sa8FZ0o?=JQu;K~IZiGMDUjMn#GKH{5BRFB_;?PiQPY-z2QU{kE0Cn0_r1Oce|umua*`8ezwj!h;JQ8s(Tj!S_4grXK$ zo_1rXBRe(#{HN%jH^~>x=omz+dsv8%cSElAcURoH43YGj@SUBQ&0Wbrz*iXz16(@= z7S7wt^x#0ZyI)0MN*HKd8c6X7tyK1r1H<6Tn>EYt44s3g?)hL9u*M6UuiHVzfJgkN3xf2il9&1(^ zX{G6}q4K>MP}<1*JE~RV$3`Qp44tk}WL{wYdr?zKh4WA@W_Z?e%%K4ulWOXq0fn>i1M3JX`fe0g^ea1mvWlLb|FBu8?D8H+$ zrGpEhw1~rCx5uRt&Na@HUG2UWNV=(KCC?RGC=IJum`ZexqTf;G#H+)h!43z<5lNX? zc$GnoqoNt*defB_6Qrdes2>H9`DE}PUm$%kD3HL*7{eRcBVneP{ETLlnK-J4Ru}eI z!;uu1mIj61&Xks+CV6vY^_IA8Txy{2lMK*5^KP~GsT1<&)lDX-gNe9_q_cqCg+3Eo zrN*$6oQ3ZENTnD_Xx$-d{qj+_@b=y)153fSl3=N&I&7UL4$8u^kT@nZtKu+*$X>xm z)(daR&cbUV0JsePRTP4$m)viWHwdD(aGUBI0TIN+^c`XZQ*dI4wX#PVZNP<>ERR@H ziWBDN6YZd%yqXFOgwf~^Q9sPY;BYfxBK?{`CCPqNwvZYca5e$`TZhOY8kBlBMya__ zF0zmxxS*J~3_^Hf{3@Wk$hf<{Cm4#Axm!C7cGARcsFA?^NJ)4bH8y!iPT1*q)4z{T z^EQ{{qh1A_emMTD`JrBlqG9~)Nu$BghlWay%|Lj1i=Lz#05!0y8;GlL^kwh4wklrGk{qOlu*+h3l2fcpy$^DPK1U;D{lha0|EgX zsaQY>RZe54eqGP|X1>wY=`v$FYple#TI?zARI(&4lpCARh03H1E<8}cV#MOtITBh; z_0(Qw;jErJugZxoq?fW;5d*#eNiQjN;j7CJZp-KTzS#FN5u=UB-iZjPuBdSQk>eA$ z*UPR&t=;F8xk<=vDd7BLJkk%Jgy$*Z5wy1+Zn8ux%`3VxKS8 zwnb1-PlrgFpC2wgkvPRjQd~#k^aV#YmOqpVkP(>^y zOAo5dLXm`3M(;E^R-5fbo!3&|;y7E@uyGK$Se!4drX9pQKgy zqm=MD`VP-?R+%_zr*ZZkvBHA8BrJIYLq$-Z21h|qr^ex;P&pciMva-@Y+kZLq#!NB z58D0)q-p<>AY@vS1_qIO2wEiC$Z48w<2)~Ot#PG>pzovZze|b?1;KyDv&)v>3Qj(d z984hv_D#fpA)ow=-$>JEMcXl0O$c!v+oJhREpI+OlICIEjP9jdRGE%EbqfV0lcgsV z8X=v)1SGQo_Xo=NjBY)D7wK4r9y}BgCIBmdlCaUGP%v@LTKI7J@%0VxS; z&Z5Y*{-u)MSw>9Z?|ga+rPK%CRZwN9%PLY)sG55`9@gV8Q5P0e=(PGsZ9J{^2X3~} zdQQ;~zH1YO&=p_+q+en328N#64Y;R|zKiCs|FT#Roi@Q#TcFaAi7QdAWV~pbo`Ry_; zv7UjE0U+R{aTfAbjUcTT`Job)N-JfLkLqwi;dT`fVU$+quas=Q^B6LAv1~f*_~k3L zr-hUbLi!pevx8^F`gxd$wlipXl*oLAwH{f&sgM1S~3SK(&IJ5q|wD_H>3FnWY z;9nwk8Wawo+^Ofk8%AQ+(Wt5`poA!e+bx@)i@!d>epiVYKi5y&#DDqm7-CFXk6raT zkTu;THR{9Ba(BKpHnK5)LZ{<)5^TY5jny8&zB$w_1e}k6 z@x!+VxF1+K6&Y84AINVX1tFB1K-4c)^wbX(44JG{NAW2ZQG#sxr3&BnFQxh^G2@k`rpCBTf zE5W&6DkKpe0iIeQ{WPdC9ukk?u2JR(wqR3$hMq-;f?B z`I1%^yLl0Dymw{YDn@@);QxGML1D*4QdQ@m{lNvF*|WonO{Bm)!H>hJaFA~YFH53# zTAm*n<*IMq51WTR(m~(~d_$~*@e_#@IsdZYH9p{bQCgfViH7+l~X4Q^#9l-CmEU3OvVDEB#7aO4HA&ebTvhoTg5P_a5@ zs`OE6yiyD-NgUNKiTd?X)}1gNze&Tx%tK2$slhjw{LZjARPHljmDVUvu)M~U%&q7g zdG-{C_aLu+|7rmx?F^KN7Hkd+u z_?b|M(XnO3ZB@k*Qeih4rdr_9YJ!geQ^;Hb;4=r$=x((j=c|*`IupE@H*zsrt%rSe zP5@U$il7z?6>+e#Nm*&+8YzXRnb23Ef7b6t>_=2K_QtsDgBl-v<+u!ES?LceMB-lJ z9)6^N;Te7(T3Ctc=tDFYu>&T1Ya>|L~eYFrY49;bJJVCtgr5@>C|>o z`{Ke_xp=x<%jEvVi54}r)?HEm@rH6#QRyAL3k89DIub|jc@Xt05#RtBy(pv-K`Ppa z<;YboV@x6%5I4LRMPtZ_VNawGpi?>et2D#fy2)=5A`d=x9_1wSv?O?{3&Z?EMtLvX z=}L}TzBKCSn=BrLgV@!#J@#ZDxw7R(Sm|_ddOE$Fq&DrQ8`e@~8?mRtkypYUeEVw~ z7rNWf9ShNf(cNSCRxDOgx44qz+46b<@(AC`O`u8$GZukLU@ABy2HydoOyCKOtp;FO z%&kD+V0gPFpb)s4MW7EbpId;x?j2ycdn)L16pjF+Ti{A=iVG6%Fo(c>3@Cg=4j#SB zz}eHuGtN0e!6JiB3LG2ro$(@NyimDPK}UMn{wN)T=NXs5@0i=}2m;pQtK_JYH@X8# zS0zPx(oB6#$Sa=LxO$%OH>l!yEE$xpeTie9ZFkhn)5EXc!_%t?_P71Y_2f@(DKm|Z zq$?XC3cB^vhOSz#!EuWQhXyW2d!l*j5Wl|k42b*ypJEP`p9JC!Voc|iz=a&3#TdJU z>rZ@O_~3&HH+n=3&xn(#enf@A^!6FPw0iz>;NdZxH~?K7+>>$*JpWZ92WCWm0FDj*+_jtGP*-@y3|x&Y*)#ce-lqw1 z7G2w4k>h^%!zQeRWR_|u#_%D$b}OLdJif9B2YyszIM)IINDbbpLq83~@2&(}!05E1 zwh_a(jZ=MGM}7_1$-$-*rTb?}ChPamIV8Bf=%yHsR2~DVLltIgr3h39rwSTOYFmpR1 z#3V2ZBACv!;hN;rp|kd+N7yVLQ%GIM0iWTi#q`~E7bkuz=DEy-#JlT`O5_dCSKslo zAHmzr9s$M8aobWxeC-8A^Z?@Yh=9CTJarx!V;G>j^bKRWiGwG--``I>W+8gxL`w$=V^HBcxpOPU6g%-Aj zhRPQF!pIokcFmR5_JBK0g$^>vGnBCMKB|{CV0WnF)ZJF7eeGpfnndVT z8DwjZz}lzjR%#*Nx*e#n&}LAte+~F8JY(A2TQoj19%1;VxO6Kt)}?oVYn8cjj<>I} z?3}au_|~%*E>o*#rQYiWN_(RCL&MpoYGtg>8M1gb@7ZilqZ7PyeO|$!Jw{{N0uszz zI>{MS=;#s}7w8!H(rh>KT{81%A$H!jpo%>htA=U8^N!VezPghQaGKZn-kH2nIaWzJ ztK(L9^_o4v8a#kNeHHir=OnR z|J@q26JFH%vH>1po67*yQ5lIs{_(3Jo9i%ya087^fbv{a4+wa6O^;VYNl1LIhmt6A zDEvllAtjb`NuHJb+gFd+H>* zbLY`f23_}iVZki2e4V|@bX8^Zy`H(Pu#>Pe9EsC=@&=@s;tzhx9}@ydjK9SNaW z#*^GBjIEGZ6-!W0xHXH96c6qgNCJS!M1lkUY_Xudj1)?gZG(Wb=fo&mbF2ug3aVBn!Ug5 z!S0gzw;=Fk@bY|w^65~*s*OWd1GAWHXO$+I@!xG$qzmGS7!XB*H!MiSz+`k8c1XMG zwq=sPjtVSho=Z>1NEV~aseJru4UoSJ7j}3LSsvra9~f}ZL*86oYqMX(k~mz{0_d>Y zcDiTwDlK96*AaJDPSOz;#jq z)hxol*_b&A*K$Jxwi~czTYm>)2d~?O8tDBHh8T~b@FXs*m4Ae#Kf%>zt@ zBed%?P#tjtGuVkR138!<(vr|mm>yF?4qSgFLRUJl5Met_D7FwF zBEk}QLCk^rKwntFK{c2k9AIyRNW$`h5w)k%P#bVP;!s~2qB{xA;7QBn?cgXI5(qhv z{qckJV)L|-{htVt6s^aUurOc*X~3dN*=Q24Sqgbj{ei7?XeKCJ6jo*%K&AbO`ps{a z%J>qSP{%*k9A&kC0xUuVDaV)WBstxNmAUo~mS?>;0*l20T*yh*d3^-w^4}#d=+`cN z)tdXfuA~|b+Y6mGu|~?v%bTze#aY=aH5VPvfX#U!#!c8%JQcnv|A@LxNfdKsq2>|Z#H(nB!HE*z2_uYZtXG_`@Tg#3A=3lr%PW8_J+hb zOWZ`m6H!(rs3RJcl0)ExY=3CsL0<3SuydAZ>Cr4hLMIimnoO3j8QHh;^xbzT8Xh8A zey~X?)y;`9S0pQj2dLN6SV!It*TJVnyu@IlI(1VvMgtvVm>7GbX~vXygj`hOhKN_AQs?Df{VrA8RG$w zqk8^uLPM>Yl;lqeE(~-GR8k?M+SwiaNrZFu^0sr)TiGIOUV8!kqd6KWL2}PdI5zKe@?sKleEu(9Z!A=^|oX?r!iHmz_oKZ5>E~OlmqS#?fSSR3(*i+zU zT@@{AD%oe9L&?(ZLaoG>Eoe-Qn@Ka?_n_u)tkqJRvEDP_Ni%AQJg(z%a^9c|RtbC| zBk}QHxV30->yr~Pwh&s>5x@)NdI&;5W&#vT$J$R6Y@HKSNjcxWpqSI)VPGD21t)j_e%EGKKKt6N)n?ZuoQHK}Rx%-~YZYVYV_ zIcY2zK7#uo)F9}>n&-~Q;+0h?r@usFfLKu9qS0$ynW9#pZ4Na)0DLjNgJ;+P%7?eB z0~W<1m|@svIHI#?=C8{4Hbqoqy6>D|z$x_;`(R^D!r)2@TMGO6pa(D7OfoxNVHwdD56 zrK`RKq!`{jzW4MbGeVm9t4N^7z?FK>&-J_!&E0IVqJ!O7BK`~e19g@N%cT+VIUTLc z@%HdnoQ!c3SW$g%5-N#5sTkINq^!pfN?UO@TJ^a)Ot)jz(j?_$3` zc~+Yr@wj-~+X;HxXntj17%Q(_}BB+ba0A8x)!^~f*kUVM9j`i`qula-=dKMx9r zAX*U}DA8koY-4mS`Fs4Or1}_}*!}mXyOWT8wCb~ziPzN_n`M=+slYyOqi)rX_u}%$ z9Cu1NJc#=-IeUDCwbfy$an1djtl%U$ljDsVoloFvx8^~?Y7JAndrlp6X!AEejomi% zotLKAg%-Pe(x)XDGJ=cxwj4215w4DqG7z>MF|rUI6rfCqQHi8OT#EXjf)b}`(h$%) zMIzv5^&?dTDfWhs7(`AKDabpDV1M;deoJ=*i7cg@un;w~DuPy*cr@~j)F>2stJC1n zC48CF=J!4tf4Q*oxGt=Hdw4zUaX`40TKW8r$*%h{dr$y~LMe@Vdp&OHM-*=YUCjQd zJl=mmh1|REoz;(__X-_}-J5~Am$`Q`Aj7jSY#EEs zFjXl})A~h?u^vZ(0q?fF%$23h$7nj&fwicXLecFDB;s2Z3M9;ef&!FFT-rcTAPkse z)Y`w7D8ix~gDzaVYdu0Sc8}%>!6T_B{f%J$!d_SXnB8!2m$JjFc$MvS^Rjj=$n^5O zJh(^9zNOh~`8xmrvQ*exEJnjQCML?&_3H}piO=13Ky*J8FHZ^6NwmGMmraazUrWY; zC8h63zA{t6YP0L84mOKa&qrDmbcbF~EkN#y3>+lL$MvI=UB~AmU{S{eL5Q|Oz~zUC zyQn0C@XTakb1qPFw}G9+g@hclSmA{f;_qu8eyv~!M_v!g7WoVH64Xr)I4F*>Y*5!tV6vO_R=INYW#r>-y&tFJF{5M!?G0z)+L_AimPdU`+xp=@AWiA{9B9 zdxiZ&2=O4?Ft+y6XXc@JFkD^JLqc4;p`|+g;64Rtxk$BcWrgqYoW*g!BR*e7aEk3C zo#=j?=Iy--4ZnO`h`evQklXW(oFL5kFt>`(FqbQnMUkl{SvFpZ*oyQRF^Z}rl#hPf zsai-2{c1|iD~8?J8~areS(hTQm6GpB9>18zX+Fw(2WJdzH8@+8cHn@)3i)>1W4iRIz07 zrBe-QN}4yz$QOZctU9uxor4mKtVzgYEt=9{?S&>bT1XHrVHIjc7GUrnfa(uLnSv@dHx6C02n_!Y%xn^< zK%B|a8;ZOwiWDVpl6VA%c^QZtY-S!v=K)azhbH%Vzp$=r!DSl<-)E&A`$6UK%>2|>55SV7G{<`b1W^22Nyb+&p6Fp_}_zAS7Y1pMlC1cKl zy|(=f&o-Ov%XodMG+9KDHf|$EqLe;S=i#>wdDcVl0Cdr#_3A)$2qpGzI!|nA%wPRZ z>0!KWlpY`6PfRdQK6~wYXm^=&S?PJ^kt}xWukRhda9;qzB^I5Ay94~4b?=2q z49=cQW!$#xuYS}{iQ-|L0n{I_zuk`Tzl~tdLzsil`Wdpsdn$;rv}Oh~r#V1f5Y5jg zEShDkYrsew2Ze1k8Fqi|vVL*6aCGi?dsPmQ+A=)KyzMO=h|2o#ozL-vEB}1-WPB~U z6u6o&8>-y6NEn}gFGQI}M_(`-mNa^;U4-MW&~O|^Y<(IGir zIN6g5cV9%;aqWfm==^yngl_V_9Rxu?_8?S?u7&E}jBaz?JFl}O9zjJhk&$>Rh8oRr z6VlQBQ()(N5i-?60%dFQ1qc}v((OhV0bgbJxYDOeze3zT6Z+KuN3)(gLra8F*grHG+85OGG;I&tIqGg@MOj#J`hR@g^~%?LuDXezIYkJ#Fy?z=5e&GxD|%nQtHnJSIE-*6_9^0Fs+;Xn z!wO5|r%pij(7b)Es{Xk;t<_R^eYU&KUKEZ<41f_qf#nH_Xv2i;&Npi`Bu{&8i+N-)8=4e@-O2EEOx4`ZXaP)*@+T5Rd1fcPECY#_GT+ z>B_)oJm2H}ae=gtJil_RulfD59q_o`WxKKEi~~{hXv!b@alC9u%{J2_uTx%~>tp-9 zaIG>ZLXVU&LSyJ4f*|vPbmCSQyKv#&^3d&DGsZ%$=1IS|-IGlgCz|!b-C^n%+!_(n zDMl=v;vFqIDVk&d{gTmsb3=t_^Jx21vttq>p%`jK>=`8x)4BBR$W`fi0o$OL;^E(Q zwl+{oeED**^sG<&_`DcEzDz`Ibg=kXQN7tn*7w2=wGS(dp z6~ll>&rF^=Ht88eIYkQ4tG-uAx@&QPW&AwaV^oeJe^ryl`nbHnzkfIJ{%tUiPg?^n zvIL|lG?T$ki6Hqw_on!qf4kaRI4L!$BG-S$UVOnvPwIb_8IfL3mnUT~;qBS6@znGpnq|5DyPi z=I_D;YRiKCh4OUR*;dI!whKs0Cv#(>@R?c{giZ4;sN*O~RVRl$D{f-Q#V=}xyesET zI&88~|D8b_9n`23gTzGeAW`_Xm*}O(li-OW^%bN?OWqgQLy$_3zBl$KRA8P2Fn78} z$Zs%7sOBXbR? zuqk~*`hRePR%jZJFt#rH=G1zzk1#-}i$q3~x*25KJ^bRSmo;TD>%wNWQ-$0L2V#NL zQwG|HB)|Yt1!@3(Bm&9-+ZqSzK=maDxy%PzL-!2;7I=*UHiHsyg0P1)_#g#+IR{!p z_2mUV%uPa5;_-qx01v-Gs+2NsC(NIp1?Ir?MFGY@=+*ZN&&A1Ox|60E_|O4K>gc4;4gwi5nih{xEY&f=|-HxqPSsKASv9M?dN9e4ZDXflv5^5P>(AX38{3>;}15-SOJ?h~+ch z$=(aP*UZ6nfrGU#`;#pU)JJAPTp;9Pg;v-ybH^eRW zG+rW&iV1YK?~%@Ay&z5)kjyJU^r%Azs6EA#e!1io=3F45zUurky1&gG8iQg^yVhP1 zdqRAJtP|5>uQ_0kwMx}v>Rng)g1i}cbTXeIj$V|3WJ(Iio|$GtZboiOxEuDKFtr@U ztMK5nei5t#&cQ0OcvT-8HB|GnZN0dTJAnufL0ni&J#Ck$LYz%eLf{y}&A@X~nTNX%L6z&D9I zL^_MJy%sBdLlUwUCtV(z?a80^`Mf!muQ;RL4^lYX5WFiS!;}TTjwDgkNRs15^_Jr& znZ_P}grgWX8XP}C>Q>PK36lAWFB4stLNY4=7A;eR89(}zV4gho+l2hnxRp$iTl}DQ z&ZqH^7agWbGSimggd-ZJEFY4zg;>w`aU-sbC*qF>BMqs2<2Syvg*YkJ6(gmys_rrUm(htExi=tZ_^go!ERbSTO9w^r*5WHd)dQ4hCG zw=VaNDJJx3;VN_$Jyge<&!*6$ZOw^Qhihv^TQHWZ?%b=34c6;#*yXf_4TYL46G->yyXICYkLrNu85!kN86$_cFb~KxkpBYMQCT}z~*;rK+ zHX1t|G);I{ROS~p8^hYeEibed#@K^l683AhNgX@i-uJJ59uAE*qhBcQ_m<_wdTa6~ z8bg=n#>Np^gJzc|YhfZQS53Leuh*_C9`3dIm2bGDn7pH{j+g85 zrIJzVTKVT&lW9A7)zCHakNBf$_1QPQ{%Vx9cu}< z+mS{`YfZoHi{x+30VAq-{VT@QfyzI2S~!cHdR*^TPqui zT`cXCUBOF9vy7&^R~+7?ZP>t@k&&E!)4ry+q#m40H=;kLyrYq(6@I2w>w_s+jVw&N zgE68Fa?DFhqHK=GU5Y^qq#^SXpAY7!L=`3=eS9tFdRKmOPd}DQNi+nQ>?pYjj`%3s zk}r_R%RbD0X)V@ncu*y%fIND~ENmQcsuqrHM5Pv@G?u-cU1+0J z*#Xzk3ZiWyenX=gM%_o#Xs$q(9Oq3v7r(x>-*urs6QnMbimF7^e6ItetH8E2zi^&m zqc5`K+!PzNVAxE-N$IT@U5UU89O+mJ;*DE9`+0;mGN~d-d!ptNZ_jLzbt$)s9N$1I z(dszM=1k^6IXfnK-Ja$BFzwu43-5O?7k9ne1U^!XHsbVcMq6z~?ng6$C-(cP>_i>i zZurc?{w~kTH&bIV`+n^P9lwhH2fDJayx(osyFjRRpsOg{XS3&&{APYJt_zFBZ5u)- zMe)S5ttfHM3z@!~6fB9Zsyr_UHs%M7G|^I?cysxq0yGkclRR*XW4|bh-3eu1SW9H< z_&Xa6fLng&NG;8%lWv-Rzc-#+m+@Fl$II`v#pU4H_5w)XP^TKJk8jTd^9)=%W;` z7Qto)-iUrx@E(|uiBdF2FqvM;=D^mNmLQgEW=OvOV(#-yK`(WL(PZ#MWu+fT&rR$BqFDaAk!kkTi_6zB+o(hYn9 zhsud*nvK|;f2`;|AmGE{gAv6v0K3AK-j`zFho#i%wfz|bS1DTZsuTU>?ny7x)dyAG z=c3I7fV+7lW0W8D5fK37K*)N6iB9%O9SCwDdUW{?p)*__Z55B{4w|^)V|lnos^3Z6 zkRy8aCVPQA%MnC)8a+~6E1c#(iV5SF*4^RzN56tcUPMpabk$#0I@!{{?r>eBMW0sI zH51vwcOcPyj6B2`XnlCP9Dt3+3ADN@W`FN2!UEkvAQ&!@1@OBachPFwg^THWcR1QKVC+jf z9Ecd!Dq1=ljw(Fe+1R0QE9q|du-?Y&<`#EhAtzz~iq)FhBaH6m{1*fq0@m|jk*Ad+ zkuh9r@dg8-L=@0ehL)IRahZndYCx*@&lZeX?#m3+3kuP#B0g}*nZ1G*#OEoII|U+& zWaLDiEtguYV4yUFSa&7-IKXbNL6CUSxs-}nSQ34@oz*kGr6R@ne}J9-Vru?^{g@fp znf?j;G5zmm3ljN{u;2f{`7yC`5O8uZ{a;~zoE)DF;D4n2{#%-$Pgd!_K*oQi{Qk!@ zK?$Q(84O6l4?ICB#Sz4psiT}JGojya0h^qJDlO7$UOO{kWM`IVPGm<;i~H zx$eLF;e!*x`ranJK3u)e6#2G&F>83#!TEB+AgUtG?|9NQ^Krf~p@1`yo&7Ms8NFjn zHA?Z0c7J|y%|hSq&Gmw)@M?VY#uTY~bDhr@ba%u!33wfkDVNAAW9kG1^5m>MIe6UE zX1nv=>wBo>RR10V_+CsdV^230O0wU*^EGGbu3R1GGf7Y>;UOsR4!#3AE4Jcp3SXA# z2)cHQ_ z;;c=H;UbKo&?&D3GIBG#-9SixfIQK@!Ok_7+80TGz&X*rIecP$(QVE*n*m3gW;}28 zpX{E}xWq@+uc^&a>^In`VnDajVGfZF+XsmB2hJPnbMax=6hII!*9X`%*C#w1>h0Uj z6#qQNbFoIsdmbmd&#lT~&WX!&#KOvRjQ7Zb&)VoTzgT2G;HPTzJAxDL8@SD9`Goss zx$Bt0e|~bfY3BV&1%|vw$GCYkx-O))^Y0k64b}xJO#hz4>~Vz4|KJAPuc-`~GJ6{wn|Qc%Qu7Uku*Alz;fSKimJo-2E4$ z_u2ky+aGT4Gr`y2%--KD-ya))eEh4Qf7pQG{5;41_Vb6!``h22v7hOL{<$9u1IK^a z{`B=X@0{OXSCN0?{Qf#6{|&`u`tMngnEvN1 zNX)EE|DFZO-NO@mp!IOQJIrv@zJlY2KdvnfzhS_hYV38Lu~c-@ zQZg~61jxIarUl)v7|XmaYn?S&j^2A(+aZQG6lDUwGQ07PgC zKBdM7hf7a-v6BnGQ)1@I@=hvvXM(x{`LolOgb70ppnvL)G2-t$Yqlk|Gsz4v$nAt) z=~dHX>6dvW!d_t~DtOy>B|)Qif0dF5q^dCT^0I@j09Rj+fXXl3)z@%9s@5c&Af4G$Rd*FbF?@+At_`1Z1we~LnZjw?!W z$7f!cGu)hTRyz4^Yo99#8uK&Z5bw77u-LvG+D!pt9gO#;`d});w;B6ahZ(5*scpO$ zNLJ7fdp8CCwls13`4iFxkWK^+v8lA>uAE%#DGDwqY7akH{HlJLL!Ue)Gwf&hXJ~;% zNwd=CX@y%U(U^EeY?iPoB=C?axBVz}_Xp;|DXx87UxdEUl>7O7cN{UXtALtb-1;wz zo_>Igsk6&dp*}P8HW{7b_iBKGBO}(WaVjSWZuyk^oNrU!Rayki)s@&4*aqSS*mIM# zF)x)|6Zr>R+;XptVb>%B^Mk;JHp2lOYWGk5eS-F20;cmsRGGm>I9qra7M) zKY*Cqx#Gq^RIgRyv-Wkck^GOWJX9}4FLc6Mw;c#Tb#rlh`RwYC^~N*n6AjJu3@q%0 zg=*vzmBj_EdJE&b@I7TI>b1S9x`7BZG;~gMRIUnjvV6gu-1!pa4#l2YI8kFEkOy|M zC4-(hR68~UMrYko~Ez zsd<5v69xwP@&Oh@Ut|fd>;sfIBG?_Df%ulTZeha^DLiR|T7w$mfTMbaQUzOy)?lK- zinRNbqTagypYq-_DvG9S7Zy}RKrn%1Q49nLlV_A5l2jxkS;;v`6qKNVphT4=lb@g$i(KSAXHDM7rDNC@&;RcK#4CXRLSW3u1#O@lJ3h>iC4N(k6^uh zY3~@eAG#2eeN%t-(5soZ8WHN2ao>~Z5)>5~@taeft##Al*&Q~y@@6xgOi&cB=uWge z`bC*_F>q3#>c}N^ExrBu&Z#2RyK!4`31nxshG?$N}pQ zKAJKcU!6STws61b3e8B`%|YRr!*{%qP7>nALkD>yhHiBX{Zh)Y(<^omsAevvxf_~1 z`RnTQz76j0vBs=vh?M2vidO_P>{h`~-a&#Jv>sRI+*CQT>0ou%{H|vX^^yF%c7x0N zDc-@}V;!4q4gI%HMC;oLAziDo4KGD=MbSzLT zL*Y%+rbR0z-GHTSn+TVM+&gOO_zf=b^$Zqo**6xjDXBtq-$HebcbZ7wVf!uY0;Q&D zEj?+KuX}BV-HKf8C(bs7oZRTosnzAanJukV_!iZcGwDHReZzC}y^o_$1ispICBKp; zaciaa=HeZ@l`h}tZGTTIVJmNCYsjm*A05DMD)zcEB;B{<&Btgo=Aaez-9n++6Fw;} zrH!ntEPdCE0)qGo4~lQHqNCCHl4PT2xu@+x6u#n%b3lUkK+etW6%zY7RGHr8WidQ* z?$8vEDeUK`f9p?Yg#X0Tcm^HyaX=8)cBV7`Wwc;`-kaK*$i|L#aoOv~%zSC_4vIWq zYm5sUl$@!yS|08@UroDDapNUx-QA}|nX>oGBs{L>w@Tk zOy{fom2myl0j_VBTkMz;UtFKfc zKjP$M%%Hea zm7hx=T*m!W8csgiIkb!A(cwKM!LFxd!E`vs8FQzh zl$}-e`%ZR?bcqz#_K4p{UmF~r5j-WyBpj5FIFq!g^YX4c?$6{5_W9p8T#WT<{7ID? zx%YNsy^kmcs%;?(ME21YDyvIh{37i42DOF6~shygX4!ZuEf2#r|(Kdtnnb) zs>O5qw%swBTtJ2BCnB?(vYX9S1Ct7$-OjtCN!L)LMmVVI{IiDn^nmZRvrWyiiH!-& z+?AZi_VBSOXksm|7LKSK>~8V-@htH&qlrs*;^>oatw*fW8NAcF-&gk9D3(4+eUlcJ z_*`MHL7rjpr>W50AFI5aBnhY9J@{;KF<(*&TOgIyqIr+OEI?e@WOiYWBaHPk%G3VK zO{&aoG@)&V&L6t4Siiy!?e>pD7Wv`ddgwjekxUMs%X#gPIofxL6=u`@uXQd{OGbvoBN$Nh^@SgeA#wDp3EysN?wv7Zm(J8Q&}@&3Dinju~oH4E;zJT8Yx z_{@DRf+0-~H{pIP95+=GN-Pv}o5aTub-8_7dgt7i4uu4N<=*QOOfF@$0^>0bJVF_Zx@^OzNEcKS3lBp z{KTQg0)gG_*MgCou*Z&d56hQo6TkJFbLc#NZ;)QDFn{y*S%D7QO-4nr_vx5!5WeRL z9t^~!)iNSuoU89KCnivjWNg}dP9w~UuBpdrlfXXLXWO0om%`J=_#9(xy)X{8jDa*t z;yJx1bM*|03vH4u1};dpEYzLLT>dp%p7-Xx?bMM^qZKp4121lUFADp14%6gtfAZus zSE#&Z5D~#19=|E=V`LbSk9M*29@iw_uE)D#(tliv4pgho(_x7y>U8)TsUK)ybu%xe z)0d0IHs{M0p*!gsEn#SBwYx26H=GPUFlS+Ys`M6(X`5um?Eyv~*=q_~!B3E?N1Sim zr0Ph~-!pqs@z(cBW~GvFzp>GDMg7QN6*uz$rG{zivkwI%MQ~-cNj42Cd2&Tf4(RW1 zxxDXQ4U`d&&k#o*+bNmo^04jz8=pt}sh?l9{J!T4>70%heVPD$$jWS3=?UlMz6oLG zmZG_YQVH~Zy6$_YE00FjmXAOBJ=Gt}?`HF4c&WaA@TT{><{g>AR&hM#_8TPGzEo0| zCTkth(mg`ZNw)SopIO-XgP=n=?_>UuzbRQIUBfobAZj$n#E;9zlDNz5_FaoN&UcBu zN_*66P)1L03*3&r#iQc1ta#jcYhVv!5Hi(a!^CmJ*zQ%1txV$R0SduUFa%G@XI)L{Gl zHp^$x)`KF`^*Z)J2S=-wZrJWOlhCHo$gJefp>(3L?A5*T=4KRKa z8+cS{#XJ3=${Y25rfW90ZC`C+$oubc9{o)&;nNa}Ca-j8F6bWW=h@|e(V3nSVmHJm@6S#R-T?M9BO!f*27<@lKfqp4@&#avG> z_dnrxKT!Ig?9B%{*m>yPg;Q<}|+06TA7vRKSK*<&>h|k?rkN zh|N|(S^{@2`u_#_b%tPi_SuVW;W64Zv5lYX~C`{+-p`f$4({0eMH9K zDQ1V>J%g3i>3iC`SsnhaHPU>j%un6X)P}_9e z_RaGZ_K9^=bqw^ml~Qk9cv306Ijgj(mA$Q8Xd3z+EZ_C`2S|L(9mSyu|G{!G{-!4< zja?s^t~@r&pEoJahB1VW-nW#kaLV8WBQf{rit%ezUmrWnO8R) zpH*?2ZoZ*k-*s943A1={Rsx|F{pqXA;|XPr)`Y{kzn8wm>`x9>;8AII|Q+?c# zPMeor=y>hdM`C^{^`+15Nm&=FWf-!_rSLTtoR|@{<~%ANV-WLL)9vRwmaw4-=fSA` zOSU^Cbo_^dCc*^2=S130luxs^6~unrtI+T*h_|VHx^ap*>*}tmjGAqG8wR2|#>%&( z*6Il)3_mIouuT^V+Y6h%dfKzj$%YE&k(hF!4{DM+1axiJ3Y%6W-%u1*Ip=$R3D~UD#hX1~R@GdR>;3sGPTVo*y8qNCG8 zBA;1|F!dWt3oEtxIDGqhL!YzZg;%L|a}=&-d$S6`@EFhN{(*72*YUn*4tLPrfU zwv83LS<Gxg+r2g$)4UMbIx{)9*VlXHY~PwIoAy*5 z(T|b6bM3Kk1JYTHI>MZtI?APN^TR8a{kajFv-5kuH3uqWJ=)vxG~##r-mwkmx@M|m z+*BRe#v64;%3RHP%W&^8>i**#G~#KOA{0lso+WMk(G|HdewVbjMD5@OsjDjKuZHNh z?YX1CFfHmF;BnO`l)*eDhm~+h(xATJ)-MGqHxF#4-{VW>+yYnXtG|T0Mnz5Q2ium3 zdA(Mx=G`3Pp}CR5 z+*4lAFdx&?N{6<18xGYy8)#r-=)SqTN9)7Dmd0RmG z(K)Js&09;)@k~^f)~JU`CS4{zZAm^PRl7^IG(kyA{2XX=~Z;ZJ4>PVCPn*`IrT%)4p#aK*C36 zF=$puD7ZlT@w+L`JT^PuABEIz%3j{IzcRg3L|=LttJ0oq(a6dVIv}W|r0M#hR)EkS z+qb15smj-3q3>PsIUCKx3so^oqkemmf`30uF;lcVGM^NyebPI~!LuX6vsWf#v9xdF z^6v!)jz`|nOAR}VHRe7L_c0Ar6SAK_G#s533sFhr7o?w^*z7Uy!4gqf>yXFiq(M06 z9d(P_|J5D|`j=zKf!o6V8%`B1oeg5|@cGKDa@XHZZd|>xG(VtVU=f?K6Qx`b$UDu* z5nTV!p&xtO&+Y#2EIjpsu#7}*P4iJYx~$UVY5nMPUyjrl4$RJvx;>v>kf@U4fHuF> z*{E>V;nq8^j-I!15*PdKe;PP_H(MK@HpTpUi}=aH=8V3;2Kqe{p+57q+2S@GH?-0s zV#2CC+kGBB89R1gbj)V4j%Yq|(mQPK_q{_NL$^{aB8c8TJ?C1DIdg;z>=o>F&oa7- z&TQqxDhpVrwClDJzZQqm_$6xbM_Csp<_-##V$Z)D$K8Ax?>GKs(Oro+Wo&Lw-#UEe z(1dVAUblnsyGvZOnJ5lB){cqBaND1^w;AO0Ok)#rdQ7mMY1@=PPLyn$>&$r{Aj|P2 z$EZ5s!Pe!npUXd|Yx_HB6^B{hatYm?%WxSpxnihWl(Rd3x+bcGUaNl7h(c$04t;90nV`Dw!7ig9L=z ztk7~1H+p&|8bozixYR;3SuvSv8KGHmqjQ-$yZl%u=%%|=nLMTF_jWI=cmgkW|_p1T(X;tBU@^yEj_~^zp-5rwg^XVKPrH4G4O$OCp zNT#}qO3-;_5~lQ^3|s1^KKNyvXM8Zr->%L+yuo41oZI(Z!U2^uKQ8m*&JCLXu+hK4 zF|o1vSF=U4g-T<4zVe0ZozJ*>B{VezKSs%Y^J?5P|81#OAgVEKq4cS~*YRJM70dcf z>?*K)4GfnRaD#>j-|yE$HaPg&7PI4f1}&+$BYbkDy{oR6vTp3Z#Ag2G2lhbikpw<@ z(>s1~uJH_lU$W+}FbJw*FX;z(6zmZ{Tq_WHE&G-c=5;S4Tl*ITKKOJF%Qu9`%iq4~ z3G;po7Rdtb`)e#UURogBE zo8~>_m=#-p8?kHLO#2#(pf_)=b!3{UsdnvBeBSYZ!gSr4Scc(Ohg=^(r0u>RGt~}{ z&XBaDb=XF%y(}%YkM;T%|LXdmiI(oe7xcBowD)Uh9(lYyj`!AM-hD=P2aa;zp!wQU zuU%?B8f6)EV$V&>tWh^$nD$gwh_Ok@VNvK z{Xb8QIaPC953Kuo!te;+k7lJ2R(3k30LuYGK6a)JP6s3yJRLgOwh?`Mr1EsLJT((M z9u0*Bx?S_P**NLW$HJD$^xRPBOV(jAmK#x9%K~ftYHP-hpP>yf?s;q?iqDZR@eJFL zN_ErB_DCN6$uYVps&45v6`floTrR0A1xYB2a zXlj#Q-m7>Ow$LahVsCF|*Vw1Bi!obF-!S-^HD1kI91ndl7ZPZCS!Qcg+buWIWmd!| zC2NEIG8b*iULhD4tf>1pv89|jd2I0Y)Pt#=$#oO%Vw&9a;gRz9^geMZj;2#xYtt<0 zy)Z7juYQuci^_7#26mYp=&;#jz8CBP=c$mrJOWoQ9(;6Mp@&5UWhiUtxv8JtQs|lL z9oa;x(>UKc6~gORx2lvM?@Shs4Q4r7#*nOeN0N5;N2AXhLR!)UlkGq53P|WYUCK@6 zzWuQj!aZOE?@8k3KHtT?sz2p>Ys_r2(thRYl%M|M$lrBV>j6ssg)3WBW;PqmQ|dyg zgs|=Way?wKohc$GJmx#&c5V=n8D;l_zUa7_|LlpfJ)%$fqhneQ=mx!cSI4K>dRBAf z3UeS|Rf@+QzewyY*?XK+?%M5h*n)^gj*VxKB0_o$n!oS4J{iM&iYzTU65pO3g9o2}*p_h9HISb(d4b_|$MeOyzSxal!fU$E$=@8HF)a&e!?-o* z-zJ#lRR#{Cib9!NNeC6J>JoN zPt{o-JE(6g?)Z@JaPPJQNF_U)(EsM_K286R@9@W6RFD^CV>CQkWG!{s5Gv3di- zOzpfXijR1vv^jrq*`2$`Cc*lGx2KGS2is=u&ToTz<3pd`o&JimyJ251HHtO}Y5M)< zfQ?d#FZGQ$LDZmHoRmn+iK#l#g5Jm^)^}!vC?mm;i_hprU9v;f_DZ-(%$!|#6C|Q< zvvBLWG;Oa@IkVCw#;))uwO;9avZV^O{flW$W+u+l+f4}*3oUm}Sf}`43T%>>+3WAp zxIgWA;&++aK5XPQzuacSlAh7%PGQTK>asKT@1^3)-%FKk{`_*PZ0iC?&nLcOy_9VZ zeJ{jDUVr-GvD5k9R)ag$tu2PV3}K#OFIp$lEOMpLG5Fta5}lS_lzo`IQCv4EDe=fL zp*Hrz5#emdrFlPg;^Iqw;@*mbVUo{&Enc+dteVy&e7?F^Y#|n=U|}03SuyNbKJ$<` z*{u`4u_E|g-y55kWx6JB%I=KHI{0=uXqFFoIZwTO9#8i!{?(krm7g{aiM_5RKAY!k zK1cRih_oL)Ka%daRFb+$^F6iR!p^`&5B<5Nlz~_aqi^~6UX6UV^H0;bPZPWg9y~X~ z2V?HBOHTJ8iEor2a+>P2mfm}zI8ZJd_B3r`&ggZ%MNW@tcSC){7G*F1Vp35JORHklW%GvtXY*Qhda)*r}RfYEXnpyVBYoCadDZO}C&bhsNB_%u( zyxt}_dB!Lb!aSNQ$St1U3E5EQs zY$shD7DFEv$|1nX5vRbZ^Pww#tD4}mOPt%WIgCYNqlUaA`(|~bwOn1Fa@`f3zdgq* zVlsHarR3O$BJ*$)uEBeSrFCtu^+!d~$KpP{%tlweTQbU@sy2TWQi02U@i~4p_eWe# z%KJgY4BeWQ3|;|SH`*L`y&l_KN9W1XP5AWYobE@rXl2*JgKs~FZY>v4 z?NUrM9tiMvGN7KZ|1cO|_mgp1i-}uiX5Q{bqrJgB$?ooGT56u1hC4Ty{C2@Unj;!d zstwiT-tD{Qc7hnqI+`;2x|CjF^zIdfD|dIY%Z8sy&Hb?{xhx{AhMuUxf6ZhkmG;io zwof~GP5Jl}5)}i@5?D(`yQT>@UQ%oN|E9m0+`sU*btB{tq~noz^naF2{kPvom;URL zDWOv?Mz&Tac$4 zq!aK^#=k9|f>&XzU6--`6X_@n;om-ye*2}ppD4qXaWUDjPbvFTmI`*B_|6xFACVuP z-4J<)(aN9i)kcS^59aX&8wZ0;;zjUAI!V@VT6;1%I_aD54TrjkhF*N{TT=5FcQwd= ztkdIMTNxKShkxa4-We1_;ZU6zQw^>P_tJhxd@6VL#CCrXCBNa9inbDs!3G9n?cUWJ z%vq3pbSWv*UWx3BT@2gR-W9cbmnFqK7MWLYH#lkE*q%@hti#_S^f^SoTXM z1#bxXU0fWY?=gre)lkaa&vDfR!*3Z$diQU-lx^PThcj9Qsc>iIbveauQ$7#o`+bdW=hU#W%>j( z|F#M$U)YuJBPZS=Ded#(HzHB>@o#rG=w!xp*?+1-GG#o^N286WT{4Wf`q(tey6yAb zX_JS+vePdbW@)^~6S;&m+ordf&gDM*8zTRgpDh132>x|J69C!jf+q5Z#K{Ybzycuf zfpPMO!odP3cmWc0B;Nzq&<|eF1TRz~<)O?+UYtb!fH=rUUho8H|7DTUx{rw?*L_SJ zx&C9~sDJ&KI11X1fb#qQqne%J99mqzLmlFe##ET@DncrTAG3pj=mDU(%TmvHWK z{^v}Sak<{Sow0=$cDUJ)V@1Us*G}9jDPWN~al-E4g38&GSCZd#e7h?4P(b#P%z@)( zyxXI`P*rdA$auan{eb6y`|NF(B9DEc^AXgILF7{HH)-6C!Fh> zk=Fh5)%3;tmRXuEes@dlP&O!&cjZ7A%MsARv@-a!l6IY7n?@ZC%%h!sIkxuyXP@z*yDC4=X>&f9^v((xhzi-x^-znw2 z85eSSuX1L{V&a|t$hJ=NPD5%>#BRm`X*+(iW4CEpM@--E`o6Wc*C_PY`DkYuliG5d z3py4f_l{bLwYq5P50z}cBrj{~Z*J$7D{hr;*RE-XKZ_sOYI#pWYQmp?(+AFoTZtXq zw1LvLWue$-e4)0{U0pS5kM-0$ia7Mm7S0Io?mvCrAvL++qo&TWPnz3|ULkg<`_EnP zd=*%JS(b|Whq%gdy)%y{m!f_}(Z1UQ~u}8Z=3X*B*NBEw%L^LgGnt z*I){DgDRiMka6?(?{s-uMCm)bT{-V6o6ZOsqg7eE)$aJ-$fx%Cu(YI*t26KOazTtMZS?2oAt9vvYTTpK|TK;Xt$G!`(S`X@k`pLCdP-;-}Qg-bafb(0bp; zbuGG=;1Yi1l%+-C#-e{IEYIt_z8L)chUjC@!P2k4?u51Rk2n>4W$~sP=kBkx^Zv== z9WUO-d`O1bjr+B>s$47WAFUogW^8- zt-iFVX4HRnDU%SpDej{7>ii4wUtw)!$Gjsu%OsfTPN?Z;3V+KMp7mW04EB1KRPsUj zQ)8Miqsl91*0`YYeXQlfgdXE-3%|z8K1dUniqDN~UdHWNys|uMEP0oX)7A0H!bU#} zI^|q<^wCBqq2QNi>B2r~JD^|c`aO7DqjJGfAWAW}?}Pxce-De!Y2^VH9pWJtlQ)m8 zUle>O&o##S#oAi$kMjSj-Pa)=-1QpTA~~unUngC&UEpEu!w~CtESf{5k!YRfhp2r1 z_I>&@JFph$CgxPC8M)f5c7`Up_9kYlD}~!@8^>QTG%xY#cL( zOOrsHQmWxGLwYx_PebVh^9g1KtC#@ERYI-zWu83OmBsM{up#7XbXq-Fd1Z_+$9?YF!yIJ#fnLlrjpT}b!-bBKh!B9_9~lcHH0+Vb<6ib9ZM*dhvnFh3cyEKCT7~j%hg4&j&j)7Ry*SKc(H)IpbHQ zXr&jEnyV*!0e5Nl;z<5QdyO#;>Cd47my1Q}xhhNuTPt?3Iaur&8Ia#Q!5S0ioR@vD zlu37@@=CePLBfwLnsKaCOQZb_i-zNMTdX*rpK}|ROFMe#*bX9!tG1r8;O4Tyl=HaY zTc1}=3?ZN;&!Tt~ z4*`i=+lBs52bzF{HfI6*8iC$4C_%Z&5Pb8m9q4s$AE4I1eSk#%>mEZlrIerZY`-?X z6hs)~#ug;RA2NS=NPLhzQ}Rkp!R-%M&kUt3f9BUz6gxiUKJJGbw3+*$TEB2Dbr@00 zT8|QTGz%2{visya8qW*!DrOh+6;IQ5Iw;hYrXsMRud}}j#p3YdKk;95hK^nCJH9L7 zb9Tj`x8l$)i~9^w)_N28Msa1Vcqf}{ityb%$NEP1*BgAXQ=ok~xKI`p%pGIOmG@xl zS@p9*=wiLhn@f`8JOOQ9+R>&$r_|Zh^N2%Aqb9!!sEUya5y;CKIg;G8K2?Wb6sVhd zQF#a3dHl`r|H}pVf3x&oyQP zqYEd^tSl^DppxM3DjcECDtWUm6nTjHpI2X?y>b3+^tKj!uf*N09gUQ z)xq42v9G0W(n}n4VX;!9T|?>~HY<+lXC6-PPE| z>D2QgzU-B6=j*+%Ba#C?}FmV}ICT7lh2%eRK=OEKV#&vRb z0YrJAV0OlcbPk2DRad}5Xj?ykf?*E1f|{ALgR2un78=Mwtgdwq_>~OG{h44^LD2pW z!Z0|B@e-&@l*d$*&Jl{Zu6OE&mBWcO zTvOBlhXfTUzle$v6bqooelTbMabcJpH4#NKQ!69z2oVU3fq)3@vq(VUpsf<|I5gP? zI4lZ>BVdrwzKhb34k2>RJfQQUMj;+Wd-8w0ZdkVzb)zYIQqm5tkhBQ!7AF+#c%Y|F zz;YnkL64ch`5H5WyCgHO6ciQFuyV0A6O)sblM@w1L7PpYp&t_Zi$HJujWk7G#tuh9fBQp(z0Sv073QG`3GBRvc{I>Iunsr^K_Kp6?SdnjX-EiQ9h4NwN+2I} z56=5%S@Jar64}a4zoDS-M_<;F@&R6LGet?ex z`Ve0r54cCp2d-DG2PMLO4QPS2=qB`xS2q``SfaswV^L7hOS04+cka89NL z>;&p1rQz^@MFW4ycn-+W=`KzEE<1)hrTf?Lc>Don}{p&q_d9(K6h4Qfe6_{F_gb zBqsYMngYu(4guFd;{Y2#t7Ps;T*DYArIYarB!V$RwgRLXU@d^N|JyzfIHmoO-U;m@;15}Z82kRH;3h0Gg?k}`f`2_KZjIzJ9wNRvn zI=OIf_#e;$`yr{#g?pHkXaNcTh8B_~$!Ph1)F%-HJUmeN2Q9C3Vqu?zruv{powzk4!$PK2hu6){-ZwRY6M&9DS*)e6v6PK zm_J7fEBE2{ZpEKS)?PQbTQ|U3J5GXo6%gnEmt<>W$XEwfg`|YFO!fo7G0ES^eza;m zP!9T$rG_PitOHw=GM&;gARSl`Se|@NvM#85wS5Kk0&V_XLpT%;dPMY3{;=W$Bn`pC zN=kqDmysl_A;?21HS~YFrw-$pq?OeOLc$^717Ho-4$ug=hO`I!8^A8ON4`(O9mw1s>`SftRjesL2 z#WhSD$OPyEtCQ;kd7$e*>B3Qpgyw%k4Y@3=KgcKHvQUMf&eisioKC8rQm2&luhIZ~ z0XqOW0m3OF`9JtJ7J91u$4HwJH7k#aR(ck2I;C%egn#QurRs&ss@2op>lA&f1vEYwJ2;Es4Pr_)Kglu z2xLieon)Tje4yPTSqpyh1<(d~q2LGR5z-ZGVW<$e56b?h7qenHQoDx1A^)d%0LK7Q zJb=e^l$QN(pRGXLz#NdC41q^sz*otB3tJW7k%C*e-6EBP`;BC&AuF$HiIfItuhSB# z?3!5f4`smvTbKsWCaFgOw|Nl1tC1gA8E6%>#U!f%tyAWQ`G;u1>7@3VGCw)*Do>Ei zpkA`vz;fUm=ml6GSdLttY{fNt`7h8w*2^lI{t0O$xzT{;|5oq74uEGent`53ya9R0 zb(7_UWg^9598?ZQFq9A01*J}b&cXe^*bUHF*DoRCfP{-xegH2JT{0iAr$cFEJ;U_^ zeg9Do#u=0bdl%q^lE&X?g6ILsE(>@AKg#^1@}MrVZs0s*ynwvmN74hh_Ybic4W_jI zaohpTZmk{JQ9Nu}omz0FoQ_G@^1%OzLN#hynO!u4CVS1uGq=!ekc^e{1zRHz83z-1N`lA5$<+)@ zUWkxMLsN-BQ(!LF-h$8ENk~qOpK^8sL#a55Sq&H!kTo$Rw7?O9WL=Q9=HWerDkS7_ zYtl$%VQ+xY0_ed%$npR^APT_9hE4#2R?!K(3PQyi6a#cZ8CE@Oou@zoOFNkvxi~nH zCS@=HaG)xZ!@?j%LfN1hGgDU+GjcvS5CG?+AP)}#f#ZT7$uY?+!a)>b4}~FD37JgB z$i<9L<|s4)gofI83<8=g#h?U55r;)Z5A#z1#2qpn9l#tNBs}R44;F)g=84UDR??t} zPy*D=0DpMwNomkI0vd0uO+$bw({*V$2-9owVKE2<1j{vP2m;j4`6CSpDI979*W|+? zpbsSekp|@huD2#15{1G3Sud1^Uso1|gWfy%qbwQ;X7tz6gXYQq%m=+S0Ij-On-59@ zD^%8$MPU(OZ1zVQ)TRA14F@6ck2H)Zv=U~0+BzLzM8QP<+Bz_z>+Oa?pw{UCL%?DF zv@eu~`%?}K0s6Gh$cI~Jb1Y<#b#-7dU}@Ldve0UUb@Xs(^tyVXImLDI;t{xY^zh()g+J$D;UK*HnGc6RLn|x($cMmUDayJy8CltyIe{fP>QQ{IVHoR$0LSA$RW@&a#)-!4oi@Q;yM8 Date: Thu, 29 Aug 2024 17:14:07 +0200 Subject: [PATCH 3/3] black --- _latex/ensae/td_note_2013_r.py | 1 - 1 file changed, 1 deletion(-) diff --git a/_latex/ensae/td_note_2013_r.py b/_latex/ensae/td_note_2013_r.py index 6cfa1400..bb3d7942 100644 --- a/_latex/ensae/td_note_2013_r.py +++ b/_latex/ensae/td_note_2013_r.py @@ -46,4 +46,3 @@ def extrait_montant(objet): else: print("probl�me ", objet) return None -