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 00000000..a9e1c7e1 Binary files /dev/null and b/_doc/articles/2024/sudoku.png differ diff --git a/_doc/articles/index.rst b/_doc/articles/index.rst index 5f51f0c7..9960bcfc 100644 --- a/_doc/articles/index.rst +++ b/_doc/articles/index.rst @@ -9,6 +9,8 @@ Ou *blog*. :caption: 2024 :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/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/_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 00000000..45c77f79 Binary files /dev/null and b/_doc/practice/exams/td_note_2023-2024_rattrapage_sans_correction.pdf differ 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..bb3d7942 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] @@ -27,6 +26,18 @@ def recupere_donnees(): def extrait_montant(objet): + """ + Exemple de chaînes de caractères cherchée: + + :: + + 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. + """ exp = re.compile("[ (]([0-9.,]+) {0,3}euros") res = exp.search(objet) if res: @@ -35,10 +46,3 @@ def extrait_montant(objet): else: 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.""" 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):