{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# <center> Projet IA Grundy R1.13 Python </center>\n",
    "### <center> Grégoire MAROUSE 1C1 & Floriant LE JONCOUR 1C2 </center>\n",
    "\n",
    "***"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1 - Présentation jeu de Grundy :\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Le jeu de Grundy consiste à opposer deux joueurs qui devront partager, chacun leur tour, un tas d'allumettes en deux tas inégaux. Le gagnant est le dernier joueur à avoir joué.\n",
    "\n",
    "### Mise en place\n",
    "\n",
    "\n",
    "Le jeu de Grundy se joue à 2 joueurs selon les règles suivantes : \n",
    "- On commence la partie avec un tas de $n$ allumettes\n",
    "- Les deux joueurs jouent alternativement\n",
    "- On sépare un tas en deux tas contenant un nombre d'allumettes différent. (donc impossible de choisir des tas de 1 ou 2 allumettes)\n",
    "- La personne qui réalise le dernier coup possible gagne la partie. (présence uqiquement de tas contenant une ou deux allumettes à la fin de la partie)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sommaire\n",
    "\n",
    "2 - PRÉREQUIS\n",
    "\n",
    "3 - CODE JEU DE GRUNDY (JOUEUR)\n",
    "- a - Affichage du message de bienvenu\n",
    "- b - Affichage du plateau\n",
    "- c - Condition de victoire\n",
    "- d - Vérifier la validité d'un coup\n",
    "- e - Jouer un coup (joueur)\n",
    "- f - Jeu joueur contre joueur\n",
    "- g - Stockage de la stratégie de l'IA\n",
    "- h - Jeu joueur contre IA\n",
    "\n",
    "4 - IA DU JEU DE GRUNDY\n",
    "- a - Stockage de la stratégie\n",
    "- b - Jouer un coup (IA)\n",
    "- c - Joueur contre IA\n",
    "- d - Jeu IA contre IA\n",
    "- e - Règles d'apprentissage\n",
    "- f - Entrainement IA contre aléatoire\n",
    "- g - Entrainement odri contre lui même\n",
    "- h - Entrainement ordi contre ordi"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "***\n",
    "## 2 - Prérequis"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "import random\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "plt.rcParams['figure.figsize'] = (12, 12)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "***\n",
    "## 3 - Code jeu de Grundy (Joueur)\n",
    "####      a - Affichage du message de bienvenu"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "----------------------------------------------------------------------------\n",
      "                        Règles du jeu de Grundy\n",
      "----------------------------------------------------------------------------\n",
      "Règles : 1 - Les joueur jouent à tour de rôle.\n",
      "         2 - Choisir un tas à séparer en 2 tas de tailles différentes\n",
      "         3 - Celui qui ne peux plus séparer de tas en 2 perd.\n",
      "----------------------------------------------------------------------------\n",
      "\n"
     ]
    }
   ],
   "source": [
    "def welcome_message_joueur():\n",
    "    \"\"\"\n",
    "    Fonction d'affichage du message au début du jeu\n",
    "    \"\"\"\n",
    "    print(\"\"\"\n",
    "----------------------------------------------------------------------------\n",
    "                        Règles du jeu de Grundy\n",
    "----------------------------------------------------------------------------\n",
    "Règles : 1 - Les joueur jouent à tour de rôle.\n",
    "         2 - Choisir un tas à séparer en 2 tas de tailles différentes\n",
    "         3 - Celui qui ne peux plus séparer de tas en 2 perd.\n",
    "----------------------------------------------------------------------------\n",
    "\"\"\")\n",
    "    \n",
    "# Example usage:\n",
    "welcome_message_joueur()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "####      b - Affichage du plateau"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " . oo . ooo . o . o .\n"
     ]
    }
   ],
   "source": [
    "def display_board_with_x(plateau):\n",
    "    \"\"\"\n",
    "    Fonction d'affichage du platea de jeu au format :   . oo . o .\n",
    "    Prend en argument le tableau représentatif du plateau de jeu\n",
    "    ne renvoi rien\n",
    "    \"\"\"\n",
    "    #Affichage des \".\"\n",
    "    for i in range (len(plateau)) :\n",
    "        print(\" . \",end=\"\")\n",
    "        indice=0 \n",
    "        valeurL=plateau[i]\n",
    "        #Affichage des \"o\"\n",
    "        while(indice<valeurL):\n",
    "            print(\"o\",end=\"\")\n",
    "            indice+=1\n",
    "    print(\" .\")\n",
    "\n",
    "# Example usage:\n",
    "l=[2,3,1,1]\n",
    "display_board_with_x(l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### c - Condition de victoire"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "On vérifie la présence de tas de taille supérieur à 2 dans le tableau. Si c'est le cas, ça qui signifie qu'il reste encore des coups disponible et donc la fonction renvoie False. Sinon elle renvoie True.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def victoire(tab) :\n",
    "    \"\"\"\n",
    "    Fonction qui test si la partie est fini\n",
    "    param tab : le tableau représentatif du plateau de jeu\n",
    "    renvoi un bouleen True si le joueur a gagné (partie finie)\n",
    "    \"\"\"\n",
    "    victoire=True\n",
    "    for i in range(len(tab)):\n",
    "        if (tab[i]!=1 and tab[i]!=2):\n",
    "            victoire=False\n",
    "    return victoire\n",
    "\n",
    "# Example usage:\n",
    "victoire([1,2,1,2,2,1])\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### d - Vérifié la validité d'un coup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "On vérifie si la taille du tas sélectionné est valide. Si c'est le cas, on vérifie ensuite si la séparation du tas choisi est possible. Sinon la séparation est considérée comme False. La fonction renvoie ensuite la comparaison entre la vérification de la taille du tas et celle de la séparation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def testCoup(plateau, coup) :\n",
    "    \"\"\"\n",
    "    Fonction qui vérifie que le coup est valide avant de le jouer\n",
    "    Prend en parametre le tableau représentatif du plateau de jeu et le coup a jouer\n",
    "    Renvoi un bouleen : True si le coup est valide sinon False\n",
    "    \"\"\"\n",
    "    tasValid= ( 0<=coup[0]<len(plateau) and plateau[coup[0]]>2 )\n",
    "    coupValid=False\n",
    "    if tasValid :\n",
    "        coupValid= ( 1<=coup[1]<=(plateau[coup[0]]-1) and coup[1]!=(plateau[coup[0]]-coup[1]) )\n",
    "\n",
    "    return (tasValid and coupValid)\n",
    "\n",
    "# Example usage:\n",
    "l=[2,3,1,1]\n",
    "t1 = testCoup(l,[1,2]) #true\n",
    "t2 = testCoup(l,[0,1]) #false"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### e - Jouer un coup (Joueur)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "On enregistre le tas et la séparation que le joueur souhaite réaliser puis on appele la fonction testCoup() tant que le coup n'est pas jouable. On réalise ensuite les modifications sur le plateau"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " . oo . oooo . o . o .\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[2, 3, 1, 1, 1]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def joueur(tab) :\n",
    "    \"\"\"\n",
    "    Fonction qui permet au joueur de jouer un coup\n",
    "    Prends en parametre le tableau représentatif du plateau de jeu\n",
    "    Ne renvoi rien, modifi directement le tableau\n",
    "    \"\"\"\n",
    "    coup = []\n",
    "    coup.append(int(input(\"Quel tas souhaitez-vous séparer ? \")))\n",
    "    coup.append(int(input(\"Quel taille pour le premier sous-tas ? \")))\n",
    "\n",
    "    while (not(testCoup(tab,coup))) :\n",
    "        print(\"Veuiller saisir un coup valide !\")\n",
    "        coup[0]=int(input(\"Quel tas souhaitez-vous séparer ? \"))\n",
    "        coup[1] = int(input(\"Quel taille pour le premier sous-tas ? \"))\n",
    "        \n",
    "    tab[coup[0]]-=coup[1]\n",
    "    tab.append(coup[1])\n",
    "\n",
    "# Example usage:\n",
    "l=[2,4,1,1]\n",
    "display_board_with_x(l)\n",
    "joueur(l)\n",
    "l"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### f - Jeu joueur contre joueur"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Fonction qui permet de jouer au jeu. On initialise un tableau de taille n, une variable tour qui va nous permettre de savoir à qui est-ce le tour de jouer et une variable v qui va nous permettre de vérifier si la partie est terminée ou non."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "----------------------------------------------------------------------------\n",
      "                        Règles du jeu de Grundy\n",
      "----------------------------------------------------------------------------\n",
      "Règles : 1 - Les joueur jouent à tour de rôle.\n",
      "         2 - Choisir un tas à séparer en 2 tas de tailles différentes\n",
      "         3 - Celui qui ne peux plus séparer de tas en 2 perd.\n",
      "----------------------------------------------------------------------------\n",
      "\n",
      " au tour du premierjoueur ... \n",
      "la taille des tas est : [5]\n",
      " . ooooo .\n",
      " au tour du deuxiemejoueur ... \n",
      "la taille des tas est : [4, 1]\n",
      " . oooo . o .\n",
      " au tour du premierjoueur ... \n",
      "la taille des tas est : [3, 1, 1]\n",
      " . ooo . o . o .\n",
      " . oo . o . o . o .\n",
      "Fin! le premier joueur à gagné !\n"
     ]
    }
   ],
   "source": [
    "def JvJ(n) :\n",
    "    \"\"\"\n",
    "    Fonction qui permet de jouer une partie joueur contre joueur\n",
    "    Prends en parametre la taille du tas de départ\n",
    "    ne renvoi rien\n",
    "    \"\"\"\n",
    "    welcome_message_joueur()\n",
    "\n",
    "\n",
    "    tab = [n]\n",
    "    tour = -1\n",
    "    v= False\n",
    "    while not v :\n",
    "        tour +=1\n",
    "        print(\" au tour du \"+(\"premier\" if tour%2==0 else \"deuxieme\")+\"joueur ... \\nla taille des tas est :\",tab)\n",
    "        display_board_with_x(tab)\n",
    "        joueur(tab)\n",
    "        v = victoire(tab)\n",
    "    display_board_with_x(tab)\n",
    "    print(\"Fin! le \"+(\"premier\" if tour%2==0 else \"deuxieme\")+ \" joueur à gagné !\")\n",
    "\n",
    "# Example usage:\n",
    "JvJ(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "***\n",
    "## 4 - IA du jeu de Grundy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### a - Stockage de la stratégie"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Pour initialiser le dictionnaire contenant la stratégie, on utilise une fonction récursive qui effectue un parcours de tous les chemins possibles depuis la situation donnée. Le dictionnaire ressence pour chaque situation un autre dictionnaires des coups possibles dans cette situation précise. on associe a chacun de ces coups une vleur initiale $n$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'5': {'0,1': 1, '0,2': 1}, '4': {'0,1': 1}, '3': {'0,1': 1}}"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def stratInit(plat,strat,n) :\n",
    "    \"\"\"\n",
    "    Fonction récursive qui gère l'initialisation du dictionnaire de stratégie de l'IA par un parcours de chemin depuis un plateau de jeu.\n",
    "    Prends en paramettre plat le plateau de jeu, strat la variable qui contiendra le dictionnaire de stratégie et n la valeurs initiale des cases du dicitionnaire\n",
    "    \"\"\"\n",
    "\n",
    "    string = \",\".join(str(x) for x in plat)\n",
    "    strat[string]={}\n",
    "    for x in range(len(plat)) :\n",
    "        for y in range(1,(plat[x]//2 if plat[x]%2==0 else (plat[x]//2)+1)) :\n",
    "            coup=str(x)+\",\"+str(y)\n",
    "            strat[string][coup]=n\n",
    "\n",
    "    for i in range(len(plat)) :\n",
    "        for j in range(1,(plat[i]//2 if plat[i]%2==0 else (plat[i]//2)+1)):\n",
    "            test = plat.copy()\n",
    "            test[i]-=j\n",
    "            test.append(j)\n",
    "            while 1 in test or 2 in test :\n",
    "                if 1 in test :\n",
    "                    test.remove(1)\n",
    "                if 2 in test :\n",
    "                    test.remove(2)\n",
    "            test.sort()\n",
    "            stratInit(test,strat,n)\n",
    "    return\n",
    "\n",
    "# Example usage :\n",
    "strat = {}\n",
    "stratInit([5],strat,1)\n",
    "strat.pop('')\n",
    "strat"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### b - Jouer un coup (IA)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "La fonction coup IA Permet à l'IA de jouer un coup. Pour cela on commence par retrouver la situation dans la stratégie en normalisant le plateau. Puis on choisie un coup aléatoire dans le dictionnaire en fonction des pondérations associés à chauqe coup. Enfin on modifie le plateau de jeu en fonction du coup choisi et on renvoi le coup en String qui est la clef du dictionnaire choisie dans cette situation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " L'IA à séparer le tas  2 en 1 et 4\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[1, 1, 4, 1]"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def coupIA(tab,strat,verb=False) :\n",
    "    \"\"\"\n",
    "    fonction qui permet à l'IA de jouer un coup sur le plateau : tab à partir d'une stratégie donnée : strat\n",
    "    Prend en paramètre tab le plateau de jeu, strat le dictionnaire de stratégie de l'IA et l'option verb un booléen qui gère l'affichage\n",
    "    renvoi le coup jouer en String\n",
    "    \"\"\"\n",
    "    \n",
    "    jeu = tab.copy()\n",
    "    while 1 in jeu or 2 in jeu :\n",
    "        if 1 in jeu :\n",
    "            jeu.remove(1)\n",
    "        if 2 in jeu :\n",
    "            jeu.remove(2)\n",
    "    string = \",\".join(str(x) for x in jeu)\n",
    "    coupStr = random.choice([key for key, value in strat[string].items() for x in range(value)])\n",
    "    coup = [int(x) for x in coupStr.split(\",\")]\n",
    "    if verb : print(\" L'IA à séparer le tas \",((len(tab)-len(jeu))+coup[0]),\"en\",coup[1],\"et\",tab[(len(tab)-len(jeu))+coup[0]]-coup[1])\n",
    "    tab[(len(tab)-len(jeu))+coup[0]]-=coup[1]\n",
    "    tab.append(coup[1])\n",
    "    return coupStr\n",
    "\n",
    "# Example usage:\n",
    "tab=[1,1,5]\n",
    "coupIA(tab,strat,True)\n",
    "tab"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### c - Jeu joueaur contre IA"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Fonction qui encadre le cycle de jeu entre un joueur et une IA, pour un jeu de taille n et la stratégie strat pour l'IA. A la fin on renvoi un booléen : True si l'IA à gagnée et un dictionnaire qui stock la partie dont on pourra se servir pour permettre à l'IA d'apprendre."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Au tour de l'IA ... \n",
      " La taille des tas est : [3]\n",
      " . ooo .\n",
      " L'IA à séparer le tas  0 en 1 et 2\n",
      " . o . oo .\n",
      "Fin! L'IA a gagné !\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "({'3': '0,1'}, True)"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def JvAI(n,strat) :\n",
    "    \"\"\"\n",
    "    Fonction qui permet de jouer une partie joueur contre une IA\n",
    "    Prends en parametre la taille du tas de départ et la stratégie de l'IA\n",
    "    \"\"\"\n",
    "\n",
    "    tab = [n]\n",
    "    partie = {} \n",
    "    tour = 0\n",
    "    v= False\n",
    "    while not v :\n",
    "        situation = tab.copy()\n",
    "        while 1 in situation or 2 in situation :\n",
    "            if 1 in situation :\n",
    "                situation.remove(1)\n",
    "            if 2 in situation :\n",
    "                situation.remove(2)\n",
    "        string = \",\".join(str(x) for x in situation)\n",
    "\n",
    "        tour +=1\n",
    "        print(\"Au tour \"+(\"du joueur \" if tour%2==0 else \"de l'IA \")+\"... \\n La taille des tas est :\",tab)\n",
    "        display_board_with_x(tab)\n",
    "\n",
    "        if tour%2==0 :\n",
    "            joueur(tab) \n",
    "        else :\n",
    "            coup=coupIA(tab,strat,True)\n",
    "            partie[string]=coup\n",
    "\n",
    "        tab.sort()\n",
    "        v = victoire(tab)\n",
    "\n",
    "    display_board_with_x(tab)\n",
    "    print(\"Fin! \"+(\"Le joueur\" if tour%2==0 else \"L'IA\")+ \" a gagné !\")\n",
    "    return partie,True if tour%2==1 else False\n",
    "\n",
    "# Example usage:\n",
    "# strat aléatoire\n",
    "aleatoire = {}\n",
    "stratInit(tab,aleatoire,1)\n",
    "aleatoire.pop('')\n",
    "JvAI(3,aleatoire)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### d - Jeu IA contre IA"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Fonction qui encadre le cycle de jeu entre 2 IA dans le but de réaliser un entrainement en boucle soit contre l'aléatoire si on entraine qu'une des deux stratégie l'autre est seulempent initialisée, sinon contre une stratégie précise ou une autre IA qui apprends séparement."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "({'7': '0,2', '3': '0,1'}, True, {'5': '0,2'})"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def IAvIA(n,strat1,strat2,verb=False) :\n",
    "    \"\"\"\n",
    "    Fonction qui permet de jouer une partie joueur contre IA\n",
    "    Prends en parametre la taille du tas de départ n, strat1 et strat2 les stratégie des IA et l'option verb pour gérer l'affichage.\n",
    "    renvoi true si l'IA 1 a gagné ainsi que les enregistrements des parties de chaque IA en dictionnaire\n",
    "    \"\"\"\n",
    "    tab = [n]\n",
    "    partie1 = {} \n",
    "    partie2 = {} \n",
    "    tour = -1\n",
    "    v= False\n",
    "    while not v :\n",
    "        situation = tab.copy()\n",
    "        while 1 in situation or 2 in situation :\n",
    "            if 1 in situation :\n",
    "                situation.remove(1)\n",
    "            if 2 in situation :\n",
    "                situation.remove(2)\n",
    "        string = \",\".join(str(x) for x in situation)\n",
    "\n",
    "        tour +=1\n",
    "        if verb :\n",
    "            print(\"Au tour \"+(\"de l'IA 1 \" if tour%2==0 else \"de l'IA 2 \")+\"... \\n La taille des tas est :\",tab)\n",
    "            display_board_with_x(tab)\n",
    "\n",
    "        if tour%2==0 :\n",
    "            coup=coupIA(tab,strat1)\n",
    "            partie1[string]=coup\n",
    "        else :\n",
    "            coup=coupIA(tab,strat2)\n",
    "            partie2[string]=coup\n",
    "\n",
    "        tab.sort()\n",
    "        v = victoire(tab)\n",
    "    if verb :\n",
    "        display_board_with_x(tab)\n",
    "        print(\"Fin! \"+(\"L'IA 1\" if tour%2==0 else \"L'IA 2\")+ \" a gagné !\")\n",
    "    return partie1,True if tour%2==0 else False,partie2\n",
    "\n",
    "# Example usage:\n",
    "# strat contre aleatoire\n",
    "tab = [7]\n",
    "strat = {}\n",
    "stratInit(tab,strat,5)\n",
    "strat.pop('')\n",
    "aleatoire=strat.copy()\n",
    "IAvIA(7,strat,strat)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### e - Règles d'aprentissage "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Pour l'apprentissage nous avons choisi des règles simples : si l'IA gagne on ajoute 1 au coéfficients des coups qu'elle a jouer si elle perds on enlève 1. De plus, le coéfficiant minimum est 1 pour ne jamais faire disparaitre completement un coup \"par malchance\"."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Au tour de l'IA ... \n",
      " La taille des tas est : [7]\n",
      " . ooooooo .\n",
      " L'IA à séparer le tas  0 en 1 et 6\n",
      "Au tour du joueur ... \n",
      " La taille des tas est : [1, 6]\n",
      " . o . oooooo .\n",
      "Au tour de l'IA ... \n",
      " La taille des tas est : [1, 2, 4]\n",
      " . o . oo . oooo .\n",
      " L'IA à séparer le tas  2 en 1 et 3\n",
      "Au tour du joueur ... \n",
      " La taille des tas est : [1, 1, 2, 3]\n",
      " . o . o . oo . ooo .\n",
      " . o . o . o . oo . oo .\n",
      "Fin! Le joueur a gagné !\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'7': {'0,1': 4, '0,2': 5, '0,3': 5},\n",
       " '6': {'0,1': 5, '0,2': 5},\n",
       " '5': {'0,1': 5, '0,2': 5},\n",
       " '4': {'0,1': 4},\n",
       " '3': {'0,1': 5},\n",
       " '3,4': {'0,1': 5, '1,1': 5},\n",
       " '3,3': {'0,1': 5, '1,1': 5}}"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def apprend(rec,strat) :\n",
    "    \"\"\"\n",
    "    Fonction qui modifie la stratégie de l'IA en fonction de la partie et de la victoire\n",
    "    Prends en paramettre rec le tupple contenant le dictionnaire ou est stocké la partie et un booléen de victoire sur cette partie\n",
    "    Prend aussi en paramettre la stratégie à modifier\n",
    "    \"\"\"\n",
    "    partie=rec[0]\n",
    "    victoire=rec[1]\n",
    "\n",
    "    for situation in partie :\n",
    "        coup = partie[situation]\n",
    "        if victoire :\n",
    "            strat[situation][coup]+=1\n",
    "        elif strat[situation][coup]>1 :\n",
    "            strat[situation][coup]-=1\n",
    "\n",
    "# Example usage:\n",
    "strat = {}\n",
    "stratInit([7],strat,5)\n",
    "strat.pop('')\n",
    "apprend(JvAI(7,strat),strat)\n",
    "strat"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### f - entrainement IA contre aléatoire"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Avec les fonctions précédentes, on peut créer une stratégie initiale et une stratégie aléatoire puis les faire jouer ensembles un nombre de parties choisi sur un jeu de taille n pour entrainer l'IA sur un grand nombre de parties très rapidement et donc dévelloper une stratégie gagnante probabiliste à cause de la partie aléatoire des coups jouer par l'IA (cf jouer un coup IA plus haut) mais qui peut s'avérer très efficace et de plus en plus efficace avec le nombre de parties jouées.\n",
    "La fonction calcule également le taux de victoire après chaque partie et renvoi le tableaux de ces taux à la fin.\n",
    "<br>Plusieurs paramètres peuvent influencer l'apprentissage de l'IA comme son adverssaire (l'aléatoire ci-dessous), le nombre de parties (nbParties), le coefficiant initial de la stratégie (5 ci-dessous) et les règles d'apprentissages évidemment.\n",
    "<br>Pour les 2 prochaines sections on réalisera une fonction similaire en modifiant l'adverssaire.\n",
    "<br><br>\n",
    "L'aléatoire n'est surement pas un adversaire très performant mais permet d'explorer toutes les situations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'12': {'0,1': 6, '0,2': 4978, '0,3': 4446, '0,4': 3, '0,5': 46}, '11': {'0,1': 5, '0,2': 5, '0,3': 5, '0,4': 5, '0,5': 5}, '10': {'0,1': 3, '0,2': 5, '0,3': 4, '0,4': 1}, '9': {'0,1': 1, '0,2': 565, '0,3': 1427, '0,4': 1}, '8': {'0,1': 1890, '0,2': 1, '0,3': 1}, '7': {'0,1': 1, '0,2': 1, '0,3': 1}, '6': {'0,1': 1, '0,2': 2117}, '5': {'0,1': 937, '0,2': 1}, '4': {'0,1': 1}, '3': {'0,1': 9731}, '3,4': {'0,1': 1619, '1,1': 2425}, '3,3': {'0,1': 1, '1,1': 1}, '3,5': {'0,1': 1, '1,1': 1, '1,2': 1922}, '3,6': {'0,1': 1, '1,1': 1, '1,2': 1}, '4,5': {'0,1': 4, '1,1': 9, '1,2': 1}, '4,4': {'0,1': 1, '1,1': 1}, '3,7': {'0,1': 530, '1,1': 766, '1,2': 1, '1,3': 1013}, '3,3,4': {'0,1': 1, '1,1': 1, '2,1': 1}, '3,3,3': {'0,1': 171, '1,1': 423, '2,1': 144}, '4,6': {'0,1': 371, '1,1': 8, '1,2': 338}, '3,8': {'0,1': 1, '1,1': 1, '1,2': 826, '1,3': 44}, '3,3,5': {'0,1': 5, '1,1': 5, '2,1': 5, '2,2': 5}, '4,7': {'0,1': 1, '1,1': 1, '1,2': 1, '1,3': 1}, '3,4,4': {'0,1': 5, '1,1': 5, '2,1': 5}, '5,6': {'0,1': 1, '0,2': 22, '1,1': 13, '1,2': 9}, '5,5': {'0,1': 2, '0,2': 1, '1,1': 1, '1,2': 1}, '3,9': {'0,1': 5, '1,1': 5, '1,2': 5, '1,3': 5, '1,4': 5}, '3,3,6': {'0,1': 311, '1,1': 387, '2,1': 40, '2,2': 193}, '3,4,5': {'0,1': 3, '1,1': 39, '2,1': 1, '2,2': 882}, '4,8': {'0,1': 5, '1,1': 5, '1,2': 5, '1,3': 5}, '5,7': {'0,1': 5, '0,2': 5, '1,1': 5, '1,2': 5, '1,3': 5}}\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[0.0,\n",
       " 0.0,\n",
       " 0.0,\n",
       " 25.0,\n",
       " 40.0,\n",
       " 33.333333333333336,\n",
       " 42.857142857142854,\n",
       " 50.0,\n",
       " 55.55555555555556,\n",
       " 60.0,\n",
       " 54.54545454545455,\n",
       " 50.0,\n",
       " 46.15384615384615,\n",
       " 50.0,\n",
       " 46.666666666666664,\n",
       " 50.0,\n",
       " 47.05882352941177,\n",
       " 50.0,\n",
       " 47.36842105263158,\n",
       " 45.0,\n",
       " 47.61904761904762,\n",
       " 45.45454545454545,\n",
       " 47.82608695652174,\n",
       " 50.0,\n",
       " 52.0,\n",
       " 53.84615384615385,\n",
       " 51.851851851851855,\n",
       " 50.0,\n",
       " 48.275862068965516,\n",
       " 50.0,\n",
       " 51.61290322580645,\n",
       " 50.0,\n",
       " 48.484848484848484,\n",
       " 50.0,\n",
       " 51.42857142857143,\n",
       " 52.77777777777778,\n",
       " 54.054054054054056,\n",
       " 55.26315789473684,\n",
       " 56.41025641025641,\n",
       " 55.0,\n",
       " 56.09756097560975,\n",
       " 57.142857142857146,\n",
       " 58.13953488372093,\n",
       " 59.09090909090909,\n",
       " 60.0,\n",
       " 58.69565217391305,\n",
       " 57.4468085106383,\n",
       " 58.333333333333336,\n",
       " 59.183673469387756,\n",
       " 58.0,\n",
       " 58.8235294117647,\n",
       " 59.61538461538461,\n",
       " 58.490566037735846,\n",
       " 57.407407407407405,\n",
       " 56.36363636363637,\n",
       " 57.142857142857146,\n",
       " 57.89473684210526,\n",
       " 58.62068965517241,\n",
       " 57.6271186440678,\n",
       " 56.666666666666664,\n",
       " 55.73770491803279,\n",
       " 56.45161290322581,\n",
       " 55.55555555555556,\n",
       " 56.25,\n",
       " 56.92307692307692,\n",
       " 56.06060606060606,\n",
       " 56.71641791044776,\n",
       " 57.35294117647059,\n",
       " 57.971014492753625,\n",
       " 58.57142857142857,\n",
       " 57.74647887323944,\n",
       " 58.333333333333336,\n",
       " 58.9041095890411,\n",
       " 59.45945945945946,\n",
       " 58.666666666666664,\n",
       " 59.21052631578947,\n",
       " 58.44155844155844,\n",
       " 57.69230769230769,\n",
       " 58.22784810126582,\n",
       " 57.5,\n",
       " 56.79012345679013,\n",
       " 56.09756097560975,\n",
       " 56.626506024096386,\n",
       " 55.95238095238095,\n",
       " 56.470588235294116,\n",
       " 56.97674418604651,\n",
       " 56.32183908045977,\n",
       " 56.81818181818182,\n",
       " 57.30337078651685,\n",
       " 57.77777777777778,\n",
       " 57.142857142857146,\n",
       " 56.52173913043478,\n",
       " 56.98924731182796,\n",
       " 56.38297872340426,\n",
       " 56.8421052631579,\n",
       " 57.291666666666664,\n",
       " 57.7319587628866,\n",
       " 57.142857142857146,\n",
       " 56.56565656565657,\n",
       " 57.0,\n",
       " 57.42574257425743,\n",
       " 57.84313725490196,\n",
       " 57.28155339805825,\n",
       " 57.69230769230769,\n",
       " 58.095238095238095,\n",
       " 58.490566037735846,\n",
       " 57.94392523364486,\n",
       " 58.333333333333336,\n",
       " 58.71559633027523,\n",
       " 58.18181818181818,\n",
       " 58.55855855855856,\n",
       " 58.92857142857143,\n",
       " 58.4070796460177,\n",
       " 58.771929824561404,\n",
       " 59.130434782608695,\n",
       " 59.48275862068966,\n",
       " 59.82905982905983,\n",
       " 59.32203389830509,\n",
       " 59.66386554621849,\n",
       " 60.0,\n",
       " 60.33057851239669,\n",
       " 60.65573770491803,\n",
       " 60.97560975609756,\n",
       " 61.29032258064516,\n",
       " 61.6,\n",
       " 61.904761904761905,\n",
       " 62.20472440944882,\n",
       " 62.5,\n",
       " 62.01550387596899,\n",
       " 61.53846153846154,\n",
       " 61.83206106870229,\n",
       " 62.121212121212125,\n",
       " 61.65413533834587,\n",
       " 61.19402985074627,\n",
       " 61.48148148148148,\n",
       " 61.76470588235294,\n",
       " 62.043795620437955,\n",
       " 61.594202898550726,\n",
       " 61.8705035971223,\n",
       " 61.42857142857143,\n",
       " 61.702127659574465,\n",
       " 61.971830985915496,\n",
       " 62.23776223776224,\n",
       " 62.5,\n",
       " 62.758620689655174,\n",
       " 62.32876712328767,\n",
       " 61.904761904761905,\n",
       " 62.16216216216216,\n",
       " 61.74496644295302,\n",
       " 61.333333333333336,\n",
       " 61.58940397350993,\n",
       " 61.18421052631579,\n",
       " 60.78431372549019,\n",
       " 61.03896103896104,\n",
       " 61.29032258064516,\n",
       " 61.53846153846154,\n",
       " 61.78343949044586,\n",
       " 62.0253164556962,\n",
       " 62.264150943396224,\n",
       " 62.5,\n",
       " 62.732919254658384,\n",
       " 62.96296296296296,\n",
       " 63.190184049079754,\n",
       " 62.80487804878049,\n",
       " 63.03030303030303,\n",
       " 63.25301204819277,\n",
       " 62.874251497005986,\n",
       " 63.095238095238095,\n",
       " 63.31360946745562,\n",
       " 63.529411764705884,\n",
       " 63.74269005847953,\n",
       " 63.95348837209303,\n",
       " 64.16184971098266,\n",
       " 64.36781609195403,\n",
       " 64.0,\n",
       " 63.63636363636363,\n",
       " 63.27683615819209,\n",
       " 63.48314606741573,\n",
       " 63.687150837988824,\n",
       " 63.888888888888886,\n",
       " 64.08839779005525,\n",
       " 63.73626373626374,\n",
       " 63.9344262295082,\n",
       " 63.58695652173913,\n",
       " 63.78378378378378,\n",
       " 63.97849462365591,\n",
       " 63.63636363636363,\n",
       " 63.829787234042556,\n",
       " 64.02116402116403,\n",
       " 63.68421052631579,\n",
       " 63.87434554973822,\n",
       " 64.0625,\n",
       " 63.73056994818653,\n",
       " 63.91752577319588,\n",
       " 64.1025641025641,\n",
       " 64.28571428571429,\n",
       " 63.95939086294416,\n",
       " 63.63636363636363,\n",
       " 63.81909547738694,\n",
       " 64.0,\n",
       " 64.17910447761194,\n",
       " 64.35643564356435,\n",
       " 64.5320197044335,\n",
       " 64.2156862745098,\n",
       " 63.90243902439025,\n",
       " 63.592233009708735,\n",
       " 63.768115942028984,\n",
       " 63.94230769230769,\n",
       " 64.11483253588517,\n",
       " 64.28571428571429,\n",
       " 63.981042654028435,\n",
       " 64.15094339622641,\n",
       " 64.31924882629107,\n",
       " 64.48598130841121,\n",
       " 64.65116279069767,\n",
       " 64.35185185185185,\n",
       " 64.51612903225806,\n",
       " 64.22018348623853,\n",
       " 63.926940639269404,\n",
       " 64.0909090909091,\n",
       " 63.800904977375566,\n",
       " 63.96396396396396,\n",
       " 64.12556053811659,\n",
       " 64.28571428571429,\n",
       " 64.44444444444444,\n",
       " 64.60176991150442,\n",
       " 64.31718061674009,\n",
       " 64.47368421052632,\n",
       " 64.62882096069869,\n",
       " 64.78260869565217,\n",
       " 64.93506493506493,\n",
       " 65.08620689655173,\n",
       " 65.23605150214593,\n",
       " 65.38461538461539,\n",
       " 65.1063829787234,\n",
       " 65.2542372881356,\n",
       " 65.40084388185655,\n",
       " 65.54621848739495,\n",
       " 65.69037656903765,\n",
       " 65.83333333333333,\n",
       " 65.97510373443983,\n",
       " 66.11570247933884,\n",
       " 66.2551440329218,\n",
       " 66.39344262295081,\n",
       " 66.53061224489795,\n",
       " 66.66666666666667,\n",
       " 66.80161943319838,\n",
       " 66.93548387096774,\n",
       " 67.06827309236948,\n",
       " 66.8,\n",
       " 66.93227091633466,\n",
       " 67.06349206349206,\n",
       " 67.19367588932806,\n",
       " 67.32283464566929,\n",
       " 67.05882352941177,\n",
       " 67.1875,\n",
       " 67.31517509727627,\n",
       " 67.44186046511628,\n",
       " 67.56756756756756,\n",
       " 67.6923076923077,\n",
       " 67.43295019157088,\n",
       " 67.55725190839695,\n",
       " 67.30038022813689,\n",
       " 67.42424242424242,\n",
       " 67.54716981132076,\n",
       " 67.66917293233082,\n",
       " 67.79026217228464,\n",
       " 67.91044776119404,\n",
       " 68.02973977695167,\n",
       " 68.14814814814815,\n",
       " 68.26568265682657,\n",
       " 68.38235294117646,\n",
       " 68.4981684981685,\n",
       " 68.61313868613139,\n",
       " 68.36363636363636,\n",
       " 68.47826086956522,\n",
       " 68.59205776173285,\n",
       " 68.70503597122303,\n",
       " 68.81720430107526,\n",
       " 68.57142857142857,\n",
       " 68.32740213523131,\n",
       " 68.43971631205673,\n",
       " 68.55123674911661,\n",
       " 68.66197183098592,\n",
       " 68.7719298245614,\n",
       " 68.53146853146853,\n",
       " 68.6411149825784,\n",
       " 68.75,\n",
       " 68.5121107266436,\n",
       " 68.62068965517241,\n",
       " 68.72852233676976,\n",
       " 68.83561643835617,\n",
       " 68.9419795221843,\n",
       " 68.70748299319727,\n",
       " 68.8135593220339,\n",
       " 68.58108108108108,\n",
       " 68.68686868686869,\n",
       " 68.79194630872483,\n",
       " 68.56187290969899,\n",
       " 68.66666666666667,\n",
       " 68.77076411960132,\n",
       " 68.87417218543047,\n",
       " 68.97689768976898,\n",
       " 68.75,\n",
       " 68.52459016393442,\n",
       " 68.62745098039215,\n",
       " 68.72964169381108,\n",
       " 68.83116883116882,\n",
       " 68.93203883495146,\n",
       " 68.70967741935483,\n",
       " 68.81028938906752,\n",
       " 68.58974358974359,\n",
       " 68.69009584664536,\n",
       " 68.78980891719745,\n",
       " 68.88888888888889,\n",
       " 68.9873417721519,\n",
       " 69.08517350157729,\n",
       " 69.18238993710692,\n",
       " 69.27899686520377,\n",
       " 69.375,\n",
       " 69.47040498442368,\n",
       " 69.56521739130434,\n",
       " 69.6594427244582,\n",
       " 69.75308641975309,\n",
       " 69.84615384615384,\n",
       " 69.93865030674847,\n",
       " 70.03058103975535,\n",
       " 69.8170731707317,\n",
       " 69.90881458966565,\n",
       " 69.6969696969697,\n",
       " 69.78851963746223,\n",
       " 69.87951807228916,\n",
       " 69.96996996996997,\n",
       " 70.05988023952096,\n",
       " 70.14925373134328,\n",
       " 70.23809523809524,\n",
       " 70.32640949554896,\n",
       " 70.41420118343196,\n",
       " 70.20648967551622,\n",
       " 70.29411764705883,\n",
       " 70.38123167155425,\n",
       " 70.46783625730994,\n",
       " 70.5539358600583,\n",
       " 70.63953488372093,\n",
       " 70.72463768115942,\n",
       " 70.8092485549133,\n",
       " 70.89337175792507,\n",
       " 70.97701149425288,\n",
       " 71.06017191977077,\n",
       " 70.85714285714286,\n",
       " 70.94017094017094,\n",
       " 71.02272727272727,\n",
       " 71.10481586402267,\n",
       " 70.90395480225989,\n",
       " 70.98591549295774,\n",
       " 70.78651685393258,\n",
       " 70.58823529411765,\n",
       " 70.67039106145252,\n",
       " 70.75208913649026,\n",
       " 70.83333333333333,\n",
       " 70.6371191135734,\n",
       " 70.7182320441989,\n",
       " 70.79889807162535,\n",
       " 70.6043956043956,\n",
       " 70.68493150684931,\n",
       " 70.49180327868852,\n",
       " 70.57220708446866,\n",
       " 70.65217391304348,\n",
       " 70.73170731707317,\n",
       " 70.8108108108108,\n",
       " 70.88948787061994,\n",
       " 70.96774193548387,\n",
       " 71.0455764075067,\n",
       " 71.12299465240642,\n",
       " 71.2,\n",
       " 71.01063829787235,\n",
       " 71.08753315649868,\n",
       " 71.16402116402116,\n",
       " 71.2401055408971,\n",
       " 71.3157894736842,\n",
       " 71.39107611548556,\n",
       " 71.20418848167539,\n",
       " 71.27937336814621,\n",
       " 71.35416666666667,\n",
       " 71.42857142857143,\n",
       " 71.50259067357513,\n",
       " 71.57622739018088,\n",
       " 71.64948453608247,\n",
       " 71.72236503856041,\n",
       " 71.7948717948718,\n",
       " 71.86700767263427,\n",
       " 71.93877551020408,\n",
       " 72.01017811704834,\n",
       " 72.08121827411168,\n",
       " 72.15189873417721,\n",
       " 72.22222222222223,\n",
       " 72.29219143576826,\n",
       " 72.36180904522612,\n",
       " 72.43107769423558,\n",
       " 72.5,\n",
       " 72.56857855361596,\n",
       " 72.636815920398,\n",
       " 72.70471464019852,\n",
       " 72.77227722772277,\n",
       " 72.8395061728395,\n",
       " 72.9064039408867,\n",
       " 72.97297297297297,\n",
       " 73.03921568627452,\n",
       " 72.86063569682152,\n",
       " 72.92682926829268,\n",
       " 72.99270072992701,\n",
       " 73.05825242718447,\n",
       " 73.12348668280872,\n",
       " 73.18840579710145,\n",
       " 73.25301204819277,\n",
       " 73.3173076923077,\n",
       " 73.38129496402878,\n",
       " 73.44497607655502,\n",
       " 73.50835322195704,\n",
       " 73.57142857142857,\n",
       " 73.63420427553444,\n",
       " 73.69668246445498,\n",
       " 73.75886524822695,\n",
       " 73.58490566037736,\n",
       " 73.6470588235294,\n",
       " 73.47417840375587,\n",
       " 73.53629976580797,\n",
       " 73.3644859813084,\n",
       " 73.42657342657343,\n",
       " 73.48837209302326,\n",
       " 73.54988399071925,\n",
       " 73.61111111111111,\n",
       " 73.67205542725173,\n",
       " 73.73271889400921,\n",
       " 73.79310344827586,\n",
       " 73.85321100917432,\n",
       " 73.91304347826087,\n",
       " 73.97260273972603,\n",
       " 74.03189066059225,\n",
       " 74.0909090909091,\n",
       " 74.14965986394557,\n",
       " 74.2081447963801,\n",
       " 74.04063205417607,\n",
       " 74.09909909909909,\n",
       " 74.15730337078652,\n",
       " 74.2152466367713,\n",
       " 74.27293064876957,\n",
       " 74.33035714285714,\n",
       " 74.38752783964365,\n",
       " 74.44444444444444,\n",
       " 74.50110864745011,\n",
       " 74.5575221238938,\n",
       " 74.61368653421634,\n",
       " 74.66960352422907,\n",
       " 74.72527472527473,\n",
       " 74.78070175438596,\n",
       " 74.83588621444201,\n",
       " 74.89082969432314,\n",
       " 74.94553376906318,\n",
       " 75.0,\n",
       " 75.05422993492408,\n",
       " 75.10822510822511,\n",
       " 75.16198704103672,\n",
       " 75.21551724137932,\n",
       " 75.26881720430107,\n",
       " 75.32188841201717,\n",
       " 75.37473233404711,\n",
       " 75.42735042735043,\n",
       " 75.47974413646055,\n",
       " 75.31914893617021,\n",
       " 75.37154989384288,\n",
       " 75.42372881355932,\n",
       " 75.47568710359408,\n",
       " 75.52742616033755,\n",
       " 75.57894736842105,\n",
       " 75.63025210084034,\n",
       " 75.68134171907757,\n",
       " 75.73221757322176,\n",
       " 75.78288100208768,\n",
       " 75.83333333333333,\n",
       " 75.67567567567568,\n",
       " 75.72614107883817,\n",
       " 75.77639751552795,\n",
       " 75.82644628099173,\n",
       " 75.87628865979381,\n",
       " 75.92592592592592,\n",
       " 75.97535934291581,\n",
       " 76.02459016393442,\n",
       " 76.07361963190183,\n",
       " 76.12244897959184,\n",
       " 76.17107942973523,\n",
       " 76.21951219512195,\n",
       " 76.26774847870182,\n",
       " 76.11336032388664,\n",
       " 76.16161616161617,\n",
       " 76.00806451612904,\n",
       " 76.05633802816901,\n",
       " 75.90361445783132,\n",
       " 75.95190380761522,\n",
       " 76.0,\n",
       " 76.04790419161677,\n",
       " 76.09561752988049,\n",
       " 76.14314115308152,\n",
       " 76.19047619047619,\n",
       " 76.23762376237623,\n",
       " 76.28458498023716,\n",
       " 76.33136094674556,\n",
       " 76.37795275590551,\n",
       " 76.42436149312377,\n",
       " 76.47058823529412,\n",
       " 76.51663405088063,\n",
       " 76.5625,\n",
       " 76.60818713450293,\n",
       " 76.65369649805447,\n",
       " 76.69902912621359,\n",
       " 76.74418604651163,\n",
       " 76.78916827852998,\n",
       " 76.64092664092664,\n",
       " 76.6859344894027,\n",
       " 76.73076923076923,\n",
       " 76.77543186180422,\n",
       " 76.8199233716475,\n",
       " 76.8642447418738,\n",
       " 76.90839694656489,\n",
       " 76.95238095238095,\n",
       " 76.99619771863118,\n",
       " 77.03984819734346,\n",
       " 77.08333333333333,\n",
       " 76.93761814744802,\n",
       " 76.98113207547169,\n",
       " 77.02448210922788,\n",
       " 77.06766917293233,\n",
       " 77.11069418386492,\n",
       " 77.15355805243446,\n",
       " 77.19626168224299,\n",
       " 77.23880597014926,\n",
       " 77.28119180633148,\n",
       " 77.32342007434944,\n",
       " 77.1799628942486,\n",
       " 77.22222222222223,\n",
       " 77.07948243992607,\n",
       " 77.12177121771218,\n",
       " 77.16390423572744,\n",
       " 77.20588235294117,\n",
       " 77.24770642201835,\n",
       " 77.28937728937728,\n",
       " 77.3308957952468,\n",
       " 77.37226277372262,\n",
       " 77.41347905282332,\n",
       " 77.27272727272727,\n",
       " 77.31397459165154,\n",
       " 77.35507246376811,\n",
       " 77.39602169981917,\n",
       " 77.25631768953069,\n",
       " 77.29729729729729,\n",
       " 77.33812949640287,\n",
       " 77.37881508078995,\n",
       " 77.24014336917563,\n",
       " 77.28085867620752,\n",
       " 77.32142857142857,\n",
       " 77.36185383244207,\n",
       " 77.40213523131672,\n",
       " 77.44227353463587,\n",
       " 77.48226950354609,\n",
       " 77.52212389380531,\n",
       " 77.56183745583039,\n",
       " 77.60141093474427,\n",
       " 77.64084507042253,\n",
       " 77.68014059753955,\n",
       " 77.71929824561404,\n",
       " 77.75831873905429,\n",
       " 77.7972027972028,\n",
       " 77.83595113438045,\n",
       " 77.87456445993031,\n",
       " 77.91304347826087,\n",
       " 77.95138888888889,\n",
       " 77.98960138648181,\n",
       " 78.02768166089966,\n",
       " 78.06563039723662,\n",
       " 78.10344827586206,\n",
       " 78.14113597246127,\n",
       " 78.1786941580756,\n",
       " 78.21612349914237,\n",
       " 78.25342465753425,\n",
       " 78.2905982905983,\n",
       " 78.32764505119454,\n",
       " 78.36456558773425,\n",
       " 78.40136054421768,\n",
       " 78.43803056027164,\n",
       " 78.47457627118644,\n",
       " 78.51099830795262,\n",
       " 78.54729729729729,\n",
       " 78.58347386172007,\n",
       " 78.61952861952862,\n",
       " 78.65546218487395,\n",
       " 78.69127516778524,\n",
       " 78.72696817420436,\n",
       " 78.76254180602007,\n",
       " 78.79799666110183,\n",
       " 78.83333333333333,\n",
       " 78.70216306156406,\n",
       " 78.7375415282392,\n",
       " 78.77280265339967,\n",
       " 78.80794701986756,\n",
       " 78.67768595041322,\n",
       " 78.7128712871287,\n",
       " 78.74794069192751,\n",
       " 78.78289473684211,\n",
       " 78.81773399014779,\n",
       " 78.85245901639344,\n",
       " 78.88707037643208,\n",
       " 78.92156862745098,\n",
       " 78.95595432300163,\n",
       " 78.99022801302931,\n",
       " 79.02439024390245,\n",
       " 79.05844155844156,\n",
       " 79.09238249594813,\n",
       " 79.12621359223301,\n",
       " 79.1599353796446,\n",
       " 79.19354838709677,\n",
       " 79.22705314009661,\n",
       " 79.09967845659163,\n",
       " 79.13322632423755,\n",
       " 79.16666666666667,\n",
       " 79.2,\n",
       " 79.2332268370607,\n",
       " 79.26634768740031,\n",
       " 79.29936305732484,\n",
       " 79.3322734499205,\n",
       " 79.36507936507937,\n",
       " 79.39778129952457,\n",
       " 79.43037974683544,\n",
       " 79.46287519747236,\n",
       " 79.49526813880126,\n",
       " 79.5275590551181,\n",
       " 79.55974842767296,\n",
       " 79.59183673469387,\n",
       " 79.62382445141066,\n",
       " 79.65571205007825,\n",
       " 79.6875,\n",
       " 79.7191887675507,\n",
       " 79.75077881619937,\n",
       " 79.78227060653188,\n",
       " 79.8136645962733,\n",
       " 79.68992248062015,\n",
       " 79.72136222910217,\n",
       " 79.75270479134467,\n",
       " 79.78395061728395,\n",
       " 79.81510015408321,\n",
       " 79.84615384615384,\n",
       " 79.87711213517665,\n",
       " 79.9079754601227,\n",
       " 79.93874425727412,\n",
       " 79.81651376146789,\n",
       " 79.8473282442748,\n",
       " 79.8780487804878,\n",
       " 79.90867579908675,\n",
       " 79.93920972644376,\n",
       " 79.96965098634294,\n",
       " 80.0,\n",
       " 80.0302571860817,\n",
       " 80.06042296072508,\n",
       " 80.09049773755656,\n",
       " 80.12048192771084,\n",
       " 80.15037593984962,\n",
       " 80.03003003003003,\n",
       " 80.0599700149925,\n",
       " 80.08982035928143,\n",
       " 80.11958146487295,\n",
       " 80.14925373134328,\n",
       " 80.17883755588673,\n",
       " 80.20833333333333,\n",
       " 80.23774145616642,\n",
       " 80.26706231454006,\n",
       " 80.29629629629629,\n",
       " 80.32544378698225,\n",
       " 80.35450516986707,\n",
       " 80.3834808259587,\n",
       " 80.41237113402062,\n",
       " 80.44117647058823,\n",
       " 80.46989720998532,\n",
       " 80.49853372434018,\n",
       " 80.52708638360176,\n",
       " 80.55555555555556,\n",
       " 80.58394160583941,\n",
       " 80.61224489795919,\n",
       " 80.64046579330422,\n",
       " 80.6686046511628,\n",
       " 80.6966618287373,\n",
       " 80.72463768115942,\n",
       " 80.75253256150506,\n",
       " 80.78034682080924,\n",
       " 80.8080808080808,\n",
       " 80.835734870317,\n",
       " 80.86330935251799,\n",
       " 80.74712643678161,\n",
       " 80.77474892395983,\n",
       " 80.80229226361031,\n",
       " 80.82975679542203,\n",
       " 80.85714285714286,\n",
       " 80.88445078459344,\n",
       " 80.91168091168092,\n",
       " 80.93883357041251,\n",
       " 80.9659090909091,\n",
       " 80.99290780141844,\n",
       " 81.01983002832861,\n",
       " 81.04667609618105,\n",
       " 81.07344632768361,\n",
       " 81.10014104372355,\n",
       " 81.12676056338029,\n",
       " 81.15330520393812,\n",
       " 81.17977528089888,\n",
       " 81.2061711079944,\n",
       " 81.23249299719888,\n",
       " 81.25874125874125,\n",
       " 81.28491620111731,\n",
       " 81.31101813110182,\n",
       " 81.33704735376044,\n",
       " 81.36300417246176,\n",
       " 81.38888888888889,\n",
       " 81.41470180305132,\n",
       " 81.4404432132964,\n",
       " 81.46611341632088,\n",
       " 81.49171270718232,\n",
       " 81.51724137931035,\n",
       " 81.5426997245179,\n",
       " 81.56808803301237,\n",
       " 81.5934065934066,\n",
       " 81.61865569272976,\n",
       " 81.64383561643835,\n",
       " 81.66894664842681,\n",
       " 81.69398907103825,\n",
       " 81.71896316507504,\n",
       " 81.74386920980926,\n",
       " 81.7687074829932,\n",
       " 81.79347826086956,\n",
       " 81.81818181818181,\n",
       " 81.84281842818429,\n",
       " 81.86738836265224,\n",
       " 81.89189189189189,\n",
       " 81.91632928475033,\n",
       " 81.94070080862534,\n",
       " 81.9650067294751,\n",
       " 81.85483870967742,\n",
       " 81.87919463087249,\n",
       " 81.90348525469169,\n",
       " 81.79384203480589,\n",
       " 81.81818181818181,\n",
       " 81.84245660881174,\n",
       " 81.86666666666666,\n",
       " 81.89081225033289,\n",
       " 81.91489361702128,\n",
       " 81.93891102257636,\n",
       " 81.96286472148542,\n",
       " 81.98675496688742,\n",
       " 82.01058201058201,\n",
       " 82.0343461030383,\n",
       " 82.05804749340369,\n",
       " 82.08168642951252,\n",
       " 82.10526315789474,\n",
       " 82.1287779237845,\n",
       " 82.1522309711286,\n",
       " 82.17562254259502,\n",
       " 82.19895287958116,\n",
       " 82.22222222222223,\n",
       " 82.24543080939948,\n",
       " 82.26857887874837,\n",
       " 82.29166666666667,\n",
       " 82.3146944083225,\n",
       " 82.33766233766234,\n",
       " 82.23086900129702,\n",
       " 82.25388601036269,\n",
       " 82.27684346701164,\n",
       " 82.29974160206719,\n",
       " 82.3225806451613,\n",
       " 82.34536082474227,\n",
       " 82.36808236808237,\n",
       " 82.39074550128535,\n",
       " 82.41335044929397,\n",
       " 82.43589743589743,\n",
       " 82.4583866837388,\n",
       " 82.48081841432226,\n",
       " 82.50319284802043,\n",
       " 82.52551020408163,\n",
       " 82.54777070063695,\n",
       " 82.56997455470739,\n",
       " 82.59212198221093,\n",
       " 82.61421319796955,\n",
       " 82.6362484157161,\n",
       " 82.65822784810126,\n",
       " 82.68015170670039,\n",
       " 82.70202020202021,\n",
       " 82.72383354350568,\n",
       " 82.7455919395466,\n",
       " 82.76729559748428,\n",
       " 82.78894472361809,\n",
       " 82.81053952321204,\n",
       " 82.83208020050125,\n",
       " 82.85356695869838,\n",
       " 82.875,\n",
       " 82.896379525593,\n",
       " 82.91770573566085,\n",
       " 82.93897882938978,\n",
       " 82.96019900497512,\n",
       " 82.98136645962732,\n",
       " 83.00248138957816,\n",
       " 83.02354399008674,\n",
       " 83.04455445544555,\n",
       " 83.0655129789864,\n",
       " 83.08641975308642,\n",
       " 83.10727496917386,\n",
       " 83.12807881773399,\n",
       " 83.14883148831488,\n",
       " 83.16953316953317,\n",
       " 83.19018404907976,\n",
       " 83.21078431372548,\n",
       " 83.2313341493268,\n",
       " 83.2518337408313,\n",
       " 83.27228327228327,\n",
       " 83.29268292682927,\n",
       " 83.3130328867235,\n",
       " 83.33333333333333,\n",
       " 83.3535844471446,\n",
       " 83.37378640776699,\n",
       " 83.39393939393939,\n",
       " 83.4140435835351,\n",
       " 83.4340991535671,\n",
       " 83.45410628019323,\n",
       " 83.47406513872136,\n",
       " 83.49397590361446,\n",
       " 83.51383874849579,\n",
       " 83.53365384615384,\n",
       " 83.55342136854742,\n",
       " 83.57314148681056,\n",
       " 83.59281437125749,\n",
       " 83.61244019138756,\n",
       " 83.63201911589009,\n",
       " 83.65155131264916,\n",
       " 83.67103694874851,\n",
       " 83.69047619047619,\n",
       " 83.70986920332938,\n",
       " 83.729216152019,\n",
       " 83.7485172004745,\n",
       " 83.76777251184834,\n",
       " 83.78698224852072,\n",
       " 83.80614657210401,\n",
       " 83.82526564344747,\n",
       " 83.84433962264151,\n",
       " 83.86336866902238,\n",
       " 83.88235294117646,\n",
       " 83.90129259694477,\n",
       " 83.92018779342723,\n",
       " 83.9390386869871,\n",
       " 83.95784543325527,\n",
       " 83.9766081871345,\n",
       " 83.99532710280374,\n",
       " 84.01400233372229,\n",
       " 84.03263403263404,\n",
       " 84.0512223515716,\n",
       " 84.06976744186046,\n",
       " 84.08826945412311,\n",
       " 84.10672853828306,\n",
       " 84.12514484356895,\n",
       " 84.14351851851852,\n",
       " 84.16184971098266,\n",
       " 84.18013856812934,\n",
       " 84.19838523644752,\n",
       " 84.21658986175115,\n",
       " 84.23475258918297,\n",
       " 84.25287356321839,\n",
       " 84.27095292766934,\n",
       " 84.28899082568807,\n",
       " 84.3069873997709,\n",
       " 84.32494279176201,\n",
       " 84.22857142857143,\n",
       " 84.24657534246575,\n",
       " 84.26453819840364,\n",
       " 84.28246013667426,\n",
       " 84.30034129692832,\n",
       " 84.31818181818181,\n",
       " 84.33598183881952,\n",
       " 84.35374149659864,\n",
       " 84.37146092865233,\n",
       " 84.38914027149322,\n",
       " 84.40677966101696,\n",
       " 84.42437923250564,\n",
       " 84.44193912063135,\n",
       " 84.45945945945945,\n",
       " 84.4769403824522,\n",
       " 84.49438202247191,\n",
       " 84.51178451178451,\n",
       " 84.52914798206278,\n",
       " 84.5464725643897,\n",
       " 84.56375838926175,\n",
       " 84.58100558659218,\n",
       " 84.59821428571429,\n",
       " 84.61538461538461,\n",
       " 84.6325167037862,\n",
       " 84.6496106785317,\n",
       " 84.66666666666667,\n",
       " 84.68368479467259,\n",
       " 84.70066518847007,\n",
       " 84.71760797342192,\n",
       " 84.62389380530973,\n",
       " 84.64088397790056,\n",
       " 84.65783664459161,\n",
       " 84.6747519294377,\n",
       " 84.69162995594714,\n",
       " 84.70847084708471,\n",
       " 84.72527472527473,\n",
       " 84.74204171240395,\n",
       " 84.75877192982456,\n",
       " 84.77546549835706,\n",
       " 84.79212253829321,\n",
       " 84.80874316939891,\n",
       " 84.82532751091703,\n",
       " 84.84187568157034,\n",
       " 84.85838779956427,\n",
       " 84.87486398258977,\n",
       " 84.8913043478261,\n",
       " 84.90770901194354,\n",
       " 84.81561822125813,\n",
       " 84.8320693391116,\n",
       " 84.84848484848484,\n",
       " 84.86486486486487,\n",
       " 84.88120950323975,\n",
       " 84.89751887810141,\n",
       " 84.91379310344827,\n",
       " 84.93003229278794,\n",
       " 84.94623655913979,\n",
       " 84.9624060150376,\n",
       " 84.97854077253218,\n",
       " 84.994640943194,\n",
       " 85.01070663811564,\n",
       " 85.02673796791444,\n",
       " 85.04273504273505,\n",
       " 85.05869797225186,\n",
       " 85.07462686567165,\n",
       " 85.09052183173588,\n",
       " 85.1063829787234,\n",
       " 85.12221041445271,\n",
       " 85.1380042462845,\n",
       " 85.15376458112407,\n",
       " 85.16949152542372,\n",
       " 85.18518518518519,\n",
       " 85.20084566596195,\n",
       " 85.21647307286167,\n",
       " 85.23206751054852,\n",
       " 85.24762908324553,\n",
       " 85.26315789473684,\n",
       " 85.27865404837014,\n",
       " 85.29411764705883,\n",
       " 85.30954879328436,\n",
       " 85.32494758909853,\n",
       " 85.34031413612566,\n",
       " 85.35564853556485,\n",
       " 85.37095088819227,\n",
       " 85.38622129436325,\n",
       " 85.4014598540146,\n",
       " 85.41666666666667,\n",
       " 85.4318418314256,\n",
       " 85.44698544698545,\n",
       " 85.46209761163033,\n",
       " 85.47717842323651,\n",
       " 85.49222797927462,\n",
       " 85.5072463768116,\n",
       " 85.52223371251293,\n",
       " 85.53719008264463,\n",
       " 85.55211558307533,\n",
       " 85.56701030927834,\n",
       " 85.58187435633367,\n",
       " 85.59670781893004,\n",
       " 85.61151079136691,\n",
       " 85.62628336755647,\n",
       " 85.64102564102564,\n",
       " 85.65573770491804,\n",
       " 85.56806550665301,\n",
       " 85.58282208588957,\n",
       " 85.59754851889683,\n",
       " 85.61224489795919,\n",
       " 85.62691131498471,\n",
       " 85.64154786150714,\n",
       " 85.65615462868769,\n",
       " 85.67073170731707,\n",
       " 85.68527918781726,\n",
       " 85.6997971602434,\n",
       " 85.71428571428571,\n",
       " 85.72874493927125,\n",
       " 85.64206268958544,\n",
       " 85.65656565656566,\n",
       " 85.67103935418768,\n",
       " 85.68548387096774,\n",
       " 85.69989929506546,\n",
       " 85.71428571428571,\n",
       " 85.7286432160804,\n",
       " 85.7429718875502,\n",
       " 85.75727181544634,\n",
       " 85.77154308617234,\n",
       " 85.78578578578579,\n",
       " 85.8,\n",
       " ...]"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def entrainementIAvAleatoire(nbParties,taille,play=False) :\n",
    "    \"\"\"\n",
    "    fonction d'entrainement d'une IA contre l'aléatoire\n",
    "    Prend en paramètre nbParties : le nombre de parties à réaliser, et taille : la taille du tas de départ\n",
    "    Option play permet de jouer contre l'IA à la fin de l'entrainement si True\n",
    "    Renvoi le tableau des taux de victoire\n",
    "    \"\"\"\n",
    "    tauVictoire=[]\n",
    "    victoire=0\n",
    "    strat = {}\n",
    "    stratInit([taille],strat,5)\n",
    "    strat.pop('')\n",
    "    aleatoire=strat.copy()\n",
    "    for i in range(nbParties):\n",
    "        rec=IAvIA(taille,strat,aleatoire)\n",
    "        apprend(rec[:2],strat)\n",
    "        if rec[1]==True:\n",
    "            victoire+=1\n",
    "        tauVictoire.append(victoire*100/(i+1))\n",
    "    if play : JvAI(taille,strat)\n",
    "    print(strat)\n",
    "    return tauVictoire\n",
    "\n",
    "# Example usage:\n",
    "entrainementIAvAleatoire(10_000,12)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### g - Entrainement ordi contre lui meme"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sur le même principe, on peut également entrainer une stratégie contre elle même ce qui risque cependant de créer un effet boule de bords puisqu'elle risque de condenser des faiblesses mais aussi ses points forts. Il n'y as pas de regard exterieur de remise en question en quelque sorte ce qui peut mener à des absurdités, à mon avis ce n'est pas une très bonne idée."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'12': {'0,1': 3, '0,2': 4768, '0,3': 4914, '0,4': 3, '0,5': 2}, '11': {'0,1': 9, '0,2': 4, '0,3': 4, '0,4': 7, '0,5': 5}, '10': {'0,1': 1, '0,2': 1, '0,3': 1, '0,4': 1}, '9': {'0,1': 1, '0,2': 1159, '0,3': 1035, '0,4': 1}, '8': {'0,1': 1186, '0,2': 1, '0,3': 1}, '7': {'0,1': 1, '0,2': 1, '0,3': 1}, '6': {'0,1': 1, '0,2': 2071}, '5': {'0,1': 1041, '0,2': 1}, '4': {'0,1': 1}, '3': {'0,1': 10005}, '3,4': {'0,1': 2480, '1,1': 2421}, '3,3': {'0,1': 1, '1,1': 1}, '3,5': {'0,1': 1, '1,1': 1, '1,2': 1098}, '3,6': {'0,1': 1, '1,1': 1, '1,2': 1}, '4,5': {'0,1': 1, '1,1': 47, '1,2': 1}, '4,4': {'0,1': 1, '1,1': 1}, '3,7': {'0,1': 804, '1,1': 422, '1,2': 1, '1,3': 1053}, '3,3,4': {'0,1': 1, '1,1': 1, '2,1': 1}, '3,3,3': {'0,1': 313, '1,1': 412, '2,1': 195}, '4,6': {'0,1': 287, '1,1': 1, '1,2': 939}, '3,8': {'0,1': 1, '1,1': 1, '1,2': 951, '1,3': 1}, '3,3,5': {'0,1': 2, '1,1': 3, '2,1': 33, '2,2': 1}, '4,7': {'0,1': 1, '1,1': 1, '1,2': 2, '1,3': 2}, '3,4,4': {'0,1': 8, '1,1': 9, '2,1': 11}, '5,6': {'0,1': 3, '0,2': 6, '1,1': 10, '1,2': 4}, '5,5': {'0,1': 3, '0,2': 3, '1,1': 3, '1,2': 3}, '3,9': {'0,1': 1, '1,1': 1, '1,2': 1, '1,3': 1, '1,4': 1}, '3,3,6': {'0,1': 101, '1,1': 289, '2,1': 1, '2,2': 637}, '3,4,5': {'0,1': 1, '1,1': 1, '2,1': 1, '2,2': 1009}, '4,8': {'0,1': 6, '1,1': 11, '1,2': 4, '1,3': 6}, '5,7': {'0,1': 14, '0,2': 1, '1,1': 2, '1,2': 8, '1,3': 6}}\n"
     ]
    }
   ],
   "source": [
    "def entrainementIA(nbParties,taille,play=False) :\n",
    "    \"\"\"\n",
    "    fonction d'entrainement d'une IA contre elle même\n",
    "    Prend en paramètre nbParties : le nombre de parties à réaliser, et taille : la taille du tas de départ\n",
    "    Option play permet de jouer contre l'IA à la fin de l'entrainement\n",
    "    \"\"\"\n",
    "    strat = {}\n",
    "    stratInit([taille],strat,5)\n",
    "    strat.pop('')\n",
    "    for i in range(nbParties):\n",
    "        rec=IAvIA(taille,strat,strat)\n",
    "        rec2=[rec[2],not rec[1]]\n",
    "        apprend(rec[:2],strat)\n",
    "        apprend(rec2,strat)\n",
    "    if play : JvAI(taille,strat)\n",
    "    print(strat)\n",
    "\n",
    "# Example usage:\n",
    "entrainementIA(10_000,12)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### h - entrainement ordi contre un autre ordi"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Toujours sur le même principe cette fois ci on entraine deux IA distinctes entre elles. Cette option réduits les risques d'effets de bords liés à la précédentes méthode et va mener a une stratégie plus élitiste et moins diversifié qu'avec l'aléatoire. Les parties risque de toutes se ressemblées a mesure que l'entrainement avance."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "IA 1 :  {'12': {'0,1': 2, '0,2': 7725, '0,3': 1914, '0,4': 1, '0,5': 2}, '11': {'0,1': 9, '0,2': 2, '0,3': 2, '0,4': 14, '0,5': 3}, '10': {'0,1': 1, '0,2': 1, '0,3': 1, '0,4': 1}, '9': {'0,1': 1, '0,2': 1321, '0,3': 1048, '0,4': 1}, '8': {'0,1': 2022, '0,2': 1, '0,3': 1}, '7': {'0,1': 1, '0,2': 1, '0,3': 1}, '6': {'0,1': 1, '0,2': 2271}, '5': {'0,1': 1355, '0,2': 1}, '4': {'0,1': 1}, '3': {'0,1': 10005}, '3,4': {'0,1': 2176, '1,1': 2722}, '3,3': {'0,1': 1, '1,1': 1}, '3,5': {'0,1': 1, '1,1': 1, '1,2': 986}, '3,6': {'0,1': 1, '1,1': 1, '1,2': 1}, '4,5': {'0,1': 1, '1,1': 52, '1,2': 1}, '4,4': {'0,1': 1, '1,1': 1}, '3,7': {'0,1': 591, '1,1': 713, '1,2': 1, '1,3': 1020}, '3,3,4': {'0,1': 1, '1,1': 1, '2,1': 1}, '3,3,3': {'0,1': 182, '1,1': 153, '2,1': 186}, '4,6': {'0,1': 507, '1,1': 1, '1,2': 1453}, '3,8': {'0,1': 1, '1,1': 1, '1,2': 413, '1,3': 1}, '3,3,5': {'0,1': 1, '1,1': 2, '2,1': 31, '2,2': 1}, '4,7': {'0,1': 1, '1,1': 1, '1,2': 1, '1,3': 1}, '3,4,4': {'0,1': 17, '1,1': 7, '2,1': 8}, '5,6': {'0,1': 5, '0,2': 8, '1,1': 6, '1,2': 4}, '5,5': {'0,1': 3, '0,2': 4, '1,1': 5, '1,2': 3}, '3,9': {'0,1': 1, '1,1': 1, '1,2': 1, '1,3': 1, '1,4': 1}, '3,3,6': {'0,1': 116, '1,1': 83, '2,1': 4, '2,2': 175}, '3,4,5': {'0,1': 1, '1,1': 2, '2,1': 1, '2,2': 386}, '4,8': {'0,1': 1, '1,1': 32, '1,2': 1, '1,3': 1}, '5,7': {'0,1': 11, '0,2': 3, '1,1': 4, '1,2': 9, '1,3': 3}} \n",
      "\n",
      "IA 2 :  {'12': {'0,1': 2, '0,2': 7725, '0,3': 1914, '0,4': 1, '0,5': 2}, '11': {'0,1': 9, '0,2': 2, '0,3': 2, '0,4': 14, '0,5': 3}, '10': {'0,1': 1, '0,2': 1, '0,3': 1, '0,4': 1}, '9': {'0,1': 1, '0,2': 1321, '0,3': 1048, '0,4': 1}, '8': {'0,1': 2022, '0,2': 1, '0,3': 1}, '7': {'0,1': 1, '0,2': 1, '0,3': 1}, '6': {'0,1': 1, '0,2': 2271}, '5': {'0,1': 1355, '0,2': 1}, '4': {'0,1': 1}, '3': {'0,1': 10005}, '3,4': {'0,1': 2176, '1,1': 2722}, '3,3': {'0,1': 1, '1,1': 1}, '3,5': {'0,1': 1, '1,1': 1, '1,2': 986}, '3,6': {'0,1': 1, '1,1': 1, '1,2': 1}, '4,5': {'0,1': 1, '1,1': 52, '1,2': 1}, '4,4': {'0,1': 1, '1,1': 1}, '3,7': {'0,1': 591, '1,1': 713, '1,2': 1, '1,3': 1020}, '3,3,4': {'0,1': 1, '1,1': 1, '2,1': 1}, '3,3,3': {'0,1': 182, '1,1': 153, '2,1': 186}, '4,6': {'0,1': 507, '1,1': 1, '1,2': 1453}, '3,8': {'0,1': 1, '1,1': 1, '1,2': 413, '1,3': 1}, '3,3,5': {'0,1': 1, '1,1': 2, '2,1': 31, '2,2': 1}, '4,7': {'0,1': 1, '1,1': 1, '1,2': 1, '1,3': 1}, '3,4,4': {'0,1': 17, '1,1': 7, '2,1': 8}, '5,6': {'0,1': 5, '0,2': 8, '1,1': 6, '1,2': 4}, '5,5': {'0,1': 3, '0,2': 4, '1,1': 5, '1,2': 3}, '3,9': {'0,1': 1, '1,1': 1, '1,2': 1, '1,3': 1, '1,4': 1}, '3,3,6': {'0,1': 116, '1,1': 83, '2,1': 4, '2,2': 175}, '3,4,5': {'0,1': 1, '1,1': 2, '2,1': 1, '2,2': 386}, '4,8': {'0,1': 1, '1,1': 32, '1,2': 1, '1,3': 1}, '5,7': {'0,1': 11, '0,2': 3, '1,1': 4, '1,2': 9, '1,3': 3}}\n"
     ]
    }
   ],
   "source": [
    "def entrainementIAvIA(nbParties,taille,play=False) :\n",
    "    \"\"\"\n",
    "    fonction d'entrainement d'une IA contre une autre IA\n",
    "    Prend en paramètre nbParties : le nombre de parties à réaliser, et taille : la taille du tas de départ\n",
    "    Option play permet de jouer contre l'IA à la fin de l'entrainement\n",
    "    \"\"\"\n",
    "    strat1 = {}\n",
    "    stratInit([taille],strat1,5)\n",
    "    strat1.pop('')\n",
    "    strat2=strat1.copy()\n",
    "    for i in range(nbParties):\n",
    "        rec=IAvIA(taille,strat1,strat2)\n",
    "        rec2=[rec[2], not rec[1]]\n",
    "        apprend(rec[:2],strat1)\n",
    "        apprend(rec2,strat2)\n",
    "    if play :JvAI(taille,strat1)\n",
    "    print(\"IA 1 : \",strat1,\"\\n\")\n",
    "    if play : JvAI(taille,strat2)\n",
    "    print(\"IA 2 : \",strat2)\n",
    "\n",
    "# Example usage:\n",
    "entrainementIAvIA(10_000,12)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5 - Graphique"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'12': {'0,1': 5, '0,2': 11973, '0,3': 36454, '0,4': 606, '0,5': 9}, '11': {'0,1': 5, '0,2': 5, '0,3': 5, '0,4': 5, '0,5': 5}, '10': {'0,1': 2, '0,2': 5, '0,3': 3, '0,4': 4}, '9': {'0,1': 1, '0,2': 6133, '0,3': 3513, '0,4': 1}, '8': {'0,1': 3636, '0,2': 1, '0,3': 1}, '7': {'0,1': 1, '0,2': 1, '0,3': 1}, '6': {'0,1': 1, '0,2': 11283}, '5': {'0,1': 4667, '0,2': 1}, '4': {'0,1': 1}, '3': {'0,1': 49515}, '3,4': {'0,1': 17252, '1,1': 4885}, '3,3': {'0,1': 1, '1,1': 1}, '3,5': {'0,1': 1, '1,1': 1, '1,2': 7200}, '3,6': {'0,1': 1, '1,1': 1, '1,2': 1}, '4,5': {'0,1': 5, '1,1': 10, '1,2': 3}, '4,4': {'0,1': 1, '1,1': 1}, '3,7': {'0,1': 4315, '1,1': 2912, '1,2': 1, '1,3': 3176}, '3,3,4': {'0,1': 1, '1,1': 1, '2,1': 1}, '3,3,3': {'0,1': 1709, '1,1': 726, '2,1': 1820}, '4,6': {'0,1': 1775, '1,1': 3, '1,2': 1410}, '3,8': {'0,1': 1, '1,1': 1, '1,2': 7338, '1,3': 87}, '3,3,5': {'0,1': 5, '1,1': 5, '2,1': 5, '2,2': 5}, '4,7': {'0,1': 1, '1,1': 1, '1,2': 17, '1,3': 1}, '3,4,4': {'0,1': 5, '1,1': 5, '2,1': 5}, '5,6': {'0,1': 2, '0,2': 7, '1,1': 13, '1,2': 4}, '5,5': {'0,1': 8, '0,2': 3, '1,1': 4, '1,2': 2}, '3,9': {'0,1': 5, '1,1': 5, '1,2': 5, '1,3': 5, '1,4': 5}, '3,3,6': {'0,1': 3320, '1,1': 2649, '2,1': 75, '2,2': 1338}, '3,4,5': {'0,1': 2, '1,1': 136, '2,1': 1, '2,2': 7422}, '4,8': {'0,1': 5, '1,1': 5, '1,2': 5, '1,3': 5}, '5,7': {'0,1': 5, '0,2': 5, '1,1': 5, '1,2': 5, '1,3': 5}}\n",
      "Après entrainement contre un environement jouant aléatoirement sur un jeu de taille initiale 12, l'ordinateur gagne \n",
      "--------------  99.02  % du temps\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA+0AAAPyCAYAAAAJxz5dAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAbMVJREFUeJzt3Xl4VOX9N+DvEJKwBhBlFRURFBHrjrhXUOq+vSpq61qtFluRWpdfRQUX1CputWo31Kp1qVtbV1xbFRERqQriUncFVISAIARy3j8oU0JYkpBkziT3fV25yJzzzJnPzDyJfnKWySRJkgQAAACQOk1yHQAAAABYOaUdAAAAUkppBwAAgJRS2gEAACCllHYAAABIKaUdAAAAUkppBwAAgJRS2gEAACCllHYAgHo0Z86cGDlyZPzrX//KdRQA8oDSDkCjk8lk4qKLLsp1DFLi+OOPj4022qhWtvXcc89FJpOJ5557bpVjTjrppHjsscdiu+22q5XHrInafM4A1C2lHYC1cuutt0Ymk1nl18svv1ztbT766KNKdR2466674tprr811jNX6/PPP46KLLorXX389pzkymUzceuuttb7d6667Lv7973/H3//+92jevHmNtjFlypS46KKL4sMPP6zdcACkUtNcBwCgYRg5cmR079690vJNNtmk2tt69NFH48Ybb6yz4r5gwYJo2rTx/SfwrrvuijfffDOGDh2a6yir9Pnnn8eIESNio402iq222irXcWrVokWL4ttvv43HH3881l133RpvZ8qUKTFixIjYY489ary3/Pe//32Ul5fXOAMA9afx/R8LAHVin332ycnhvosXL47y8vIoKiqq8n2aNWtWh4moT/Pnz48WLVrkOkaVFBUVxf/93//lOkZERBQWFq5xTE1+tgCofQ6PB6BefPjhh5HJZOKqq66K3/3ud9GjR48oLi6O7bffPiZMmJAdd/zxx8eNN94YEVHhMPsVt3HttddmtzFlypRYtGhRXHDBBbHttttGmzZtomXLlrHrrrvGs88+WynLiue0X3TRRZHJZOK9996L448/Ptq2bRtt2rSJE044IebPn1/p/nfccUdsu+220bx581hnnXVi8ODB8cknn1QYs8cee8QWW2wR//73v2P33XePFi1axCabbBJ//etfIyLi+eefj379+kXz5s1j0003jaeeeqrS43z22Wdx4oknRseOHaO4uDj69OkTf/rTnyqMWXYO9b333huXXnpprL/++tGsWbMYMGBAvPfeexXyPPLII/HRRx9lX9Oq7KW94447YocddogWLVpEu3btYrfddosnn3yywpjf/va30adPnyguLo4uXbrEkCFDYvbs2St9PaZMmRLf//73o0WLFtG1a9e48sorKzyX7bffPiIiTjjhhGzOZYepL9vGxIkTY7fddosWLVpkS/DChQvjwgsvjE022SSKi4ujW7ducfbZZ8fChQvX+Byr4qOPPoqf/vSnsemmm0bz5s2jffv2cfjhh1f5EPXx48fHD37wg2jTpk20aNEidt9993jxxRer/Ri33nprHH744RER8f3vfz/7Gi1/Dn1V3o8Vz2lf3c9WRMTbb78d/+///b9YZ511olmzZrHddtvF3/72tyq/fgDUnD3tANSKOXPmxFdffVVhWSaTifbt21dYdtddd8XcuXPjJz/5SWQymbjyyivj0EMPjf/85z9RWFgYP/nJT+Lzzz+PsWPHxp///OeVPtaYMWPiu+++i1NOOSWKi4tjnXXWidLS0vjDH/4QRx11VJx88skxd+7c+OMf/xiDBg2KV155pUqHWh9xxBHRvXv3GDVqVLz22mvxhz/8ITp06BBXXHFFdsyll14aw4cPjyOOOCJ+/OMfx5dffhk33HBD7LbbbjFp0qRo27Ztduw333wT+++/fwwePDgOP/zwuOmmm2Lw4MFx5513xtChQ+PUU0+No48+On7961/H//t//y8++eSTaN26dUREzJgxI3bcccfIZDJx+umnx3rrrRePPfZYnHTSSVFaWlrpEPfLL788mjRpEmeddVbMmTMnrrzyyjjmmGNi/PjxERHxq1/9KubMmROffvppXHPNNRER0apVq9W+HiNGjIiLLroodtpppxg5cmQUFRXF+PHj45lnnom99947Ipb+wWPEiBExcODAOO2002LatGlx0003xYQJE+LFF1+ssEf3m2++iR/84Adx6KGHxhFHHBF//etf45xzzom+ffvGPvvsE717946RI0fGBRdcEKecckrsuuuuERGx0047Zbfx9ddfxz777BODBw+OH/7wh9GxY8coLy+PAw88MF544YU45ZRTonfv3vHGG2/ENddcE++880489NBDa3zv12TChAnx0ksvxeDBg2P99dePDz/8MG666abYY489YsqUKavd2//MM8/EPvvsE9tuu21ceOGF0aRJkxgzZkzsueee8a9//St22GGHKj/GbrvtFj//+c/j+uuvj//7v/+L3r17R0Rk/63O+7EyK/vZeuutt2LnnXeOrl27xrnnnhstW7aMe++9Nw4++OC4//7745BDDlnr1xeA1UgAYC2MGTMmiYiVfhUXF2fHffDBB0lEJO3bt09mzZqVXf7www8nEZH8/e9/zy4bMmRIsrL/RC3bRklJSTJz5swK6xYvXpwsXLiwwrJvvvkm6dixY3LiiSdWWB4RyYUXXpi9feGFFyYRUWncIYcckrRv3z57+8MPP0wKCgqSSy+9tMK4N954I2natGmF5bvvvnsSEcldd92VXfb2228nEZE0adIkefnll7PLn3jiiSQikjFjxmSXnXTSSUnnzp2Tr776qsJjDR48OGnTpk0yf/78JEmS5Nlnn00iIundu3eF53/dddclEZG88cYb2WX77bdfsuGGGyZV8e677yZNmjRJDjnkkGTJkiUV1pWXlydJkiQzZ85MioqKkr333rvCmN/85jdJRCR/+tOfKr0et99+e3bZwoULk06dOiWHHXZYdtmECRMqvRYrbuPmm2+usPzPf/5z0qRJk+Rf//pXheU333xzEhHJiy++uNrnetxxx63xdVn2ei9v3LhxlZ7Tsvfj2WefTZJk6WvVs2fPZNCgQdnXbdn2unfvnuy1117Vfoz77ruvwmMsU533Y8XnvLqfrQEDBiR9+/ZNvvvuu+yy8vLyZKeddkp69uxZKTMAtcvh8QDUihtvvDHGjh1b4euxxx6rNO7II4+Mdu3aZW8v25v6n//8p8qPddhhh8V6661XYVlBQUH23Nvy8vKYNWtWLF68OLbbbrt47bXXqrTdU089tcLtXXfdNb7++usoLS2NiIgHHnggysvL44gjjoivvvoq+9WpU6fo2bNnpUPxW7VqFYMHD87e3nTTTaNt27bRu3fv6NevX3b5su+XvQZJksT9998fBxxwQCRJUuGxBg0aFHPmzKn0nE444YQK5x7X5HVd3kMPPRTl5eVxwQUXRJMmFf93YdnpCk899VQsWrQohg4dWmHMySefHCUlJfHII49Uej1++MMfZm8XFRXFDjvsUK2MxcXFccIJJ1RYdt9990Xv3r1js802q/Ba7bnnnhERKz1ForqWv9J7WVlZfP3117HJJptE27ZtVzu/Xn/99Xj33Xfj6KOPjq+//jqb7dtvv40BAwbEP//5z+wF4Wr6GMtU9/1YmRV/tmbNmhXPPPNMHHHEETF37txs/q+//joGDRoU7777bnz22Wdr3C4ANefweABqxQ477FClC9FtsMEGFW4vK/DffPNNlR9rZVepj4i47bbb4uqrr4633347ysrK1ji+OtlKSkri3XffjSRJomfPniu9/4qHHq+//vrZgrtMmzZtolu3bpWWLXuciIgvv/wyZs+eHb/73e/id7/73Uofa+bMmVXOXhPvv/9+NGnSJDbffPNVjvnoo48iYukfI5ZXVFQUG2+8cXb9Mit7Pdq1axf//ve/q5yra9eulS6M9u6778bUqVMr/SFnmRVfq5pYsGBBjBo1KsaMGROfffZZJEmSXTdnzpxV3u/dd9+NiIjjjjtulWPmzJkT7dq1q/FjLFPd92NlVvxZee+99yJJkhg+fHgMHz58pfeZOXNmdO3adY3bBqBmlHYA6lVBQcFKly9fUNZkZZ9vfccdd8Txxx8fBx98cPzyl7+MDh06REFBQYwaNSref//9WslWXl4emUwmHnvssZWOXfEc8VVtryqPExHxwx/+cJVlb8stt6zWNtOgrt778vLy6Nu3b4wePXql91nxjyQ18bOf/SzGjBkTQ4cOjf79+0ebNm0ik8nE4MGDV/vRacvW/frXv17ldRWWzZuaPkZtWvH1Xfa4Z511VgwaNGil96nJxzoCUHVKOwCps+Le2Kr461//GhtvvHE88MADFe5/4YUX1lquHj16RJIk0b179+jVq1etbXdF6623XrRu3TqWLFkSAwcOrLXtVud17dGjR5SXl8eUKVNWWTY33HDDiIiYNm1abLzxxtnlixYtig8++KBG2Wvy3vfo0SMmT54cAwYMqNH9q+Kvf/1rHHfccXH11Vdnl3333XeVrsq+smwRESUlJWt8Par6GKt6jnXxfizbTmFhYa3ORQCqzjntAKROy5YtIyLWWIiWt2wv7vJ7bcePHx/jxo2rtVyHHnpoFBQUxIgRIyrtHU6SJL7++utaeZyCgoI47LDD4v77748333yz0vovv/yyRttt2bJllQ6zjog4+OCDo0mTJjFy5MhKe3mXPfeBAwdGUVFRXH/99RVejz/+8Y8xZ86c2G+//WqUMaJ67/0RRxwRn332Wfz+97+vtG7BggXx7bffVjvHigoKCiq95zfccEMsWbJktffbdttto0ePHnHVVVfFvHnzKq1f/r2s6mOs6jWqi/ejQ4cOsccee8Qtt9wSX3zxxWrzA1A37GkHoFY89thj8fbbb1davtNOO1XY61cV2267bURE/PznP49BgwZFQUFBhQu6rcz+++8fDzzwQBxyyCGx3377xQcffBA333xzbL755istSzXRo0ePuOSSS+K8886LDz/8MA4++OBo3bp1fPDBB/Hggw/GKaecEmeddVatPNbll18ezz77bPTr1y9OPvnk2HzzzWPWrFnx2muvxVNPPRWzZs2q9ja33XbbuOeee2LYsGGx/fbbR6tWreKAAw5Y6dhNNtkkfvWrX8XFF18cu+66axx66KFRXFwcEyZMiC5dusSoUaNivfXWi/POOy9GjBgRP/jBD+LAAw+MadOmxW9/+9vYfvvtK1x0rqp69OgRbdu2jZtvvjlat24dLVu2jH79+q32ugQ/+tGP4t57741TTz01nn322dh5551jyZIl8fbbb8e9994bTzzxRJWut7A6+++/f/z5z3+ONm3axOabbx7jxo2Lp556qtJHGq6oSZMm8Yc//CH22Wef6NOnT5xwwgnRtWvX+Oyzz+LZZ5+NkpKS+Pvf/16tx9hqq62ioKAgrrjiipgzZ04UFxfHnnvuGR06dKj19yNi6UUmd9lll+jbt2+cfPLJsfHGG8eMGTNi3Lhx8emnn8bkyZNrtF0AqkZpB6BWXHDBBStdPmbMmGqX9kMPPTR+9rOfxd133x133HFHJEmyxtJ+/PHHx/Tp0+OWW26JJ554IjbffPO444474r777ovnnnuuWo+/Oueee2706tUrrrnmmhgxYkRELD1neu+9944DDzyw1h6nY8eO8corr8TIkSPjgQceiN/+9rfRvn376NOnT4XPja+On/70p/H666/HmDFj4pprrokNN9xwlaU9ImLkyJHRvXv3uOGGG+JXv/pVtGjRIrbccsv40Y9+lB1z0UUXxXrrrRe/+c1v4swzz4x11lknTjnllLjsssvW+JngK1NYWBi33XZbnHfeeXHqqafG4sWLY8yYMast7U2aNImHHnoorrnmmrj99tvjwQcfjBYtWsTGG28cZ5xxRq2cynDddddFQUFB3HnnnfHdd9/FzjvvHE899dQqz/Ne3h577BHjxo2Liy++OH7zm9/EvHnzolOnTtGvX7/4yU9+Uu3H6NSpU9x8880xatSoOOmkk2LJkiXx7LPPRocOHWr9/YiI2HzzzePVV1+NESNGxK233hpff/11dOjQIbbeeutV/twDUHsySZquUAMAAABkOacdAAAAUkppBwAAgJRS2gEAACCllHYAAABIKaUdAAAAUkppBwAAgJTyOe0RUV5eHp9//nm0bt06MplMruMAAADQwCVJEnPnzo0uXbpEkyar3p+utEfE559/Ht26dct1DAAAABqZTz75JNZff/1VrlfaI6J169YRsfTFKikpyXGaVSsrK4snn3wy9t577ygsLMx1HKjEHCXtzFHSzhwl7cxR0i6f5mhpaWl069Yt20dXRWmPyB4SX1JSkvrS3qJFiygpKUn9BKRxMkdJO3OUtDNHSTtzlLTLxzm6plO0XYgOAAAAUkppBwAAgJRS2gEAACCllHYAAABIKaUdAAAAUkppBwAAgJRS2gEAACCllHYAAABIKaUdAAAAUkppBwAAgJRS2gEAACCllHYAAABIKaUdAAAAUkppBwAAgJRS2gEAACCllHYAAABIKaUdAAAAUkppBwAAgJRS2gEAACCllHYAAABIKaUdAAAAUkppBwAAgJRS2gEAACCllHYAAABIKaUdAAAAUkppBwAAgJRS2gEAACClclra//nPf8YBBxwQXbp0iUwmEw899FCF9UmSxAUXXBCdO3eO5s2bx8CBA+Pdd9+tMGbWrFlxzDHHRElJSbRt2zZOOumkmDdvXj0+CwAAAKgbOS3t3377bXzve9+LG2+8caXrr7zyyrj++uvj5ptvjvHjx0fLli1j0KBB8d1332XHHHPMMfHWW2/F2LFj4x//+Ef885//jFNOOaW+ngIAAADUmaa5fPB99tkn9tlnn5WuS5Ikrr322jj//PPjoIMOioiI22+/PTp27BgPPfRQDB48OKZOnRqPP/54TJgwIbbbbruIiLjhhhti3333jauuuiq6dOlSb88FAAAAaltOS/vqfPDBBzF9+vQYOHBgdlmbNm2iX79+MW7cuBg8eHCMGzcu2rZtmy3sEREDBw6MJk2axPjx4+OQQw5Z6bYXLlwYCxcuzN4uLS2NiIiysrIoKyuro2e09pZlS3NGGjdzlLQzR0k7c5S0M0dJu3yao1XNmNrSPn369IiI6NixY4XlHTt2zK6bPn16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pptuit/85jcxderUuOKKK+LKK6+MG264ITvmyiuvjOuvvz5uvvnmGD9+fLRs2TIGDRoU3333XQ6TAwAAwNprmusAq/PSSy/FQQcdFPvtt19ERGy00Ubxl7/8JV555ZWIWLqX/dprr43zzz8/DjrooIiIuP3226Njx47x0EMPxeDBg3OWPWfuaZ3rBAAAANSSVO9p32mnneLpp5+Od955JyIiJk+eHC+88ELss88+ERHxwQcfxPTp02PgwIHZ+7Rp0yb69esX48aNy0nmnFsyb81jijvWfQ4AAADWWqr3tJ977rlRWloam222WRQUFMSSJUvi0ksvjWOOOSYiIqZPnx4RER07ViyhHTt2zK5bmYULF8bChQuzt0tLSyMioqysLMrKymr7adSaZdlWl7FpRGRWs40kIhYf+ElEip8n+asqcxRyyRwl7cxR0s4cJe3yaY5WNWOqS/u9994bd955Z9x1113Rp0+feP3112Po0KHRpUuXOO6442q83VGjRsWIESMqLX/yySejRYsWaxO5XowdO3aV6w6swv0fffTR2gsDK7G6OQppYI6SduYoaWeOknb5MEfnz59fpXGZZPlLsadMt27d4txzz40hQ4Zkl11yySVxxx13xNtvvx3/+c9/okePHjFp0qTYaqutsmN233332GqrreK6665b6XZXtqe9W7du8dVXX0VJSUmdPZ+1VVZWFmPHjo299torCgsLVzqm6X1Fa97TfviiOskHVZmjkEvmKGlnjpJ25ihpl09ztLS0NNZdd92YM2fOantoqve0z58/P5o0qXjafUFBQZSXl0dERPfu3aNTp07x9NNPZ0t7aWlpjB8/Pk477bRVbre4uDiKi4srLS8sLEz9Gxuxdjkz/70/1KV8+Vmi8TJHSTtzlLQzR0m7fJijVc2X6tJ+wAEHxKWXXhobbLBB9OnTJyZNmhSjR4+OE088MSIiMplMDB06NC655JLo2bNndO/ePYYPHx5dunSJgw8+OLfhAQAAYC2lurTfcMMNMXz48PjpT38aM2fOjC5dusRPfvKTuOCCC7Jjzj777Pj222/jlFNOidmzZ8cuu+wSjz/+eDRr1iyHyQEAAGDtpbq0t27dOq699tq49tprVzkmk8nEyJEjY+TIkfUXDAAAAOpBqj+nHQAAABozpb0hmTo61wkAAACoRUp7Q/LvC9Y8BgAAgLyh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1VdfjY4dO0aXLl2iefPmMWvWrHj//fejWbNmccwxx8Q555wTG264YV1lBgAAgEahyqV96623jqKiojj++OPj/vvvj27dulVYv3Dhwhg3blzcfffdsd1228Vvf/vbOPzww2s9cKMzdXTE26MjYoU96w+uv/Tfzf77Oe4AAAA0OFUu7ZdffnkMGjRoleuLi4tjjz32iD322CMuvfTS+PDDD2sjH188EbHgs8rLly374gmlHQAAoIGqcmlfXWFfUfv27aN9+/Y1CgQAAAAstdaf0/7II4/Ec889F0uWLImdd945DjvssNrIxTKdB0XMeSsikogFn/9vefOu/1sPAABAg7RWH/k2fPjwOPvssyOTyUSSJHHmmWfGz372s9rKRsTSQ98P+TRi/2kVlx/y6dIvh8YDAAA0WNXa0/7qq6/Gdtttl719zz33xOTJk6N58+YREXH88cfHHnvsETfccEPtpgQAAIBGqFp72k899dQYOnRozJ8/PyIiNt5447j66qtj2rRp8cYbb8RNN90UvXr1qpOgAAAA0NhUq7SPHz8+OnfuHNtss038/e9/jz/96U8xadKk2GmnnWLXXXeNTz/9NO666666ygoAAACNSrUOjy8oKIhzzjknDj/88DjttNOiZcuW8Zvf/Ca6dOlSV/kAAACg0arRheg23njjeOKJJ+KQQw6J3XbbLW688cbazsUyU0dHPLh+xD82rbj8wfWXfk0dnZtcAAAA1LlqlfbZs2fH2WefHQcccECcf/75ccghh8T48eNjwoQJseOOO8Ybb7xRVzkbr7LSiAWfVfy4t4j/Lvts6XoAAAAapGqV9uOOOy7Gjx8f++23X0ybNi1OO+20aN++fdx6661x6aWXxpFHHhnnnHNOXWVtnApLln4me/MVTkFo3nXpV2FJbnIBAABQ56p1TvszzzwTkyZNik022SROPvnk2GSTTbLrBgwYEK+99lqMHDmy1kMCAABAY1StPe09e/aM3/3ud/HOO+/EzTffHBtuuGGF9c2aNYvLLrusVgM2eg6PBwAAaLSqVdr/9Kc/xTPPPBNbb7113HXXXXHTTTfVVS6W+WZSLH2bVnyr/rvsm0n1nwkAAIB6Ua3D47faaqt49dVX6yoLK9Nu64jP/raSFeX/Ww8AAECDVOXSniRJZDKZuszCyiy7EF0kFQ+Rb971f+sBAABokKp8eHyfPn3i7rvvjkWLFq123LvvvhunnXZaXH755WsdjojoPSzikE8j9p+WXZQ0LVm67JBPl64HAACgQarynvYbbrghzjnnnPjpT38ae+21V2y33XbRpUuXaNasWXzzzTcxZcqUeOGFF+Ktt96K008/PU477bS6zN0IJf/7tmmr3MUAAACg3lS5tA8YMCBeffXVeOGFF+Kee+6JO++8Mz766KNYsGBBrLvuurH11lvHscceG8ccc0y0a9euLjM3euU9h0RBrkMAAABQ56p1IbqIiF122SV22WWXushCFZX3PF1pBwAAaASq9ZFvAAAAQP1R2gEAACCllHYAAABIKaU9L2VyHQAAAIB6oLQDAABAStW4tL///vtx/vnnx1FHHRUzZ86MiIjHHnss3nrrrVoLBwAAAI1ZjUr7888/H3379o3x48fHAw88EPPmzYuIiMmTJ8eFF15YqwEBAACgsapRaT/33HPjkksuibFjx0ZRUVF2+Z577hkvv/xyrYUDAACAxqxGpf2NN96IQw45pNLyDh06xFdffbXWoQAAAIAalva2bdvGF198UWn5pEmTomvXrmsdCgAAAKhhaR88eHCcc845MX369MhkMlFeXh4vvvhinHXWWXHsscfWdkYAAABolGpU2i+77LLYbLPNolu3bjFv3rzYfPPNY7fddouddtopzj///NrOCAAAAI1S0+reIUmSmD59elx//fVxwQUXxBtvvBHz5s2LrbfeOnr27FkXGQEAAKBRqlFp32STTeKtt96Knj17Rrdu3eoiFwAAADR61T48vkmTJtGzZ8/4+uuv6yIPAAAA8F81Oqf98ssvj1/+8pfx5ptv1nYeAAAA4L+qfXh8RMSxxx4b8+fPj+9973tRVFQUzZs3r7B+1qxZtRIOAAAAGrMalfZrr722lmMAAAAAK6pRaT/uuONqOwcAAACwgiqX9tLS0igpKcl+vzrLxgEAAAA1V+XS3q5du/jiiy+iQ4cO0bZt28hkMpXGJEkSmUwmlixZUqshAQAAoDGqcml/5plnYp111omIiGeffbbOAgEAAABLVbm077777iv9HgAAAKgbNboQXUTE7Nmz449//GNMnTo1IiL69OkTJ554YrRp06bWwrG8JNcBAAAAqGdNanKnV199NXr06BHXXHNNzJo1K2bNmhWjR4+OHj16xGuvvVbbGQEAAKBRqtGe9jPPPDMOPPDA+P3vfx9Nmy7dxOLFi+PHP/5xDB06NP75z3/WakgAAABojGpU2l999dUKhT0iomnTpnH22WfHdtttV2vhAAAAoDGr0eHxJSUl8fHHH1da/sknn0Tr1q3XOhQAAABQw9J+5JFHxkknnRT33HNPfPLJJ/HJJ5/E3XffHT/+8Y/jqKOOqu2MAAAA0CjV6PD4q666KjKZTBx77LGxePHiiIgoLCyM0047LS6//PJaDQgAAACNVY1Ke1FRUVx33XUxatSoeP/99yMiokePHtGiRYtaDceqZHIdAAAAgHpQo8PjTzzxxJg7d260aNEi+vbtG3379o0WLVrEt99+GyeeeGJtZwQAAIBGqUal/bbbbosFCxZUWr5gwYK4/fbb1zoUq1fw0pG5jgAAAEA9qNbh8aWlpZEkSSRJEnPnzo1mzZpl1y1ZsiQeffTR6NChQ62HpKLM9MdzHQEAAIB6UK3S3rZt28hkMpHJZKJXr16V1mcymRgxYkSthQMAAIDGrFql/dlnn40kSWLPPfeM+++/P9ZZZ53suqKiothwww2jS5cutR6yUXv+oIjP/lFhUSbKI+4qWHqj6/4Ruz+cg2AAAADUtWqV9t133z0iIj744IPYYIMNIpNxFfM6t2hORJSvZEX5cusBAABoiGp0Ibpnnnkm/vrXv1Zaft9998Vtt9221qFYTlGbWPo2rfhW/XdZUZv6zwQAAEC9qFFpHzVqVKy77rqVlnfo0CEuu+yytQ7FcnZ/OOLoJRGHf5NdlESTpcuOXuLQeAAAgAasRqX9448/ju7du1davuGGG8bHH3+81qEAAACAGpb2Dh06xL///e9KyydPnhzt27df61CsXtLpB7mOAAAAQD2oUWk/6qij4uc//3k8++yzsWTJkliyZEk888wzccYZZ8TgwYNrOyMrWLLTPbmOAAAAQD2o1tXjl7n44ovjww8/jAEDBkTTpks3UV5eHscee6xz2gEAAKCW1Ki0FxUVxT333BMXX3xxTJ48OZo3bx59+/aNDTfcsLbzAQAAQKNVo9K+TK9evaJXr161lQUAAABYTpVL+7Bhw+Liiy+Oli1bxrBhw1Y7dvTo0WsdDAAAABq7Kpf2SZMmRVlZWfb7VclkMmufCgAAAKh6aX/22WdX+j0AAABQN2r0kW933HFHzJ8/v7azAAAAAMupUWk/88wzo0OHDnH00UfHo48+GkuWLKntXKwoSXKdAAAAgHpWo9L+xRdfxN133x2ZTCaOOOKI6Ny5cwwZMiReeuml2s4HAAAAjVaNSnvTpk1j//33jzvvvDNmzpwZ11xzTXz44Yfx/e9/P3r06FHbGQEAAKBRWqvPaY+IaNGiRQwaNCi++eab+Oijj2Lq1Km1kQsAAAAavRrtaY+ImD9/ftx5552x7777RteuXePaa6+NQw45JN56663azAcAAACNVo32tA8ePDj+8Y9/RIsWLeKII46I4cOHR//+/Ws7GwAAADRqNSrtBQUFce+998agQYOioKCgtjMBAAAAUcPSfuedd9Z2DgAAAGAFNT6nnRzKZHKdAAAAgHqgtAMAAEBKKe0AAACQUko7AAAApFSNS/v7778f559/fhx11FExc+bMiIh47LHHfE47AAAA1JIalfbnn38++vbtG+PHj48HHngg5s2bFxERkydPjgsvvLBWAwIAAEBjVaPSfu6558Yll1wSY8eOjaKiouzyPffcM15++eVaCwcAAACNWY1K+xtvvBGHHHJIpeUdOnSIr776aq1DAQAAADUs7W3bto0vvvii0vJJkyZF165d1zoUAAAAUMPSPnjw4DjnnHNi+vTpkclkory8PF588cU466yz4thjj63tjAAAANAo1ai0X3bZZbHZZptFt27dYt68ebH55pvHbrvtFjvttFOcf/75tZ0RAAAAGqWmNblTUVFR/P73v4/hw4fHm2++GfPmzYutt946evbsWdv5AAAAoNGqUWlfZoMNNogNNtigtrIAAAAAy6lyaR82bFiVNzp69OgahQEAAAD+p8qlfdKkSRVuv/baa7F48eLYdNNNIyLinXfeiYKCgth2221rNyEAAAA0UlUu7c8++2z2+9GjR0fr1q3jtttui3bt2kVExDfffBMnnHBC7LrrrrWfEgAAABqhGl09/uqrr45Ro0ZlC3tERLt27eKSSy6Jq6++utbCAQAAQGNWo9JeWloaX375ZaXlX375ZcydO3etQ7EySa4DAAAAUM9qVNoPOeSQOOGEE+KBBx6ITz/9ND799NO4//7746STTopDDz20tjMCAABAo1Sjj3y7+eab46yzzoqjjz46ysrKlm6oadM46aST4te//nWtBgQAAIDGqkalvUWLFvHb3/42fv3rX8f7778fERE9evSIli1b1mo4AAAAaMxqVNqXadmyZWy55Za1lQUAAABYTo3OaQcAAADqntIOAAAAKaW0AwAAQEop7QAAAJBSNboQ3e23377a9ccee2yNwgAAAAD/U6PSfsYZZ1S4XVZWFvPnz4+ioqJo0aKF0l7nMrkOAAAAQD2o0eHx33zzTYWvefPmxbRp02KXXXaJv/zlL7WdEQAAABqlWjunvWfPnnH55ZdX2gsPAAAA1EytXoiuadOm8fnnn9fmJgEAAKDRqtE57X/7298q3E6SJL744ov4zW9+EzvvvHOtBAMAAIDGrkal/eCDD65wO5PJxHrrrRd77rlnXH311bWRCwAAABq9GpX28vLy2s4BAAAArKBWz2kHAAAAak+N9rRHRHz66afxt7/9LT7++ONYtGhRhXWjR49e62AAAADQ2NWotD/99NNx4IEHxsYbbxxvv/12bLHFFvHhhx9GkiSxzTbb1HZGAAAAaJRqdHj8eeedF2eddVa88cYb0axZs7j//vvjk08+id133z0OP/zw2s4IAAAAjVKNSvvUqVPj2GOPjYiln82+YMGCaNWqVYwcOTKuuOKKWg0IAAAAjVWNSnvLli2z57F37tw53n///ey6r776qnaSAQAAQCNXrdI+cuTI+Pbbb2PHHXeMF154ISIi9t133/jFL34Rl156aZx44omx44471klQAAAAaGyqVdpHjBgR3377bYwePTr69euXXTZgwIC45557YqONNoo//vGPdRIUAAAAGptqXT0+SZKIiNh4442zy1q2bBk333xz7aYCAAAAqn9OeyaTqYscrFGS6wAAAADUs2p/TnuvXr3WWNxnzZpV40AAAADAUtUu7SNGjIg2bdrURRYAAABgOdUu7YMHD44OHTrURRYAAABgOdU6p9357AAAAFB/qlXal109HgAAAKh71To8vry8vK5yAAAAACuo9ke+AQAAAPVDaQcAAICUUtoBAAAgpZR2AAAASCmlPS/56D0AAIDGQGkHAACAlFLaAQAAIKWUdgAAAEgppR0AAABSSmkHAACAlMqr0n755ZdHJpOJoUOHZpd99913MWTIkGjfvn20atUqDjvssJgxY0buQgIAAEAtyZvSPmHChLjllltiyy23rLD8zDPPjL///e9x3333xfPPPx+ff/55HHrooTlKCQAAALUnL0r7vHnz4phjjonf//730a5du+zyOXPmxB//+McYPXp07LnnnrHtttvGmDFj4qWXXoqXX345h4kBAABg7TXNdYCqGDJkSOy3334xcODAuOSSS7LLJ06cGGVlZTFw4MDsss022yw22GCDGDduXOy4444r3d7ChQtj4cKF2dulpaUREVFWVhZlZWV19CzWUllZFGa/LYtokhdvHY3Msp+f1P4c0eiZo6SdOUramaOkXT7N0apmTH3zu/vuu+O1116LCRMmVFo3ffr0KCoqirZt21ZY3rFjx5g+ffoqtzlq1KgYMWJEpeVPPvlktGjRYq0z14XCZF7s+9/vn3rqqUgyBTnNA6szduzYXEeA1TJHSTtzlLQzR0m7fJij8+fPr9K4VJf2Tz75JM4444wYO3ZsNGvWrNa2e95558WwYcOyt0tLS6Nbt26x9957R0lJSa09Tq1a9E3Ew0u/HThwYBQWN89tHliJsrKyGDt2bOy1115RWFi45jtAPTNHSTtzlLQzR0m7fJqjy474XpNUl/aJEyfGzJkzY5tttskuW7JkSfzzn/+M3/zmN/HEE0/EokWLYvbs2RX2ts+YMSM6deq0yu0WFxdHcXFxpeWFhYXpfWOT/+VKdU4Ic5T0M0dJO3OUtDNHSbt8mKNVzZfq0j5gwIB44403Kiw74YQTYrPNNotzzjknunXrFoWFhfH000/HYYcdFhER06ZNi48//jj69++fi8gAAABQa1Jd2lu3bh1bbLFFhWUtW7aM9u3bZ5efdNJJMWzYsFhnnXWipKQkfvazn0X//v1XeRE6AAAAyBepLu1Vcc0110STJk3isMMOi4ULF8agQYPit7/9ba5j1b4kyXUCAAAA6lnelfbnnnuuwu1mzZrFjTfeGDfeeGNuAgEAAEAdaZLrAAAAAMDKKe0AAACQUko7AAAApJTSDgAAACmltAMAAEBKKe0AAACQUko7AAAApJTSDgAAACmltAMAAEBKKe0AAACQUkp7Pspkcp0AAACAeqC0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7XkjyXUAAAAA6pnSDgAAACmltAMAAEBKKe0AAACQUko7AAAApJTSDgAAACmltAMAAEBKKe0AAACQUko7AAAApJTSDgAAACmltAMAAEBKKe0AAACQUko7AAAApJTSnpcyuQ4AAABAPVDaAQAAIKWUdgAAAEgppR0AAABSSmkHAACAlFLaAQAAIKWUdgAAAEgppR0AAABSSmnPQ03euS7XEQAAAKgHSnseavLu9bmOAAAAQD1Q2gEAACClmuY6AGswdXTE26Mjojy7KLPgs4gH1196Y7NhEb2H5SYbAAAAdUppT7uy0ogFn1VevmxZWWn95gEAAKDeKO1pV1gS0bxrRFIe8d0X/1vevOv/1gMAANAgKe1p1/u/h79/91XEA+tFRETSvGtkDvk0x8EAAACoay5EBwAAACmltOeh8p4/z3UEAAAA6oHSnofKe52R6wgAAADUA6UdAAAAUkppBwAAgJRS2gEAACCllHYAAABIKaUdAAAAUkppBwAAgJRS2gEAACCllHYAAABIKaUdAAAAUkppz0uZXAcAAACgHijtAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0p43klwHAAAAoJ4p7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW056NMJtcJAAAAqAdKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0p43klwHAAAAoJ4p7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSnu+SJJcJwAAAKCeKe0AAACQUko7AAAApJTSDgAAACmltAMAAEBKKe0AAACQUko7AAAApJTSDgAAACmltAMAAEBKKe0AAACQUko7AAAApJTSDgAAACmltAMAAEBKKe0AAACQUko7AAAApJTSDgAAACmltAMAAEBKKe0AAACQUkp7nkkik+sIAAAA1BOlHQAAAFJKaQcAAICUUtoBAAAgpZR2AAAASCmlHQAAAFJKaQcAAICUUtrzRpLrAAAAANQzpR0AAABSSmkHAACAlFLaAQAAIKWUdgAAAEgppR0AAABSKtWlfdSoUbH99ttH69ato0OHDnHwwQfHtGnTKoz57rvvYsiQIdG+ffto1apVHHbYYTFjxowcJQYAAIDak+rS/vzzz8eQIUPi5ZdfjrFjx0ZZWVnsvffe8e2332bHnHnmmfH3v/897rvvvnj++efj888/j0MPPTSHqQEAAKB2NM11gNV5/PHHK9y+9dZbo0OHDjFx4sTYbbfdYs6cOfHHP/4x7rrrrthzzz0jImLMmDHRu3fvePnll2PHHXfMRWwAAACoFane076iOXPmRETEOuusExEREydOjLKyshg4cGB2zGabbRYbbLBBjBs3LicZAQAAoLakek/78srLy2Po0KGx8847xxZbbBEREdOnT4+ioqJo27ZthbEdO3aM6dOnr3JbCxcujIULF2Zvl5aWRkREWVlZlJWV1X742rC4LAr/+21qM9LoLZub5ihpZY6SduYoaWeOknb5NEermjFvSvuQIUPizTffjBdeeGGttzVq1KgYMWJEpeVPPvlktGjRYq23XxeKy7+JH/z3+7Fjx+Y0C6yJOUramaOknTlK2pmjpF0+zNH58+dXaVxelPbTTz89/vGPf8Q///nPWH/99bPLO3XqFIsWLYrZs2dX2Ns+Y8aM6NSp0yq3d95558WwYcOyt0tLS6Nbt26x9957R0lJSZ08h7X23fSIvy/9dq+99orCwsLVj4ccKCsri7Fjx5qjpJY5StqZo6SdOUra5dMcXXbE95qkurQnSRI/+9nP4sEHH4znnnsuunfvXmH9tttuG4WFhfH000/HYYcdFhER06ZNi48//jj69++/yu0WFxdHcXFxpeWFhYXpfWMX/y9XqnNCmKOknzlK2pmjpJ05Strlwxytar5Ul/YhQ4bEXXfdFQ8//HC0bt06e556mzZtonnz5tGmTZs46aSTYtiwYbHOOutESUlJ/OxnP4v+/fu7cjwAAAB5L9Wl/aabboqIiD322KPC8jFjxsTxxx8fERHXXHNNNGnSJA477LBYuHBhDBo0KH7729/Wc1IAAACofaku7UmSrHFMs2bN4sYbb4wbb7yxHhIBAABA/cmrz2kHAACAxkRpBwAAgJRS2gEAACCllPa8k8l1AAAAAOqJ0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbTnjSTXAQAAAKhnSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSnueSXIdAAAAgHqjtAMAAEBKKe0AAACQUko7AAAApJTSDgAAACmltOeLxCXoAAAAGhulHQAAAFJKaQcAAICUUtoBAAAgpZR2AAAASCmlHQAAAFJKaQcAAICUUtoBAAAgpZR2AAAASCmlHQAAAFJKaQcAAICUUtoBAAAgpZR2AAAASCmlHQAAAFJKaQcAAICUUtoBAAAgpZR2AAAASCmlHQAAAFJKaQcAAICUUtoBAAAgpZR2AAAASCmlHQAAAFJKac87mVwHAAAAoJ4o7QAAAJBSSjsAAACklNIOAAAAKaW0540k1wEAAACoZ0o7AAAApJTSDgAAACmltAMAAEBKKe0AAACQUko7AAAApJTSDgAAACmltAMAAEBKKe0AAACQUko7AAAApJTSDgAAACmltAMAAEBKKe0AAACQUko7AAAApJTSDgAAACmltAMAAEBKKe0AAACQUko7AAAApJTSDgAAACmltAMAAEBKKe0AAACQUko7AAAApJTSDgAAACmltOedTK4DAAAAUE+UdgAAAEgppR0AAABSSmnPG0muAwAAAFDPlHYAAABIKaUdAAAAUkppBwAAgJRS2gEAACCllHYAAABIKaUdAAAAUkppBwAAgJRS2gEAACCllHYAAABIKaUdAAAAUkppBwAAgJRS2gEAACCllHYAAABIKaUdAAAAUkppBwAAgJRS2gEAACCllHYAAABIKaUdAAAAUkppBwAAgJRS2gEAACCllHYAAABIKaUdAAAAUkppBwAAgJRS2vNMkusAAAAA1BulPV8k6joAAEBjo7QDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASinteSP577+ZnKYAAACg/ijtAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASjWY0n7jjTfGRhttFM2aNYt+/frFK6+8kutIdSITS6LJO9fmOgYAAAD1oEGU9nvuuSeGDRsWF154Ybz22mvxve99LwYNGhQzZ87MdbRa1yTKo8k71+U6BgAAAPWgQZT20aNHx8knnxwnnHBCbL755nHzzTdHixYt4k9/+lOuowEAAECNNc11gLW1aNGimDhxYpx33nnZZU2aNImBAwfGuHHjVnqfhQsXxsKFC7O3S0tLIyKirKwsysrK6jZwNTV559qle9aTxZH577LMgs8ieXD9iIgo73VGlPcamrN8sLxlPz9p+zmCZcxR0s4cJe3MUdIun+ZoVTPmfWn/6quvYsmSJdGxY8cKyzt27Bhvv/32Su8zatSoGDFiRKXlTz75ZLRo0aJOctbUposmxmZln1VanlmwdNm7UybGtPcere9YsFpjx47NdQRYLXOUtDNHSTtzlLTLhzk6f/78Ko3L+9JeE+edd14MGzYse7u0tDS6desWe++9d5SUlOQwWWVN3nknkndeiEiSyHz3eXZ50rxrRET07LVt9Oi1b67iQQVlZWUxduzY2GuvvaKwsDDXcaASc5S0M0dJO3OUtMunObrsiO81yfvSvu6660ZBQUHMmDGjwvIZM2ZEp06dVnqf4uLiKC4urrS8sLAwfW9sn18u/YqI5MH1lx4a37xrZA75NCIiCv77BWmSyp8lWI45StqZo6SdOUra5cMcrWq+vL8QXVFRUWy77bbx9NNPZ5eVl5fH008/Hf37989hMgAAAFg7eb+nPSJi2LBhcdxxx8V2220XO+ywQ1x77bXx7bffxgknnJDraLWqvNcZ8e6UidGz17b2rgMAADQCDaK0H3nkkfHll1/GBRdcENOnT4+tttoqHn/88UoXp8t35b2GxrT3Ho0evfZV2gEAABqBBlHaIyJOP/30OP3003MdAwAAAGpN3p/TDgAAAA2V0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0g4AAAAp1TTXAdIgSZKIiCgtLc1xktUrKyuL+fPnR2lpaRQWFuY6DlRijpJ25ihpZ46SduYoaZdPc3RZ/1zWR1dFaY+IuXPnRkREt27dcpwEAACAxmTu3LnRpk2bVa7PJGuq9Y1AeXl5fP7559G6devIZDK5jrNKpaWl0a1bt/jkk0+ipKQk13GgEnOUtDNHSTtzlLQzR0m7fJqjSZLE3Llzo0uXLtGkyarPXLenPSKaNGkS66+/fq5jVFlJSUnqJyCNmzlK2pmjpJ05StqZo6RdvszR1e1hX8aF6AAAACCllHYAAABIKaU9jxQXF8eFF14YxcXFuY4CK2WOknbmKGlnjpJ25ihp1xDnqAvRAQAAQErZ0w4AAAAppbQDAABASintAAAAkFJKOwAAAKSU0p4nbrzxxthoo42iWbNm0a9fv3jllVdyHYkG4p///GcccMAB0aVLl8hkMvHQQw9VWJ8kSVxwwQXRuXPnaN68eQwcODDefffdCmNmzZoVxxxzTJSUlETbtm3jpJNOinnz5lUY8+9//zt23XXXaNasWXTr1i2uvPLKSlnuu+++2GyzzaJZs2bRt2/fePTRR2v9+ZJfRo0aFdtvv320bt06OnToEAcffHBMmzatwpjvvvsuhgwZEu3bt49WrVrFYYcdFjNmzKgw5uOPP4799tsvWrRoER06dIhf/vKXsXjx4gpjnnvuudhmm22iuLg4Ntlkk7j11lsr5fG7mBXddNNNseWWW0ZJSUmUlJRE//7947HHHsuuNz9Jm8svvzwymUwMHTo0u8w8JdcuuuiiyGQyFb4222yz7PpGP0cTUu/uu+9OioqKkj/96U/JW2+9lZx88slJ27ZtkxkzZuQ6Gg3Ao48+mvzqV79KHnjggSQikgcffLDC+ssvvzxp06ZN8tBDDyWTJ09ODjzwwKR79+7JggULsmN+8IMfJN/73veSl19+OfnXv/6VbLLJJslRRx2VXT9nzpykY8eOyTHHHJO8+eabyV/+8pekefPmyS233JId8+KLLyYFBQXJlVdemUyZMiU5//zzk8LCwuSNN96o89eA9Bo0aFAyZsyY5M0330xef/31ZN9990022GCDZN68edkxp556atKtW7fk6aefTl599dVkxx13THbaaafs+sWLFydbbLFFMnDgwGTSpEnJo48+mqy77rrJeeedlx3zn//8J2nRokUybNiwZMqUKckNN9yQFBQUJI8//nh2jN/FrMzf/va35JFHHkneeeedZNq0acn//d//JYWFhcmbb76ZJIn5Sbq88soryUYbbZRsueWWyRlnnJFdbp6SaxdeeGHSp0+f5Isvvsh+ffnll9n1jX2OKu15YIcddkiGDBmSvb1kyZKkS5cuyahRo3KYioZoxdJeXl6edOrUKfn1r3+dXTZ79uykuLg4+ctf/pIkSZJMmTIliYhkwoQJ2TGPPfZYkslkks8++yxJkiT57W9/m7Rr1y5ZuHBhdsw555yTbLrpptnbRxxxRLLffvtVyNOvX7/kJz/5Sa0+R/LbzJkzk4hInn/++SRJls7HwsLC5L777suOmTp1ahIRybhx45IkWfqHqSZNmiTTp0/PjrnpppuSkpKS7Jw8++yzkz59+lR4rCOPPDIZNGhQ9rbfxVRVu3btkj/84Q/mJ6kyd+7cpGfPnsnYsWOT3XffPVvazVPS4MILL0y+973vrXSdOZokDo9PuUWLFsXEiRNj4MCB2WVNmjSJgQMHxrhx43KYjMbggw8+iOnTp1eYf23atIl+/fpl59+4ceOibdu2sd1222XHDBw4MJo0aRLjx4/Pjtltt92iqKgoO2bQoEExbdq0+Oabb7Jjln+cZWPMc5Y3Z86ciIhYZ511IiJi4sSJUVZWVmHubLbZZrHBBhtUmKN9+/aNjh07ZscMGjQoSktL46233sqOWd3887uYqliyZEncfffd8e2330b//v3NT1JlyJAhsd9++1WaS+YpafHuu+9Gly5dYuONN45jjjkmPv7444gwRyOc0556X331VSxZsqTCBIyI6NixY0yfPj1HqWgsls2x1c2/6dOnR4cO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WrWK7bffPp566qlKr9/FF18cxx57bJSUlMQpp5wS3bt3j4iIrbfeOjKZTOyxxx4RUfnw9fLy8hg1alR07949mjdvHt/73vfir3/9a3b9N998E8ccc0yst9560bx58+jZs2eMGTNmlc9pxe0vXLgwfv7zn0eHDh2iWbNmscsuu8SECRMqvQbLW9nRGg8//HBss8020axZs9h4441jxIgRsXjx4uz6Nb2nkydPju9///vRunXrKCkpiW233Xal8wmAxkNpB6DBKygoiMsuuyxuuOGG+PTTT1c6ZuLEiXHEEUfE4MGD44033oiLLroohg8fXukQ6muuuSZ23nnnmDRpUuy3337xox/9KI499tj44Q9/GK+99lr06NEjjj322EiSJHuf+fPnx6WXXhq33357vPjiizF79uwYPHhwhe2+9957cf/998cDDzyQPVT88MMPj5kzZ8Zjjz0WEydOjG222SYGDBgQs2bNWulzmDdvXuy///6x+eabx8SJE+Oiiy6Ks846q8KY2bNnx5577hlbb711vPrqq/H444/HjBkz4ogjjljta7im5zBv3rzYd9994+mnn45JkybFD37wgzjggAPi448/rrCdq666Kr73ve/FpEmTYvjw4fHKK69ERMRTTz0VX3zxRTzwwAMrffxRo0bF7bffHjfffHO89dZbceaZZ8YPf/jDeP755yMiYvjw4TFlypR47LHHYurUqXHTTTfFuuuuu9rntLyzzz477r///rjtttvitddei0022SQGDRq0ytd6Zf71r3/FscceG2eccUZMmTIlbrnllrj11lvj0ksvzY5Z03t6zDHHxPrrrx8TJkyIiRMnxrnnnhuFhYVVzgBAA5QAQAN23HHHJQcddFCSJEmy4447JieeeGKSJEny4IMPJsv/Z/Doo49O9tprrwr3/eUvf5lsvvnm2dsbbrhh8sMf/jB7+4svvkgiIhk+fHh22bhx45KISL744oskSZJkzJgxSUQkL7/8cnbM1KlTk4hIxo8fnyRJklx44YVJYWFhMnPmzOyYf/3rX0lJSUny3XffVcjUo0eP5JZbblnpc73llluS9u3bJwsWLMguu+mmm5KISCZNmpQkSZJcfPHFyd57713hfp988kkSEcm0adNWut2qPIeV6dOnT3LDDTdkb2+44YbJwQcfXGHMBx98UCHfMsu/b999913SokWL5KWXXqow5qSTTkqOOuqoJEmS5IADDkhOOOGEVWZZ0fLbnzdvXlJYWJjceeed2fWLFi1KunTpklx55ZVJkix9Ddq0aVNhGyvOoQEDBiSXXXZZhTF//vOfk86dOydJUrX3tHXr1smtt95a5ecBQMNnTzsAjcYVV1wRt912W0ydOrXSuqlTp8bOO+9cYdnOO+8c7777bixZsiS7bMstt8x+37Fjx4iI6Nu3b6VlM2fOzC5r2rRpbL/99tnbm222WbRt27ZCjg033DDWW2+97O3JkyfHvHnzon379tGqVavs1wcffBDvv//+Sp/f1KlTY8stt8weXh8Rla5ePnny5Hj22WcrbHOzzTaLiFjldqvyHObNmxdnnXVW9O7dO9q2bRutWrWKqVOnVtrTvt12263yMVblvffei/nz58dee+1VIfftt9+ezXzaaafF3XffHVtttVWcffbZ8dJLL1V5+++//36UlZVVeP8LCwtjhx12WOlcWZXJkyfHyJEjK2Q8+eST44svvoj58+dX6T0dNmxY/PjHP46BAwfG5Zdfvtr3BIDGoWmuAwBAfdltt91i0KBBcd5558Xxxx9fo20sf6jysvOZV7asvLy8Wttt2bJlhdvz5s2Lzp07x3PPPVdp7NpcQG3evHlxwAEHxBVXXFFpXefOnWu83bPOOivGjh0bV111VWyyySbRvHnz+H//7/9Vutjcis+zqpkjIh555JHo2rVrhXXFxcUREbHPPvvERx99FI8++miMHTs2BgwYEEOGDImrrrqqhs+ooiZNmlQ45SEioqysrFLOESNGxKGHHlrp/s2aNavSe3rRRRfF0UcfHY888kg89thjceGFF8bdd98dhxxySK08DwDyj9IOQKNy+eWXx1ZbbRWbbrppheW9e/eOF198scKyF198MXr16hUFBQVr9ZiLFy+OV199NXbYYYeIiJg2bVrMnj07evfuvcr7bLPNNjF9+vRo2rRplT82rHfv3vHnP/85vvvuu+ze9pdffrnSdu+///7YaKONomnTqv9vwJqew4svvhjHH398tlzOmzcvPvzwwzVut6ioKCKiwtEMK9p8882juLg4Pv7449h9991XOW699daL4447Lo477rjYdddd45e//GWVSnuPHj2iqKgoXnzxxdhwww0jYmkhnzBhQgwdOjS77blz58a3336b/cPDih9Tt80228S0adNik002WenjVPU97dWrV/Tq1SvOPPPMOOqoo2LMmDFKO0Aj5vB4ABqVvn37xjHHHBPXX399heW/+MUv4umnn46LL7443nnnnbjtttviN7/5TaULudVEYWFh/OxnP4vx48fHxIkT4/jjj48dd9wxW4BXZuDAgdG/f/84+OCD48knn4wPP/wwXnrppfjVr361yquJH3300ZHJZOLkk0+OKVOmxKOPPlqptA4ZMiRmzZoVRx11VEyYMCHef//9eOKJJ+KEE05YbXFe03Po2bNn9iJ6kydPjqOPPrpKRxt06NAhmjdvnr0g3pw5cyqNad26dZx11llx5plnxm233Rbvv/9+vPbaa3HDDTfEbbfdFhERF1xwQTz88MPx3nvvxVtvvRX/+Mc/VvtHkeW1bNkyTjvttPjlL38Zjz/+eEyZMiVOPvnkmD9/fpx00kkREdGvX79o0aJF/N///V+8//77cdddd1W6SOEFF1wQt99+e4wYMSLeeuutmDp1atx9991x/vnnR8Sa39MFCxbE6aefHs8991x89NFH8eKLL8aECROq/DwAaJiUdgAanZEjR1YqlNtss03ce++9cffdd8cWW2wRF1xwQYwcObLGh9Evr0WLFnHOOefE0UcfHTvvvHO0atUq7rnnntXeJ5PJxKOPPhq77bZbnHDCCdGrV68YPHhwfPTRR9nz5lfUqlWr+Pvf/x5vvPFGbL311vGrX/2q0mHwXbp0iRdffDGWLFkSe++9d/Tt2zeGDh0abdu2jSZNVv2/BWt6DqNHj4527drFTjvtFAcccEAMGjSoSp9T3rRp07j++uvjlltuiS5dusRBBx200nEXX3xxDB8+PEaNGhW9e/eOH/zgB/HII49kPzKuqKgozjvvvNhyyy1jt912i4KCgrj77rvX+PjLXH755XHYYYfFj370o9hmm23ivffeiyeeeCLatWsXERHrrLNO3HHHHfHoo49G37594y9/+UtcdNFFFbYxaNCg+Mc//hFPPvlkbL/99rHjjjvGNddck917v6b3tKCgIL7++us49thjo1evXnHEEUfEPvvsEyNGjKjy8wCg4ckkK56gBQCwnFtvvTWGDh0as2fPznWUWnPUUUdFQUFB3HHHHbmOAgCrZU87ANBoLF68OKZMmRLjxo2LPn365DoOAKyR0g4ANBpvvvlmbLfddtGnT5849dRTcx0HANbI4fEAAACQUva0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEop7QAAAJBSSjsAAACklNIOAAAAKaW0AwAAQEr9f+EkI6NrPIBCAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 1200x1200 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "y=entrainementIAvAleatoire(50_000, 12)\n",
    "x=[x for x in range(1,50_001)]\n",
    "\n",
    "print(\"Après entrainement contre un environement jouant aléatoirement sur un jeu de taille initiale 12, l'ordinateur gagne \\n-------------- \", y[-1] ,\" % du temps\")\n",
    "\n",
    "plt.figure()\n",
    "plt.plot(x, y, color='orange', marker='+', markeredgewidth=2)\n",
    "plt.xlabel(\"Nombre de parties jouées\")\n",
    "plt.ylabel(\"Tau de victoire (%)\")\n",
    "plt.grid()\n",
    "plt.title(\"Entrainement contre l'aléatoire\")\n",
    "plt.show()\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
