From e0ba86b5ba1cc3bcd3cc0be3db1b114afc7920db Mon Sep 17 00:00:00 2001 From: xadupre Date: Sat, 7 Sep 2024 12:52:29 +0200 Subject: [PATCH 1/2] Add notebook for 9/4 --- _doc/articles/2024/2024-11-31-route2024.rst | 30 +++ _doc/practice/index_python.rst | 1 + _doc/practice/py-base/dame_prise.ipynb | 240 ++++++++++++++++++++ 3 files changed, 271 insertions(+) create mode 100644 _doc/practice/py-base/dame_prise.ipynb diff --git a/_doc/articles/2024/2024-11-31-route2024.rst b/_doc/articles/2024/2024-11-31-route2024.rst index 7193fd3..4f1cdf8 100644 --- a/_doc/articles/2024/2024-11-31-route2024.rst +++ b/_doc/articles/2024/2024-11-31-route2024.rst @@ -1,30 +1,60 @@ 2024-11-31 : rappel feuille de route 2024 ========================================= +Le plan des séances est changé après que celles-ci ont eu lieu. + Séance 1 ++++++++ +:ref:`Prises aux dames ` + Séance 2 ++++++++ +Tests unitaires et classes + Séance 3 ++++++++ +:ref:`classes pour représenter un graphe ` + +Fin des classes puis :ref:`les itérateurs ` et +:ref:`numpy broadcast `. + Séance 4 ++++++++ +Dame et minimax. + Séance 5 ++++++++ +* :ref:`Distance d'édition ` +* :ref:`Pivot de Gauss ` + +A propos de la distance d'édition, voir aussi +:ref:`Distance d'édition ` ou encore +:ref:`Distance entre deux mots de même longueur et tests unitaires `. + Séance 6 ++++++++ +* :ref:`Le voyageur de commerce ` +* :ref:`Recheche à base de préfixes ` + +Autres variations autour du problème du voyageur de commerce, +ou TSP pour Travelling Salesman Problem +ou encore circuit hamiltonien: :ref:`l-tsp_kohonen`, :ref:`l-tsp_kruskal`. + Séance 7 ++++++++ +* :ref:`Classe et héritage ` + Séance 8 ++++++++ +* :ref:`Optimisation de la note moyenne ` TD noté 1h30 en seconde partie. Classes et un algorithme. diff --git a/_doc/practice/index_python.rst b/_doc/practice/index_python.rst index 36074e1..c638e5c 100644 --- a/_doc/practice/index_python.rst +++ b/_doc/practice/index_python.rst @@ -39,6 +39,7 @@ Exercices sur le langage python py-base/histogramme_rapide py-base/exercice_pi py-base/de_rotation + py-base/dame_prise ../auto_examples/prog/plot_matador ../auto_examples/prog/plot_partie_dame diff --git a/_doc/practice/py-base/dame_prise.ipynb b/_doc/practice/py-base/dame_prise.ipynb new file mode 100644 index 0000000..7bf49d6 --- /dev/null +++ b/_doc/practice/py-base/dame_prise.ipynb @@ -0,0 +1,240 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Exercices autour des dames\n", + "\n", + "Comment écrire une fonction qui retourne tous les pions qu'une dame peut prendre au [jeu de dames](https://fr.wikipedia.org/wiki/Dames).\n", + "\n", + "Après avoir créé un damier, on créé deux fonctions :\n", + "\n", + "* une fonction qui retourne les dames et les pions\n", + "* une fonction qui retourne les pions qu'une dame peut prendre\n", + "\n", + "Il suffira d'appeler la fonction pour toutes les dames du jeu pour connaître tous les pions qu'un joueur peut prendre avec ses dames.\n", + "\n", + "Dans un premier temps, il convient de représenter le damier. On choisira une matrice [numpy](https://numpy.org/) qu'il faut remplir de valeur numérique :\n", + "\n", + "* 0: case vide\n", + "* 1: pion blanc\n", + "* 2: pion noir\n", + "* 3: dame blanche\n", + "* 4: dame noir\n", + "\n", + "Les valeurs numériques sont toujours plus efficace que des chaînes de caractères. Elles prennent moins de place en mémoire et les opérations sont plus efficaces." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[3 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 2 0 2 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]]\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "\n", + "\n", + "def damier_exemple(n: int = 10):\n", + " d = np.zeros(\n", + " (n, n), dtype=int # il est préférable d'avoir des entiers plutôt que des réels\n", + " )\n", + " d[0, 0] = 3\n", + " d[4, 4] = 2\n", + " d[4, 6] = 2\n", + " return d\n", + "\n", + "\n", + "damier = damier_exemple()\n", + "print(damier)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "On cherche maintenant toutes les dames. On retourne une liste de position. Il n'est pas utile de retourner ce que contient chaque case. On peut retrouver cette information avec le damier." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[(0, 0), (4, 4), (4, 6)]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def cherche_dames(damier) -> list[tuple[int, int]]:\n", + " res = []\n", + " for i in range(damier.shape[0]):\n", + " for j in range(damier.shape[1]):\n", + " if damier[i, j] > 0:\n", + " res.append((i, j))\n", + " return res\n", + "\n", + "\n", + "res = cherche_dames(damier)\n", + "res" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Et maintenant, le plat principal, une fonction retourne les possibles prises pour une dame. L'idée est de regarder dans une direction, de chercher un pion ou une dame de couleur différente et une autre case derrière, et plus précisément, la dernière case où la dame peut se poser. La fonction retourne deux positions : ``[(i1, j1), (i2, j2)]``. La première position est le pion ou la dame à prendre. La dame peut alors se poser dans l'intervalle entre ces deux positions, la première exlue.\n", + "\n", + "Comme cet algorithme est le même quelle que soit la direction, nous allons créer deux fonctions, une pour traiter une direction, l'autre pour les quatre." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "prise=(4, 4), pose=(9, 9)\n" + ] + } + ], + "source": [ + "def position_prise_direction(\n", + " damier, position_dame: tuple[int, int], direction: tuple[int, int]\n", + ") -> list[tuple[int, int]]:\n", + " assert damier[position_dame] >= 3, f\"ce n'est pas une dame {damier[position_dame]}\"\n", + " couleur = damier[position_dame] % 2\n", + " prise = None\n", + " pose = None\n", + " i, j = position_dame\n", + " di, dj = direction\n", + " i += di\n", + " j += dj\n", + " while i >= 0 and i < damier.shape[0] and j >= 0 and j < damier.shape[1]:\n", + " case = damier[i, j]\n", + " if prise is None:\n", + " if case == 0:\n", + " i += di\n", + " j += dj\n", + " continue\n", + " if case % 2 == couleur: # même couleur\n", + " return None, None\n", + " # sinon on prend\n", + " prise = i, j\n", + " i += di\n", + " j += dj\n", + " continue\n", + " # si la prise a déjà eu lieu\n", + " if case == 0:\n", + " # on peut poser la dame\n", + " pose = i, j\n", + " i += di\n", + " j += dj\n", + " continue\n", + "\n", + " # sinon\n", + " if prise is None:\n", + " # pas de case libre derrière donc on ne peut pas prendre\n", + " return None, None\n", + "\n", + " return prise, pose\n", + "\n", + " # La boucle est terminée sans passer par une instruction return?\n", + " return prise, pose\n", + "\n", + "\n", + "prise, pose = position_prise_direction(damier, (0, 0), (1, 1))\n", + "print(f\"prise={prise}, pose={pose}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Et la fonction suivante pour traiter les quatre directions :" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[((4, 4), (9, 9))]\n" + ] + } + ], + "source": [ + "def position_prise(damier, position_dame: tuple[int, int]) -> list[tuple[int, int]]:\n", + " res = []\n", + " for di in [-1, 1]:\n", + " for dj in [-1, 1]:\n", + " prise, pose = position_prise_direction(damier, position_dame, (di, dj))\n", + " if prise is None:\n", + " continue\n", + " res.append((prise, pose))\n", + " return res\n", + "\n", + "\n", + "res = position_prise(damier, (0, 0))\n", + "print(res)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} From dca290e23386978359f53d35fadb9a9ae62b5c1a Mon Sep 17 00:00:00 2001 From: xadupre Date: Sat, 7 Sep 2024 13:27:38 +0200 Subject: [PATCH 2/2] normalize --- _doc/practice/py-base/dame_prise.ipynb | 2 +- requirements-dev.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/_doc/practice/py-base/dame_prise.ipynb b/_doc/practice/py-base/dame_prise.ipynb index 7bf49d6..0e61622 100644 --- a/_doc/practice/py-base/dame_prise.ipynb +++ b/_doc/practice/py-base/dame_prise.ipynb @@ -237,4 +237,4 @@ }, "nbformat": 4, "nbformat_minor": 1 -} +} \ No newline at end of file diff --git a/requirements-dev.txt b/requirements-dev.txt index ef0e8f5..78c9af5 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,5 +1,4 @@ black -black-nb blockdiag cartopy catboost @@ -16,6 +15,7 @@ geopandas ipython jinja2 jupyter +jupyter-black lifelines lightgbm lxml