{"cells": [{"cell_type": "markdown", "id": "cf349c14", "metadata": {}, "source": ["# 2048 et les classes\n", "\n", "Le jeu [2048](https://play2048.co/) est assez addictif mais peut-on imaginer une strat\u00e9gie qui joue \u00e0 notre place est maximise le gain... Le jeu se joue sur une matrice *4x4*."]}, {"cell_type": "code", "execution_count": 1, "id": "ef14b2b0", "metadata": {}, "outputs": [{"data": {"text/html": ["
run previous cell, wait for 2 seconds
\n", ""], "text/plain": [""]}, "execution_count": 2, "metadata": {}, "output_type": "execute_result"}], "source": ["from jyquickhelper import add_notebook_menu\n", "add_notebook_menu()"]}, {"cell_type": "markdown", "id": "e0e341cf", "metadata": {}, "source": ["## D\u00e9composition du probl\u00e8me\n", "\n", "0. Cr\u00e9ation de la matrice de jeu\n", "1. Ajout d'un nombre al\u00e9atoire dans `{2,4}` \u00e0 une position al\u00e9atoire pourvu qu'elle soit libre\n", "2. D\u00e9termination de toutes les cases libres\n", "3. A-t-on perdu ?\n", "4. Joue un coup sachant une direction donn\u00e9e\n", "5. Aggr\u00e8ge les nombres dans un tableau que ce soit une ligne ou une colonne\n", "6. Score...\n", "7. Choisit le coup suivant (un coup au hasard selon deux directions possibles)\n", "8. Joue une partie en appelant toutes les fonctions pr\u00e9c\u00e9dentes."]}, {"cell_type": "markdown", "id": "6d47e109", "metadata": {}, "source": ["### 0 - Cr\u00e9ation de la matrice de jeu"]}, {"cell_type": "code", "execution_count": 2, "id": "bc5cda97", "metadata": {}, "outputs": [{"data": {"text/plain": ["array([[0, 0, 0, 0],\n", " [0, 0, 0, 0],\n", " [0, 0, 0, 0],\n", " [0, 0, 0, 0]])"]}, "execution_count": 3, "metadata": {}, "output_type": "execute_result"}], "source": ["import numpy\n", "\n", "def creer_jeu(dim):\n", " return numpy.zeros((dim, dim), dtype=int)\n", "\n", "jeu = creer_jeu(4)\n", "jeu"]}, {"cell_type": "markdown", "id": "a58daf2e", "metadata": {}, "source": ["### 2 - D\u00e9termination de toutes les cases libres"]}, {"cell_type": "code", "execution_count": 3, "id": "7b111cfd", "metadata": {}, "outputs": [{"data": {"text/plain": ["[(0, 0),\n", " (0, 1),\n", " (0, 2),\n", " (0, 3),\n", " (1, 0),\n", " (1, 1),\n", " (1, 2),\n", " (1, 3),\n", " (2, 0),\n", " (2, 1),\n", " (2, 2),\n", " (2, 3),\n", " (3, 0),\n", " (3, 1),\n", " (3, 2),\n", " (3, 3)]"]}, "execution_count": 4, "metadata": {}, "output_type": "execute_result"}], "source": ["def position_libre(jeu):\n", " pos = []\n", " for i in range(jeu.shape[0]):\n", " for j in range(jeu.shape[1]):\n", " if jeu[i, j] == 0:\n", " pos.append((i, j))\n", " return pos\n", "\n", "\n", "position_libre(jeu)"]}, {"cell_type": "markdown", "id": "cb56dec6", "metadata": {}, "source": ["### 1 - Ajout d'un nombre al\u00e9atoire dans {2,4} \u00e0 une position al\u00e9atoire pourvu qu'elle soit libre"]}, {"cell_type": "code", "execution_count": 4, "id": "8c66d10e", "metadata": {}, "outputs": [{"data": {"text/plain": ["array([[0, 0, 0, 0],\n", " [0, 0, 0, 0],\n", " [0, 0, 0, 0],\n", " [0, 4, 0, 0]])"]}, "execution_count": 5, "metadata": {}, "output_type": "execute_result"}], "source": ["def nombre_aleatoire(jeu):\n", " pos = position_libre(jeu)\n", " nb = numpy.random.randint(0, 2) * 2 + 2\n", " i = numpy.random.randint(0, len(pos))\n", " p = pos[i]\n", " jeu[p] = nb\n", " \n", "nombre_aleatoire(jeu)\n", "jeu"]}, {"cell_type": "markdown", "id": "312ea544", "metadata": {}, "source": ["### 3 - A-t-on perdu ?"]}, {"cell_type": "code", "execution_count": 5, "id": "33564881", "metadata": {}, "outputs": [{"data": {"text/plain": ["False"]}, "execution_count": 6, "metadata": {}, "output_type": "execute_result"}], "source": ["def perdu(jeu):\n", " pos = position_libre(jeu)\n", " return len(pos) == 0\n", "\n", "perdu(jeu)"]}, {"cell_type": "markdown", "id": "b8086d68", "metadata": {}, "source": ["### 5 - Aggr\u00e8ge les nombres dans un tableau que ce soit une ligne ou une colonne"]}, {"cell_type": "code", "execution_count": 6, "id": "c0fce40f", "metadata": {}, "outputs": [{"data": {"text/plain": ["array([2, 4, 4, 0])"]}, "execution_count": 7, "metadata": {}, "output_type": "execute_result"}], "source": ["def joue_ligne_colonne(lc):\n", " # on enl\u00e8ve les 0\n", " non_null = [a for a in lc if a != 0]\n", " # on additionne les nombres identiques cons\u00e9cutifs\n", " i = len(non_null) - 1\n", " while i > 0:\n", " if non_null[i] != 0 and non_null[i] == non_null[i-1]:\n", " non_null[i-1] *= 2\n", " non_null[i] = 0\n", " i -= 2\n", " else:\n", " i -= 1\n", " # on enl\u00e8ve \u00e0 nouveau les z\u00e9ros\n", " non_null2 = [a for a in non_null if a != 0]\n", " final = numpy.zeros(len(lc), dtype=int)\n", " final[:len(non_null2)] = non_null2\n", " return final\n", "\n", "joue_ligne_colonne(numpy.array([2, 4, 2, 2]))"]}, {"cell_type": "code", "execution_count": 7, "id": "b0f2d2fe", "metadata": {}, "outputs": [], "source": ["assert joue_ligne_colonne(numpy.array([0, 2, 0, 2])).tolist() == [4, 0, 0, 0]\n", "assert joue_ligne_colonne(numpy.array([2, 2, 2, 2])).tolist() == [4, 4, 0, 0]\n", "assert joue_ligne_colonne(numpy.array([2, 4, 2, 2])).tolist() == [2, 4, 4, 0]"]}, {"cell_type": "markdown", "id": "143d5c47", "metadata": {}, "source": ["### 4 - Joue un coup sachant une direction donn\u00e9e"]}, {"cell_type": "code", "execution_count": 8, "id": "f2933759", "metadata": {}, "outputs": [{"data": {"text/plain": ["array([[0, 0, 0, 0],\n", " [0, 0, 0, 0],\n", " [0, 0, 0, 0],\n", " [4, 0, 0, 0]])"]}, "execution_count": 9, "metadata": {}, "output_type": "execute_result"}], "source": ["def joue_coup(jeu, direction):\n", " if direction == 0: # gauche\n", " for i in range(jeu.shape[0]):\n", " jeu[i, :] = joue_ligne_colonne(jeu[i, :])\n", " elif direction == 1: # droite\n", " for i in range(jeu.shape[0]):\n", " jeu[i, ::-1] = joue_ligne_colonne(jeu[i, ::-1])\n", " elif direction == 2: # haut\n", " for i in range(jeu.shape[0]):\n", " jeu[:, i] = joue_ligne_colonne(jeu[:, i])\n", " elif direction == 3: # bas\n", " for i in range(jeu.shape[0]):\n", " jeu[::-1, i] = joue_ligne_colonne(jeu[::-1, i])\n", "\n", "joue_coup(jeu, 0)\n", "jeu"]}, {"cell_type": "markdown", "id": "a1894143", "metadata": {}, "source": ["### 6 - score"]}, {"cell_type": "code", "execution_count": 9, "id": "7d6a5697", "metadata": {}, "outputs": [{"data": {"text/plain": ["4"]}, "execution_count": 10, "metadata": {}, "output_type": "execute_result"}], "source": ["def score(jeu):\n", " return jeu.max()\n", " # \u00e0 ne pas confondre avec max(jeu)\n", " # max(jeu) appelle la fonction max de python (et non celle du numpy),\n", " # elle cherche le maximum sur toutes les lignes\n", " # et comparer deux lignes est ambig\u00fc, comparaison terme \u00e0 terme ? ce n'est pas un ordre total\n", " \n", "score(jeu)"]}, {"cell_type": "markdown", "id": "3bb9d978", "metadata": {}, "source": ["Voir [ordre total](https://fr.wikipedia.org/wiki/Ordre_total)."]}, {"cell_type": "markdown", "id": "13358dcb", "metadata": {}, "source": ["### 7 - coup suivant"]}, {"cell_type": "code", "execution_count": 10, "id": "102da10a", "metadata": {}, "outputs": [{"data": {"text/plain": ["2"]}, "execution_count": 11, "metadata": {}, "output_type": "execute_result"}], "source": ["def coup_suivant(jeu):\n", " # une direction al\u00e9atoire parmi 0 ou 4\n", " h = numpy.random.randint(0, 2)\n", " return h * 2\n", "\n", "\n", "coup_suivant(jeu)"]}, {"cell_type": "markdown", "id": "756afd5c", "metadata": {}, "source": ["### 8 - la fonction faisant tout"]}, {"cell_type": "code", "execution_count": 11, "id": "73ead8f4", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["nombre de coups: 68, score=64 jeu:\n", "[[64 32 16 4]\n", " [32 16 8 2]\n", " [ 2 8 4 2]\n", " [ 8 2 4 2]]\n"]}], "source": ["def partie(dim):\n", " jeu = creer_jeu(dim)\n", " coup = 0\n", " while not perdu(jeu):\n", " nombre_aleatoire(jeu)\n", " d = coup_suivant(jeu)\n", " joue_coup(jeu, d)\n", " coup += 1\n", " return coup, jeu\n", "\n", "coup, jeu = partie(4)\n", "print(\"nombre de coups: %d, score=%d jeu:\" % (coup, score(jeu)))\n", "print(jeu)"]}, {"cell_type": "markdown", "id": "0ba27ead", "metadata": {}, "source": ["## Classes"]}, {"cell_type": "code", "execution_count": 12, "id": "170bd17b", "metadata": {}, "outputs": [{"data": {"text/plain": ["coup=0 score=0, jeu=\n", "[[0 0 0 0]\n", " [0 0 0 0]\n", " [0 0 0 0]\n", " [0 0 0 0]]"]}, "execution_count": 13, "metadata": {}, "output_type": "execute_result"}], "source": ["class c2048:\n", " \n", " def __init__(self, dim=4):\n", " self.jeu = self.creer_jeu(dim)\n", " self.coup = 0\n", " self.score = 0\n", " \n", " def creer_jeu(self, dim):\n", " return creer_jeu(dim)\n", "\n", " def __repr__(self):\n", " return \"coup=%d score=%d, jeu=\\n%s\" % (self.coup, self.score, self.jeu)\n", " \n", "J = c2048()\n", "J"]}, {"cell_type": "code", "execution_count": 13, "id": "b0e51772", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["coup=0 score=0, jeu=\n", "[[0 0 0 0]\n", " [0 0 0 0]\n", " [0 0 0 0]\n", " [0 0 0 0]]\n"]}], "source": ["print(J) # l'interpr\u00e9teur python ex\u00e9cute implicitement : print(J.__repr__())"]}, {"cell_type": "markdown", "id": "56d57876", "metadata": {}, "source": ["## Classe compl\u00e8te"]}, {"cell_type": "code", "execution_count": 14, "id": "4e29bfa7", "metadata": {}, "outputs": [{"data": {"text/plain": ["coup=40 score=16, jeu=\n", "[[16 2 16 8]\n", " [ 2 16 4 2]\n", " [ 8 4 16 2]\n", " [ 4 2 8 4]]"]}, "execution_count": 15, "metadata": {}, "output_type": "execute_result"}], "source": ["class c2048:\n", " \n", " def __init__(self, dim=4):\n", " self.jeu = self.creer_jeu(dim)\n", " self.coup = 0\n", " self.score = 0\n", " \n", " def creer_jeu(self, dim):\n", " return creer_jeu(dim)\n", "\n", " def __repr__(self):\n", " return \"coup=%d score=%d, jeu=\\n%s\" % (self.coup, self.score, self.jeu)\n", " \n", " def position_libre(self):\n", " pos = []\n", " for i in range(self.jeu.shape[0]):\n", " for j in range(self.jeu.shape[1]):\n", " if self.jeu[i, j] == 0:\n", " pos.append((i, j))\n", " return pos\n", "\n", " def calcule_score(self):\n", " return self.jeu.max()\n", "\n", " def joue_ligne_colonne(self, lc):\n", " # on enl\u00e8ve les 0\n", " non_null = [a for a in lc if a != 0]\n", " # on additionne les nombres identiques cons\u00e9cutifs\n", " i = len(non_null) - 1\n", " while i > 0:\n", " if non_null[i] != 0 and non_null[i] == non_null[i-1]:\n", " non_null[i-1] *= 2\n", " non_null[i] = 0\n", " i -= 2\n", " else:\n", " i -= 1\n", " # on enl\u00e8ve \u00e0 nouveau les z\u00e9ros\n", " non_null2 = [a for a in non_null if a != 0]\n", " final = numpy.zeros(len(lc), dtype=int)\n", " final[:len(non_null2)] = non_null2\n", " return final\n", "\n", " def joue_coup(self, direction):\n", " if direction == 0: # gauche\n", " for i in range(self.jeu.shape[0]):\n", " self.jeu[i, :] = joue_ligne_colonne(self.jeu[i, :])\n", " elif direction == 1: # droite\n", " for i in range(self.jeu.shape[0]):\n", " self.jeu[i, ::-1] = joue_ligne_colonne(self.jeu[i, ::-1])\n", " # identique \u00e0\n", " # self.jeu[i, :] = joue_ligne_colonne(self.jeu[i, ::-1])[::-1]\n", " elif direction == 2: # haut\n", " for i in range(self.jeu.shape[0]):\n", " self.jeu[:, i] = joue_ligne_colonne(self.jeu[:, i])\n", " elif direction == 3: # bas\n", " for i in range(self.jeu.shape[0]):\n", " self.jeu[::-1, i] = joue_ligne_colonne(self.jeu[::-1, i])\n", " \n", " def nombre_aleatoire(self):\n", " pos = self.position_libre()\n", " nb = numpy.random.randint(0, 2) * 2 + 2\n", " i = numpy.random.randint(0, len(pos))\n", " p = pos[i]\n", " self.jeu[p] = nb\n", "\n", " def perdu(self):\n", " pos = self.position_libre()\n", " return len(pos) == 0\n", "\n", " def coup_suivant(self):\n", " # une direction al\u00e9atoire parmi 0 ou 4\n", " h = numpy.random.randint(0, 2)\n", " return h * 2\n", " \n", " def partie(self):\n", " self.coup = 0\n", " while not self.perdu():\n", " self.nombre_aleatoire()\n", " d = self.coup_suivant()\n", " self.joue_coup(d)\n", " self.coup += 1\n", " self.score = self.calcule_score()\n", " \n", "J = c2048()\n", "J.partie()\n", "J"]}, {"cell_type": "markdown", "id": "c0baddc8", "metadata": {}, "source": ["## Un dernier graphe pour finir\n", "\n", "On r\u00e9alise plusieurs parties, on trace un graphe avec le nombre de coups en abscisse et le score en ordonn\u00e9e."]}, {"cell_type": "code", "execution_count": 15, "id": "96828bc8", "metadata": {}, "outputs": [{"name": "stderr", "output_type": "stream", "text": ["100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 500/500 [00:01<00:00, 282.10it/s]\n"]}, {"data": {"text/html": ["
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
scorecoup
06467
112896
212884
31629
41633
\n", "
"], "text/plain": [" score coup\n", "0 64 67\n", "1 128 96\n", "2 128 84\n", "3 16 29\n", "4 16 33"]}, "execution_count": 16, "metadata": {}, "output_type": "execute_result"}], "source": ["from tqdm import tqdm\n", "from pandas import DataFrame\n", "\n", "obs = []\n", "for i in tqdm(range(500)):\n", " J = c2048()\n", " J.partie()\n", " obs.append(dict(score=J.score, coup=J.coup))\n", "\n", "df = DataFrame(obs)\n", "df.head()"]}, {"cell_type": "code", "execution_count": 16, "id": "550ebe36", "metadata": {}, "outputs": [{"data": {"image/png": "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\n", "text/plain": ["
"]}, "metadata": {"needs_background": "light"}, "output_type": "display_data"}], "source": ["df.plot(x='coup', y='score', kind='scatter', title=\"Score / Coup\");"]}, {"cell_type": "markdown", "id": "c646aa6a", "metadata": {}, "source": ["## Une autre strat\u00e9gie pour illustrer l'h\u00e9ritage\n", "\n", "On veut essayer une autre strat\u00e9gie et la comparer avec la pr\u00e9c\u00e9dente. Pour cela, on cr\u00e9e une seconde classe dans laquelle on remplace la m\u00e9thode `coup_suivant`. On pourrait tout copier coller mais c'est tr\u00e8s souvent la plus mauvaise option. Et pour \u00e9viter cela, on cr\u00e9e une seconde classe qui [h\u00e9rite](http://www.xavierdupre.fr/app/teachpyx/helpsphinx/c_classes/classes.html?highlight=h%C3%A9ritage#heritage) de la pr\u00e9c\u00e9dente, puis on remplace la m\u00e9thode souhait\u00e9e."]}, {"cell_type": "code", "execution_count": 17, "id": "57d15200", "metadata": {}, "outputs": [{"name": "stderr", "output_type": "stream", "text": ["100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 500/500 [00:01<00:00, 299.41it/s]\n"]}, {"data": {"text/html": ["
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
scorecoup
06455
16465
23252
33251
46467
\n", "
"], "text/plain": [" score coup\n", "0 64 55\n", "1 64 65\n", "2 32 52\n", "3 32 51\n", "4 64 67"]}, "execution_count": 18, "metadata": {}, "output_type": "execute_result"}], "source": ["class c2048_4(c2048):\n", " \n", " def coup_suivant(self):\n", " # une direction al\u00e9atoire parmi 0 ou 4\n", " h = numpy.random.randint(0, 3)\n", " return h\n", "\n", "obs = []\n", "for i in tqdm(range(500)):\n", " J = c2048()\n", " J.partie()\n", " obs.append(dict(score=J.score, coup=J.coup))\n", "\n", "df2 = DataFrame(obs)\n", "df2.head()"]}, {"cell_type": "code", "execution_count": 18, "id": "a3732857", "metadata": {}, "outputs": [{"data": {"image/png": "iVBORw0KGgoAAAANSUhEUgAAA0cAAAEWCAYAAACt9+z4AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAABF+klEQVR4nO3de3xV5Z33/c8vYZMEwzFEFBIJyqHIKUpAfbQVPIBVx8PolHqoWhl9WovW0arttHp79673WJ9nOm3ttFOntKi3ohZn1EGfqZ0K2nokKKKIKKMgAcQYAQkk5PR7/lhrJzvJTrJDsrP3Tr7v12u/9t7XutZav3WtkItfrrWuZe6OiIiIiIjIQJeV6gBERERERETSgZIjERERERERlByJiIiIiIgASo5EREREREQAJUciIiIiIiKAkiMRERERERFAyZGIiIiIiAig5EgGGDM7xcxeMrO9ZvaZmb1oZnNSHReAmW0ys8kdLFtoZi+Y2T4zqzSz583svL6OUUREkkv9lEhqKTmSAcPMhgErgXuBUcA44H8CB3t5P9mHsM4xQLa7vxdn2cXA74EHgCJgDHAH8Fc9DFVERNKI+imR1FNyJAPJZAB3X+7uje5e4+7Puvv6aAUzu8bMNoZ/+XrHzI4Py6ea2Woz22NmG2L/GmZmy8zsV2b2jJntB+ab2Vgzezz869mHZnZDF7GdAzzTttDMDPgJ8L/c/Tfuvtfdm9z9eXe/JqyTZWY/MLOtZvaJmT1gZsPDZfPMrKLNNreY2Rnh5zvNbIWZPRoe8+tmNusQ2lZERHpO/RTqpyS1lBzJQPIe0Ghm95vZl81sZOxCM/sb4E7gCmAYcB5QZWYR4D+AZ4HDgeuBh8xsSszqlwJ3AUOBl8L6bxL81e904EYzW9hJbGcDT8cpnwIUAys6Wfeq8DUfOBrIB37RSf22zif4i98o4GHgifCYRUSkb6mfik/9lPQZJUcyYLj758ApgAP/ClSa2VNmNias8rfAPe6+xgOb3X0rcCLBL/K73b3O3Z8juOzhkpjNP+nuL7p7EzADKHT3H4b1Pwj399V4cZnZEGAOsDrO4oLwfWcnh3YZ8BN3/8Ddq4HvAV81s0FdNEnUWndf4e71BH/9yw2PWURE+pD6qQ6pn5I+o+RIBhR33+juV7l7ETAdGAv8NFxcDPx3nNXGAtvCDiVqK8Ff26K2xXweD4wNL23YY2Z7gL8nuAY7ntOBl9w93jXlVeH7kR0fFWPDeGJjG9TJ/tpqjj08xopwmyIi0sfUT8Wlfkr6jJIjGbDc/V1gGUHnA8Ev32PiVN0BFJtZ7L+Xo4DtsZuL+bwN+NDdR8S8hrr72R2EcjZxruMObQq3d1Enh7KDoKOLja0B2AXsB4ZEF4Q34Ra2Wb84ZnkWwc20OzrZn4iI9AH1U83UT0mfUXIkA4aZfcHMbjazovB7McElB6+EVX4DfMfMZltgopmNB14FDgC3mlnEzOYRzMDzSAe7eg3YZ2a3mVmemWWb2XTreCrWLxP/Om7c3YGbgNvN7OtmNiy8sfUUM7svrLYc+Dszm2Bm+cD/Bh519waC69dzzeyc8PrsHwA5bXYz28z+Ory84UaCWZFeQURE+pT6KfVTknpKjmQg2QecALxqwWw9rwBvAzcDuPvvCW5WfTis+wQwyt3rCDqZLwOfAr8Ergj/oteOuzcC5wKlwIfhOr8Bhreta2bTgWp3/6ijoN19BbAIuJrgL2W7gB8BT4ZVfgs8CLwQ7q+W4GZc3H0vcF24/+0Ef6FrNStQuJ1FwG7ga8Bfh9d1i4hI31I/pX5KUsyChF9EUsHMbgVGu/utKdr/ncBEd788FfsXEZH0pn5KBppEZwkRkeTYQjCdqoiISDragvopGUCUHImkkLs/luoYREREOqJ+SgYaXVYnIiIiIiKCJmQQEREREREBMvyyutGjR3tJSUmqwxARGdDWrl37qbu3fS6JoH5KRCQddKefyujkqKSkhPLy8lSHISIyoJnZ1lTHkK7UT4mIpF53+ildViciIiIikikqK2HNmuA9meukiz6OXcmRiIiIiEgmWL4cxo+HM88M3pcvT8466SIFsWf0bHVlZWWuyxVERFLLzNa6e1mq40hH6qdEpNdUVgYJQk1NS1leHmzdCoUd3E5zKOuki16MvTv9VEbfcyQiAlBfX09FRQW1tbWpDqVfy83NpaioiEgkkupQREQySq/0UwcPwr//O8QObJjB9u3w6ae9t066OITYe6OfUnIkIhmvoqKCoUOHUlJSgpmlOpx+yd2pqqqioqKCCRMmpDocEZGM0iv9VH09NDUFr6isLJg2DTpKBg5lnXTRzdh7q5/SPUcikvFqa2spKChQYpREZkZBQYFG50REDkGv9FORSHCZWVYWZGcH7+PHd57kHMo66aKbsfdWP6WRIxHpF5QYJZ/aWETk0PXK79CCAhg2DOrqYPDgxJKcQ1knXXQz9t5oYyVHIiIiIiKZIhLpfoJzKOukiz6OXZfViYhkkB07dvDggw+mOgwREZG4Mr2fUnIkItIL7rrrLqZNm8bMmTMpLS3l1VdfBeCnP/0pBw4c6Pb2li1bxo4dO1qV7dmzh5tuuonTTz+9y/XLy8u54YYburXPs846ixEjRnDuued2az0REUl/md5PrVu3jpNOOqn5GB599NFux5wIXVYnIgNSVfVBKnbXUDQyj4L8nB5t6+WXX2blypW8/vrr5OTk8Omnn1JXVwcEnc7ll1/OkCFD2q3X2NhIdnZ23G0uW7aM6dOnM3bs2OayESNG8MgjjyQUU1lZGWVl3Xv00C233MKBAwf49a9/3a31REQkCSorYcsWKCnp8TOJ+kM/NWTIEB544AEmTZrEjh07mD17NgsXLmTEiBEJbyMRGjkSkQHnyXXbOfnHz3H5b17l5B8/x1Prtvdoezt37mT06NHk5ARJ1ujRoxk7diw///nP2bFjB/Pnz2f+/PkA5Ofnc/PNNzNr1ixefvllfvjDHzJnzhymT5/Otddei7uzYsUKysvLueyyyygtLaWmpoa1a9dy6qmnNncGO3fuBGDNmjXNfwW85ZZbmD59OgCrV69uHgHav38/V199NXPnzuW4447jySefjHscp59+OkOHDu1RW4iISC9YvjyYme3MM4P35ct7tLn+0E9NnjyZSZMmATB27FgOP/xwKisre9Qucbl7xr5mz57tIiLvvPNOwnU/3VfrU37wjI+/bWXza8oPnvFP99Ue8v737dvns2bN8kmTJvk3v/lNX716dfOy8ePHe2VlZfN3wB999NHm71VVVc2fL7/8cn/qqafc3f3UU0/1NWvWuLt7XV2dn3TSSf7JJ5+4u/sjjzziX//6193dfdq0af7SSy+5u/ttt93m06ZNc3f3VatW+TnnnOPu7t/73vf8wQcfdHf33bt3+6RJk7y6ujruscSuF0+8tgbKPQ36hHR8qZ8SEffu9VP+ySfueXnuweNPg1deXlB+iPpTP+Xu/uqrr/oXvvAFb2xsbLesp/2URo5EZECp2F1DJKv1r75IVhYVu2sOeZv5+fmsXbuW++67j8LCQhYtWsSyZcvi1s3Ozuaiiy5q/r5q1SpOOOEEZsyYwXPPPceGDRvarbNp0ybefvttzjzzTEpLS/nRj35ERUUFe/bsYd++fZx00kkAXHrppXH3+eyzz3L33XdTWlrKvHnzqK2t5aOPPjrk4xURkSTasiWYtjpWJBKUH6L+1E/t3LmTr33ta/zud78jK6v3UxndcyQiA0rRyDzqY5+2DdQ3NVE0Mq9H283OzmbevHnMmzePGTNmcP/993PVVVe1q5ebm9t8/XZtbS3XXXcd5eXlFBcXc+edd8Z9eJ27M23aNF5++eVW5Xv27EkoNnfn8ccfZ8qUKd0+LhER6WMlJcFzfWLV1wflPdAf+qnPP/+cc845h7vuuosTTzwxoW13l0aORGRAKcjP4Z6LZpIbyWJoziByI1ncc9HMHk3KsGnTJt5///3m7+vWrWP8+PEADB06lH379sVdL9rBjB49murqalasWNG8LHa9KVOmUFlZ2dzp1NfXs2HDBkaMGMHQoUObZxzq6CbYhQsXcu+99xJcWQBvvPHGIR+riIgkWWEhLF0KeXnBA1Dz8oLvPZiUoT/0U3V1dVx44YVcccUVXHzxxd06/u7QyJGIDDjnlY7j5Imje222uurqaq6//nr27NnDoEGDmDhxIvfddx8A1157LWeddRZjx45l1apVrdYbMWIE11xzDdOnT+eII45gzpw5zcuuuuoqvvGNb5CXl8fLL7/MihUruOGGG9i7dy8NDQ3ceOONTJs2jaVLl3LNNdeQlZXFqaeeyvDhw9vFd/vtt3PjjTcyc+ZMmpqamDBhAitXrmxX74tf/CLvvvsu1dXVFBUVsXTpUhYuXNijthERkUNwySVwxhm9Nltdf+inHnvsMV544QWqqqqaLwlctmwZpaWlPWqbtiyaoWWisrIyLy8vT3UYIpJiGzduZOrUqakOIyWqq6vJz88H4O6772bnzp387Gc/S9r+4rW1ma119+7NGz5AqJ8SEVA/lUn9lEaOREQy2NNPP80//MM/0NDQwPjx4zu8wVZERCQVMq2fUnIkIpLBFi1axKJFi1IdhoiISFyZ1k9pQgYR6Rcy+RLhTKE2FhE5dPodmny90cZKjkQk4+Xm5lJVVaWOJ4ncnaqqKnJzc1MdiohIxlE/lXy91U8l/bI6M8sGyoHt7n6umU0AHgEKgLXA19y9zsxygAeA2UAVsMjdtyQ7PhHJfEVFRVRUVFBZWZnqUPq13NxcioqKUh2GiEjGUT/VN3qjn+qLe46+DWwEhoXffwz8k7s/Ymb/AiwGfhW+73b3iWb21bBe5lygKCIpE4lEmDBhQqrDEBERiUv9VOZI6mV1ZlYEnAP8JvxuwGlA9AlS9wMXhJ/PD78TLj89rC8iIiIiIpJ0yb7n6KfArUBT+L0A2OPuDeH3CmBc+HkcsA0gXL43rN+KmV1rZuVmVq6hSRERSTfqp0REMlfSkiMzOxf4xN3X9uZ23f0+dy9z97LCHj4tWEREpLepnxIRyVzJvOfoZOA8MzsbyCW45+hnwAgzGxSODhUB28P624FioMLMBgHDCSZmEBERERERSbqkjRy5+/fcvcjdS4CvAs+5+2XAKuDisNqVwJPh56fC74TLn3PNdygiIiIiIn0kFc85ug24ycw2E9xTtDQsXwoUhOU3Ad9NQWwiIiIiIjJA9cVU3rj7amB1+PkDYG6cOrXA3/RFPCIiIiIiIm2lYuRIREREREQk7Sg5EhERERERQcmRiIiIiIgIoORIREREREQEUHIkIiIiIiICKDkSEREREREBupEcmVmemU1JZjAiIiIiIiKpklByZGZ/BawD/jP8XmpmTyUxLhERERERkT6V6MjRnQQPbt0D4O7rgAlJiUhERERERCQFEk2O6t19b5sy7+1gREREREREUmVQgvU2mNmlQLaZTQJuAF5KXlgiIiIiIiJ9K9GRo+uBacBB4GFgL3BjkmISERERERHpc12OHJlZNvC0u88Hvp/8kERERERERPpel8mRuzeaWZOZDY9z35GIiIhI5qqshC1boKQECgvbf49Xp62NG+G112DuXJg6tfU6+flQXd3yvmsXrFkDRxwBH38Mc+bAmDGtt/3QQ/DYY/CVr8Bll7Xf1nvvwapVcMEFcO65rWMoKICqqpZYouUHDsDatTB/PkQiQRzHHw+DB7fsO95xAKxcCU88AbNnw+7dQdmFFwZ1Omqb2JhffBHefRfmzQuONXocbdu8bXki56s7daLldXWweXP74xQBcPcuX8CTwEfAUuDn0Vci6ybzNXv2bBcRkdQCyj3F/UG6vtRPpbmHH3bPy3MfPjx4X7Kk9feHH25f5+GHW29jyRJ3aHktWdKyTl5eUDZ4cOs6bV9ZWS3bLipqvWzUqNbbavuaMaN9DNHX9Omd7xfcI5Fg22ee2f443Dvfxplnxm+btsff9lihZXm0zaN1o5/btnO889WdOtHySCT+cUq/1p1+yoL6nTOzKztIrO7vrSTtUJSVlXl5eXkqQxARGfDMbK27l6U6jnSkfiqNVVbC+PFQU9NxndxcMGtdJy8Ptm5tGWk59tj469XWdj+mQYOgoaH76yXLL38J112XeP28vGB0avbszts10W1F2xnin69E63QV0zvvaASpn+tOP5XQhAxhErQcWBu+Hk51YiQicqiqqg/y5rY9VFUf7NYyEelHtmwJLinrTHY2ZLX5r1IkEqwLwSVovSmBP1j3qeXLu1c/EgnapKt2TXRb0XaG+Ocr0TpdxdTb51EyWkJTeZvZPOB+YAtgQLGZXenuLyQtMhGRJHhy3XZue3w9kaws6puauOeimZxXOq7LZSLSz5SUBPeedKaxMRg5ilVfH6wLwT0rvantvlLtkkvgz39OvH59fdAmXbVrotuKtjPEP1+J1ukqpt4+j5LREp3K+x+BBe5+qrt/CVgI/FPywhIR6X1V1Qe57fH11NY3se9gA7X1Tdz6+Hqqqg92ukxE+qHCQli6NLjsatiw4H3Jktbff/vb9nWWLm25jGvq1GCdWEuWBOvl5QWX10HXIylmQf0HHoDi4tbLRo0KluXlxV93xoz2McQu60okEmx7wYL2x/HNb3a+jQUL2rfN1KktbRYv5uhIXG5u6zaPtlV0vdh2hvjnK9E6sTFFIu2PU5fUSYxE7zla7+4zuyrra7qWW0S6481te7j8N6+y72DLNf1Dcwbxf/72BIAOl80qHtHXoWYU3XPUMfVTGUCz1Wm2Oun3utNPJZoc/RZoAv5PWHQZkO3uVx9ylL1AnY6IdEdV9UFO/vFz1NY3NZflRrJ48bbTADpcVpCf0+exZhIlRx1TPyUiknq9PiED8E3gHeCG8PVOWCYikjEK8nO456KZ5EayGJoziNxIFvdcNJOC/JxOl4mIiMjAkNCEDGG9n7n7TwDMLBvQ/xhEJOOcVzqOkyeOpmJ3DUUj81olP50tExERkf4v0eToT8AZQHX4PQ94Fvi/khGUiEgyRUeKurtMRERE+rdEL6vLdfdoYkT4eUhyQhIREREREel7iSZH+83s+OgXMysDevjoYxERERERkfSRaHL0beD3ZvZnM/sz8AjQwaT6ATMrNrNVZvaOmW0ws2+H5aPM7I9m9n74PjIsNzP7uZltNrP1scmYiIiIiIhIsiWaHE0AjiOYoe6PwCagqznAG4Cb3f1Y4ETgW2Z2LPBd4E/uPongXqbvhvW/DEwKX9cCv+rGcYiIiIiIiPRIosnR7e7+OTACmA/8ki6SF3ff6e6vh5/3ARuBccD5wP1htfuBC8LP5wMPeOAVYISZHZn4oYiIiIiIiBy6RJOjxvD9HOBf3f1pYHCiOzGzEoKRp1eBMe6+M1z0MTAm/DwO2BazWkVY1nZb15pZuZmVV1ZWJhqCiIhIn1A/JSKSuRJNjrab2a+BRcAzZpaT6Lpmlg88DtwYjj41c3en68vzWnH3+9y9zN3LCgsLu7OqiIhI0qmfEhHJXIkmR18B/gAsdPc9wCjglq5WMrMIQWL0kLv/W1i8K3q5XPj+SVi+HSiOWb0oLBMREREREUm6hJIjdz/g7v/m7u+H33e6+7OdrWNmBiwFNrr7T2IWPQVcGX6+EngypvyKcNa6E4G9MZffiYiIiIiIJNWgJG77ZOBrwFtmti4s+3vgbuAxM1sMbCUYlQJ4Bjgb2AwcAL6exNhERERERERaSVpy5O5/AayDxafHqe/At5IVj4iIiIiISGeSOXIkIiIiA0FlJWzZAvn5UF3d/r2kBAoLg3qrVsGuXTBhAlRVwaBB8N57MGcOjBkTLFuzBtzhzTdh1iwoL4ft2+Gyy2D+/KD+qlUwfDhs3gwjR8IHH0BdHbz/PhQUwOefw7x5wT7ffBPOPRe+9S145BFYuRKKiuCzz2DUKKioCLaxcycceWTw/eijg/XffBPGjoUdO2DiRNi7FxoagvLTToOZM2HuXJg6Fe64Ax58MCi79VYYPLgl1vnzYfLkluOLHm9dHTz/fNCOF14YbOfFF+HZZ1vX2bw5OK6qqpb9VVbCG28E6xYXt27rnpzHnmxDJMNZMGCTmcrKyry8vDzVYYiIDGhmttbdy1IdRzoaEP3U8uWweHHwuaYGIhGorw8Sg7o6yMsLli1eDP/yL0FiIR0rLoZt27qut2ABrF4dtHFUtK2XLoVLLunefqPnMXreDmUbImmqO/2UkiMREekRJUcd6/f9VGUljB8fJEWSPvLyYOvWxEd/4p3H7m5DJI11p5/SZXWSMpt37WPdtj2UFo9g4pih7b7Hqqo+SMXuGg4bnM3+usbm9/qGRrZUHWDkkAi7D9RTUjCEyKDs5vKSgiF8/PlBPq0+yPSxw4gMyubTfbW8WbGXWUXDGT00t933wwZns3rTJ7y1fS/zpxQyoXBoq+213X5kUDaHDc5mx94awPisupaXP/iMowuGsL++qdV2Y2OPvheNDP7SF3t80e1H2yJ6/EUj8yjIz2Hzrn38YcPHAIwbkcsHnx7gS5NGUzahoMP2TdZ5E5EBbMuWYKRByVF6iUSCc5NoYhPvPHZ3GyL9hJIjSYk7nniLB175qPn75DGH8d6u/c3frzjpKH54/gwAnly3ndseX483OQcbnUi2Ud/oGN18gvAhePLNrmeTzzZoTDCQaN3oMeRkG43umBnZWUZtfVO74/rixALWbN1NJCuL+qYm5owfyZ83V7Xb9s+f28wXJxbw4N+e2K59Y9uzJ5K1XRHJUCUlrS/rkvRQXx+cm0TFO4/d3YZIP5HoQ2BFes3mXfta/QcbaJUYATzw8kds3rWPquqD3Pb4emrrmzgYZiD14Xu6XBCaaGIUWzd6DAcbnYam4HttfRPQ/rj+vLmK2vom9h1soLa+KW5iFFv3ide3tWvfaHv2RLzz1hvbFZEMVlgY3JuSl9dyv8ug8O+ugwcH77m5wbIlS1qW9UfW0QS93VRcnFi9BQta2jgqeh6WLu3eiE/seRw27NC2IdJP9OPfUpKu1m3bk3C9SWOGEsnKopam5AbVj6x86+O45eu27enRZXAdnbeebldEMtwll8AZZyQ2W90dd2i2unSdrS72PGq2OhnANCGD9LnNu/Zxxj+90GW9//q7LzHysMGc/OPnmkdVpGs//cpMbnxsfbvy//q7L/UoienovPV0u5L5NCFDx9RPiYikXnf6KV1WJ31u4pihXHHSUa3Kpow5rNX3K046ioljhlKQn8M9F80kN5JFTnZwyUIkfO+lCxh6LLsbgUTrRo8hJ9sYlBV8z40E/xzbbu6LEwvIjWQxNGcQuZEsvjixgI58cWIBFxxf3K59o+3ZE/HOW29sV0RERCRdaORIUkaz1Wm2OukfNHLUMfVTIiKpp+cciYhIn1Fy1DH1UyIiqafnHImIiAxklZWtb6zfuBFeey2YUGDw4JaJEurq4PXXg5v+6+uDiQMiEdiwIZgMID+/ZWKE6KQH7sGkB5MmBdutrobRo2HfPigrg1NOCeq/8kqw/4MHWyY9OO44+Pjj4Hk6EybApk2QkxPEOm1asD+zYLtTpwb7mjULtm0LjmvUqGAyg2nTgngnT4b9+4P3hoaWCQui7xMnBsuh/YQFbdsoOgnCggVw8snx27HtdxHpdzRyJCIiPaKRo46lpJ9avhwWLw6SoLq6IFn54x9blmdnQ2MjZGVB0wCb7CY63fjixcFU1dE2OuYYePvtlnoLFsBVV7Vux7brLF0azPAmImlPl9WJiEifUXLUsT7vpyorYfz4YGRGeiaaBHUkLw+2btUIkkgG0GV1Ga7tzfdty+Pd0L97fx3rtu1hUBZ88OkBjh49hIYmmicMeGVzJf+1qZLxI3PZU9vIEUMH8/G+OiaMymPtR3vYV9vACRNGUt8EJx09igmFQ1m5roI/vltJ2VHDGTvyMD6rrmXttr3MLh7OJ/sOUrW/noIhg3iv8gAzjsxnSO5gDtTW8dbOakpG5rK/wfm/JoykuCCf2roG3trxOY2Njby+bS9fGDOUcSNy+csHn1E8PIfdtY1MOfww6ptgWE42H35Ww7xJo5lRPJJP99WyalMlw/MGMX/K4UQGZfPWtt2sfv9TJozK4/ODLccTjT12YoNXP/wMgBMmjGo1mUJ0Eoe27yUFQzhQ3wgYY4fnNrdxQX5Ou3MQO0HCXzZXMjo/l5OOKYh73tqez0SXi4gkbMuW4D/1So6SLxIJ2lvJkUi/opGjNPPkuu3c9vh6IllZ1Dc1cc9FMzmvdFxzOUBtfRPZBo0OuZEs6hudxqbMPY/JkmXQG80SnWL7K2VFPFZegTc5Bxu9ubxs/Ej+srmqub4BP/tqaavz1vZ8RnW1XCQTaOSoYxo5ymAaORLpN/ScowxVVX2Q2x5fT219E/sONlBb38Stj69n8659zeXRh6E2hv/pr61vUmLUgd5qlmi7P/DyR9TWN3EwbPxoeWxiBODAd36/rtV5iz2fVdUHgY7Pd3S5iEinXnwR/sf/gJUrg0kKbr4ZSkuD/6xnZwf/uY9EgskLYmUN4K4/NzdIapYsCd6HDQveZ8xoXW/BAli2rHWdtussXarESKQf0mV1aaRidw2RrCxqablBNpKVxbpte9qVS3oz4p+3SFYWFbtrKMjP6fB8R5eLiHRowYLWkyzE09gYvG/Y0Lq8NyZhMAtmdMvk2eruuKPr2erOOKN1nbbriEi/o+QojRSNzKO+TadV39REafGIduWS3pz4562+qan5oa8dne/ochGRuF58sevEKNnc4bbb4NxzUxtHTxQWtk5wTj65JSnqqE7b7yLS7wzgsfX0U5Cfwz0XzSQ3ksXQnEHkRrK456KZTBwztLk8ep9LtgXr5EayyM6yFEadvnqrWaLtfsVJR5EbySInbPxo+RcnFrSqb8D/+zelrc5b7PmMjgp1dL41aiQiQDB6cv/9wXusZ59NTTxtPfFEqiMQEel1mpChF8SbwQyCy+Sis6pFZ1Obc9QICobmsmnnXv7ywWfU1zdQsaeWklF5DB2Sw/iRubz035+xt7aeSYVDONhkjDkswq799YzMzWbH53VMLhxCk2WRlw2bq2ooHp7D69v2cqCunpF5g6k6UM+wnGz21zdxeP5gahudiMEn1XUUDIlQ2+gcOXQw1fVObjZsrjxAdjbMHDuM6npvnj1u34GDbPmshi+MOYwpR45onolucuEQ3t1Vzd7aOoqH51FV08CUwsMYFBlEQ30Dmyr3M2FUHvVulI4bRl5OhJqD9azb/jkjc7N575MDjB2Rw9GjD2Pttr2arU6z1UmG04QMHTvkfur66+EXv2j5vmQJ3Htv8PnFF4NL11LtP/4js0eORGTA0HOO+lB0trHYGcwamxx3p6EfXglnBBMOxCuLnUEP4Cuzi3hsbQWNTU59Y8ta2VnGkEi2ZmcT6SeUHHXskPqpjRvh2GPbl7/zTnAfDsDChakdQZoxA9avT93+RUS6Qc85OgSbd+2L+5ygkUMi/GXzp+zcW8tZ08YwoXBo8zODjsiP8PTbn7SaJiE6m1x/FS+VjpbFzqAH8MArH8XdRmOTs+9gAwC3Pr6ekyeO1oiJiEjUa691XB5Njv7wh5YJBObMgTFj4JFHgldhIVx6aeuJCl55BZ57Dk47DU48MUhsnnsumPb7/fdh+PBg4oMNG2DsWNixA44+GnbvhrPOCiZaeO89WLUKLrhAI0Yi0m8pOQLueOKtDv8jH+s/N+zqg2gGFs3OJiLSxty5iZW3nUBgzhz4x3+Mv+6VV/Y8rjlz4LLLer4dEZE0NmAnZKiqPsib2/ZQ/mFVQomRJIdmZxMRaWPq1OAeo1hLlrSMGomISNKk1ciRmZ0F/AzIBn7j7ncnYz/R+4QiWVnUNjQmYxf9VrfuOSor4rHyru850qiRiEgb994L110XXEo3d64SIxGRPpI2yZGZZQP/DJwJVABrzOwpd3+nN/dTVX2Q2x5fT219U1o/VHVYTjZTxhxGdb03z1YXfZ92RD7Z2dlEsmDTJ/s5Ij9C+Ud7OdjQyNhhOezcV8fIvEHsrmlonpVu7LDB7K5tZGJBHjWNMO2IfNyy+Ky6lj9vrmLc8DzOnnEEn1TXYd7Eho+rm2eAi84aFzsD3DNv7WTH3hrOmnZEq9nh2s7i9u3TJ1Oxu6Z5hrjS4hGMPGywZmcTEenK1KlKikRE+ljaJEfAXGCzu38AYGaPAOcDvZocVeyuCUaM0jQxij7rJt1ncCubUNB1JYJn+UQToNh1lBSJiIiISLpJp+RoHLAt5nsFcELbSmZ2LXAtwFFHHdXtnRSNzKO+6dASo2zgd1fPYeP2vfzXpkrGj8xlT21j8/OGYkd4PtpzkKlHHMZJR4/mrR2fNz+7J/qco+iseIdFsvig6kDz83k0miIiktl62k+JiEjqpFNylBB3vw+4D4LnR3R3/YL8HO65aCa3hvcc1Tc1MX5UHpt27W+uY0BOJKv5nplovXsumsmXJh/OlyYfzv89f1KvHZOIiPQfPe2nREQkddIpOdoOFMd8LwrLet15peM4eeLoVve9lH9YxQvvf8qsouGMHprb7p4ZjeiIiIiIiPRv5p4ef9Qys0HAe8DpBEnRGuBSd9/QyTqVwNYkhjUa+DSJ20+WTI0bFHsqZGrcoNhTIV7c4929MBXBpDv1Ux3K1LhBsadCpsYNij0VetRPpc3Ikbs3mNkS4A8Et/f8trPEKFwnqZ2xmZW7e1ky95EMmRo3KPZUyNS4QbGnQqbGnSrqp+LL1LhBsadCpsYNij0Vehp32iRHAO7+DPBMquMQEREREZGBJyvVAYiIiIiIiKQDJUeduy/VARyiTI0bFHsqZGrcoNhTIVPj7q8y9Xxkatyg2FMhU+MGxZ4KPYo7bSZkEBERERERSSWNHMmAYmanmNlLZrbXzD4zsxfNbE6q4wIws01mNrmDZQvN7AUz22dmlWb2vJmd19cxioiIiPRnSo5kwDCzYcBK4F5gFDAO+J/AwV7eT/YhrHMMkO3u78VZdjHwe+ABgud/jQHuAP6qh6GKiIiISAwlRzKQTAZw9+Xu3ujuNe7+rLuvj1Yws2vMbGM4QvOOmR0flk81s9VmtsfMNsSO2pjZMjP7lZk9Y2b7gflmNtbMHg9HeT40sxu6iO0c4szUaGYG/AT4X+7+G3ff6+5N7v68u18T1skysx+Y2VYz+8TMHjCz4eGyeWZW0WabW8zsjPDznWa2wsweDY/5dTObdQhtKyIiIpLxlBzJQPIe0Ghm95vZl81sZOxCM/sb4E7gCmAYcB5QZWYR4D+AZ4HDgeuBh8xsSszqlwJ3AUOBl8L6bxKMTp0O3GhmCzuJ7Wzg6TjlU4BiYEUn614VvuYDRwP5wC86qd/W+QQjU6OAh4EnwmMWERERGVCUHMmA4e6fA6cADvwrUGlmT5nZmLDK3wL3uPsaD2x2963AiQQJx93uXufuzxFcnndJzOafdPcX3b0JmAEUuvsPw/ofhPv7ary4zGwIMAdYHWdxQfi+s5NDuwz4ibt/4O7VwPeAr5pZos8xW+vuK9y9nmCUKjc8ZhEREZEBRcmRDCjuvtHdr3L3ImA6MBb4abi4GPjvOKuNBbaFiU/UVoJRoahtMZ/HA2PDS/D2mNke4O8J7hWK53TgJXePd+9TVfh+ZMdHxdgwntjYBnWyv7aaYw+PsSLcpoiIiMiAouRIBix3fxdYRpAkQZAkHBOn6g6g2Mxi/70cBWyP3VzM523Ah+4+IuY11N3P7iCUs4lzv1FoU7i9izo5lB0ECVlsbA3ALmA/MCS6IJwsorDN+sUxy7MIJn3Y0cn+RERERPolJUcyYJjZF8zsZjMrCr8XE1wa90pY5TfAd8xstgUmmtl44FXgAHCrmUXMbB7BTHGPdLCr14B9ZnabmeWZWbaZTe9kyvAvE/9+Izx4ENlNwO1m9nUzGxZOwHCKmUUfcrYc+Dszm2Bm+cD/Bh519waC+6xyzeyc8D6iHwA5bXYz28z+OrwM70aC2fteQURERGSAUXIkA8k+4ATg1XBWuVeAt4GbAdz99wSTKjwc1n0CGOXudQTJ0JeBT4FfAleEI0/tuHsjcC5QCnwYrvMbYHjbumY2Hah29486CtrdVwCLgKsJRnR2AT8Cngyr/BZ4EHgh3F8twaQRuPte4Lpw/9sJRpJazV4XbmcRsBv4GvDX4f1HIiIiIgOKBX+YFpFUMLNbgdHufmuK9n8nMNHdL0/F/kVERETSSaKzWYlIcmwhmPZbRERERFJMyZFICrn7Y6mOQUREREQCuqxOREREREQETcggIiIiIiICZPhldaNHj/aSkpJUhyEiMqCtXbv2U3dv+/wsQf2UiEg66E4/ldHJUUlJCeXl5akOQ0T6k8pK2LIFSkqgMMH/7x/KOumiF2I3s629GlM/on5KRCT1utNP6bI6EZGo5cth/Hg488zgffny5KyTLjI5dhERkSTI6AkZysrKXH+RE5FeUVkZJAg1NS1leXmwdWvHIyqHsk666MXYzWytu5f1coT9gvopEZHU604/pZEjEREILi0bPLh1WSQSlPfmOukik2MXERFJkoy+50hEBKC+vp6Kigpqa2sPfSN5efDooxA7mm4WlG/c2HvrpItDiD03N5eioiIikUgfBSkiItK3lByJSMarqKhg6NChlJSUYGaHvqEjjwwuKzMLkobx46GgoPfXSRfdiN3dqaqqoqKiggkTJvRxoCIiIn1DyZGIZLza2tqeJ0YQJAbDhkFdXXDJWSIjJIeyTrroRuxmRkFBAZWVlX0YoIiISN9SciQi/UKPE6OoSKT7Cc6hrJMuuhF7r7WxiIhImtKEDCIiGWTHjh08+OCDqQ5DRESkX1JyJCLSC+666y6mTZvGzJkzKS0t5dVXXwXgpz/9KQcOHOj29pYtW8aOHTtale3Zs4ebbrqJ008/vcv1y8vLueGGGxLe37p16zjppJOaj+HRRx/tdswiIiKZTpfViYj00Msvv8zKlSt5/fXXycnJ4dNPP6Wurg4IkqPLL7+cIUOGtFuvsbGR7OzsuNtctmwZ06dPZ+zYsc1lI0aM4JFHHkkoprKyMsrKEn/00JAhQ3jggQeYNGkSO3bsYPbs2SxcuJARI0YkvA0REZFMp5EjERmYKithzZrgvYd27tzJ6NGjycnJAWD06NGMHTuWn//85+zYsYP58+czf/58APLz87n55puZNWsWL7/8Mj/84Q+ZM2cO06dP59prr8XdWbFiBeXl5Vx22WWUlpZSU1PD2rVrOfXUU5uTlp07dwKwZs2a5tGqW265henTpwOwevVqzj33XAD279/P1Vdfzdy5cznuuON48skn2x3D5MmTmTRpEgBjx47l8MMP1+QLIiIy4Cg5EpGBZ/nyYNrqM88M3pcv79HmFixYwLZt25g8eTLXXXcdzz//PAA33HADY8eOZdWqVaxatQoIEpUTTjiBN998k1NOOYUlS5awZs0a3n77bWpqali5ciUXX3wxZWVlPPTQQ6xbt45BgwZx/fXXs2LFCtauXcvVV1/N97//fQC+/vWv8+tf/5p169Z1OAp11113cdppp/Haa6+xatUqbrnlFvbv39/h8bz22mvU1dVxzDHH9KhdREREMo2SIxEZWCorYfFiqKmBvXuD98WLezSClJ+fz9q1a7nvvvsoLCxk0aJFLFu2LG7d7OxsLrrooubvq1at4oQTTmDGjBk899xzbNiwod06mzZt4u233+bMM8+ktLSUH/3oR1RUVLBnzx727dvHSSedBMCll14ad5/PPvssd999N6WlpcybN4/a2lo++uijuHV37tzJ1772NX73u9+RlaUuQkREBhbdcyQiA8uWLcEzfWpqWsoikaC8sPCQN5udnc28efOYN28eM2bM4P777+eqq65qVy83N7d5hKe2tpbrrruO8vJyiouLufPOO6mtrW23jrszbdo0Xn755Vble/bsSSg2d+fxxx9nypQpndb7/PPPOeecc7jrrrs48cQTE9q2iIhIf6I/C4rIwFJSEjz0NFZ9fVB+iDZt2sT777/f/H3dunWMHz8egKFDh7Jv376460UTodGjR1NdXc2KFSual8WuN2XKFCorK5uTo/r6ejZs2MCIESMYOnRo88x4HU3WsHDhQu69917cHYA33nijXZ26ujouvPBCrrjiCi6++OJuHb+IiEh/oeRIRAaWwkJYuhTy8mDYsOB96dIejRpVV1dz5ZVXcuyxxzJz5kzeeecd7rzzTgCuvfZazjrrrOYJGWKNGDGCa665hunTp7Nw4ULmzJnTvOyqq67iG9/4BqWlpTQ2NrJixQpuu+02Zs2aRWlpKS+99BIAS5cu5ZprrqG0tJT9+/czfPjwdvu5/fbbqa+vZ+bMmUybNo3bb7+9XZ3HHnuMF154gWXLllFaWkppaSnr1q075DYRERHJRBb9S2ImKisr8/Ly8lSHISIptnHjRqZOndq9lSorg0vpSkp6lBilWnV1Nfn5+QDcfffd7Ny5k5/97GdJ21+8tjazte6e+LzhA4j6KRGR1OtOP6V7jkRkYCoszOikKOrpp5/mH/7hH2hoaGD8+PEdTgQhIiIiXVNyJCKSwRYtWsSiRYtSHYaIiEi/oHuORKRfyORLhDOF2lhERPo7JUcikvFyc3OpqqrSf96TyN2pqqoiNzc31aGIiIgkjS6rE5GMV1RUREVFBZU9eJCrdC03N5eioqJUhyEiIpI0SU+OzCwbKAe2u/u5ZjYBeAQoANYCX3P3OjPLAR4AZgNVwCJ335Ls+EQk80UiESZMmJDqMERERCTD9cVldd8GNsZ8/zHwT+4+EdgNLA7LFwO7w/J/CuuJiIiIiIj0iaQmR2ZWBJwD/Cb8bsBpQPQx8PcDF4Sfzw+/Ey4/PawvIiIiIiKSdMkeOfopcCvQFH4vAPa4e0P4vQIYF34eB2wDCJfvDeu3YmbXmlm5mZXr/gIREUk36qdERDJX0pIjMzsX+MTd1/bmdt39Pncvc/eywn7wAEcREelf1E+JiGSuZE7IcDJwnpmdDeQCw4CfASPMbFA4OlQEbA/rbweKgQozGwQMJ5iYQUREREREJOmSNnLk7t9z9yJ3LwG+Cjzn7pcBq4CLw2pXAk+Gn58KvxMuf8710BIREREREekjqXgI7G3ATWa2meCeoqVh+VKgICy/CfhuCmITEREREZEBqk8eAuvuq4HV4ecPgLlx6tQCf9MX8YiIiIiIiLSVipEjERERERGRtKPkSEREREREBCVHIiIiIiIigJIjERERERERQMmRiIiIiIgIoORIREREREQE6EZyZGZ5ZjYlmcGIiIiIiIikSkLJkZn9FbAO+M/we6mZPZXEuERERERERPpUoiNHdxI8uHUPgLuvAyYkJSIREREREZEUSDQ5qnf3vW3KvLeDERERERERSZVBCdbbYGaXAtlmNgm4AXgpeWGJiIiIiIj0rURHjq4HpgEHgYeBvcCNSYpJRERERESkz3U5cmRm2cDT7j4f+H7yQ5J+pbIStmyBkhIoLGz/PV6dtjZuhNdeg7lzYerU1uvk50N1dcv7rl2wZg0ccQR8/DHMmQNjxrTe9kMPwWOPwVe+Apdd1n5b770Hq1bBBRfAuee2jqGgAKqqWmKJlh84AC++CLNnB8s2b4aJE2Hw4JZ9xzsOgJUrYdkyKC6G009vvf2O2qayEt54I/hcVxccc/RYo8fRts3blidyvrpTJ1peVxccf9vjFBEREUl37t7lC/gTMDyRun35mj17tksae/hh97w89+HDg/clS1p/f/jh9nUefrj1NpYscYeW15IlLevk5QVlgwe3rtP2lZXVsu2iotbLRo1qva22rxkz2scQfU2f3vl+wT0SCbZ95pntj8O9822ceWb8tnn44Y6POSsreI8eU7TNo8cX/dy2neOdr+7UiZZHIvGPU/o1oNzToE9Ix5f6KRGR1OtOP2VB/c6Z2ZPAccAfgf0xidUNScnYElRWVubl5eWpDEE6UlkJ48dDTU3HdXJzwax1nbw82Lq1ZaTl2GPjr1db2/2YBg2Chobur5csv/wlXHdd4vXz8mDt2mB0qrN2TXRb0XaG+Ocr0TpdxfTOOxpB6ufMbK27l6U6jnSkfkpEJPW6008les/RvwG3Ay8Aa2NeIvFt2RJcUtaZ7GzIavMjGIkE60JwCVpvSuAPAX1q+fLu1Y9EgjZp22aHIradIf75SrTOa691fq57+zyKiIiIJElCs9W5+/1mNhiYHBZtcvf65IUlGa+kJLj3pDONjcHIUaz6+mBdCO5Z6U1t95Vql1wCf/5z4vXr64M2aWrq+b5j2xnin69E68yd2/m57u3zKCIiIpIkCf0J2szmAe8D/wz8EnjPzL6UvLAk4xUWwtKlwWVXw4YF70uWtP7+29+2r7N0actlXFOnBuvEWrIkWC8vL7i8DroeoTIL6j/wQDDpQaxRo4JleXnx150xo30Mscu6EokE216woP1xfPObnW9jwYL2bTN1avDe0TFHR5Vyc1u3ebStosca284Q/3wlWicaU15ecLxtj1OX1ImIiEiGSPSeo7XApe6+Kfw+GVju7rOTHF+ndC13BtBsdZqtTvo93XPUMfVTIiKp151+KtHkaL27z+yqrK+p0xERST0lRx1TPyUiknrd6acSuucIKDez3wD/J/x+GaDf9iIiIiIi0m8kmhx9E/gWEJ26+88E9x6JiIiIiIj0C4kmR4OAn7n7TwDMLBvISVpUIiIiIiIifSzRB6b8CYidzisP+K/eD0dERERERCQ1Ek2Oct29Ovol/DwkOSGJiIiIiIj0vUSTo/1mdnz0i5mVATWdrWBmxWa2yszeMbMNZvbtsHyUmf3RzN4P30eG5WZmPzezzWa2PnZ/IiIiIiIiyZboPUffBn5vZjvC70cCi7pYpwG42d1fN7OhwFoz+yNwFfAnd7/bzL4LfBe4DfgyMCl8nQD8KnwXERERERFJukRHjiYAxxHMWvdHYBPQ6QOS3H2nu78eft4HbATGAecD94fV7gcuCD+fDzzggVeAEWZ2ZOKHIiIiIiIicugSTY5ud/fPgRHAfIJpvH+V6E7MrIQguXoVGOPuO8NFHwNjws/jgG0xq1WEZW23da2ZlZtZeWVlZaIhiIiI9An1UyIimSvR5KgxfD8H+Fd3fxoYnMiKZpYPPA7cGCZYzdzd6WIEqi13v8/dy9y9rLCwsDurioiIJJ36KRGRzJVocrTdzH5NcJ/RM2aWk8i6ZhYhSIwecvd/C4t3RS+XC98/ie4DKI5ZvSgsExERERERSbpEk6OvAH8AFrr7HmAUcEtnK5iZAUuBjdGHx4aeAq4MP18JPBlTfkU4a92JwN6Yy+9ERERERESSKqHZ6tz9APBvMd93Al0lLicDXwPeMrN1YdnfA3cDj5nZYmArQeIF8AxwNrAZOAB8PbFDEBERERER6blEp/LuNnf/C2AdLD49Tn0HvpWseERERERERDqTtORIelFlJWzZAvn5UF3d/r2kJKi3ZQvU1cHmzVBQAFVVMGgQvPcezJkDY8bArl2wZg24w5tvwqxZUF4O27fDZZfB/PlB/VWrYPjwYFsjR8IHHwTbfv/9YNuffRasW1gIq1fDWWfBt74FjzwCK1dCUVFQZ9QoqKgItrFzJxx5ZPD96KNh3rwghrFjYccOmDgR9u6Fhoag/LTTYOZMmDsXli+HRx8Nyk48Mag7eHBLrPPnw+TJLccXPd66Onj++aB9LrwQpk6FF1+EZ59tXSe2zebOhdGj47d5SUlwzD05jz3ZhoiIiIgkjQUDNpmprKzMy8vLUx1Gci1fDosXB59raiASgfr6IDGoq4O8PGhsDJIds6BMOlZcDNu2dV0vOzto49g2z8sLli1dCpdc0r39Rs9j9LwdyjZE0pSZrXX3slTHkY4GRD8lIpLmutNPJTohg6RCZWXwH+qamuAFwX/SoSUJqqkJPtfXKzFKRCKJEQQJZ9s2j56HxYuDc5Oo2PO4d++hbUNEREREkk7JUTrbsiUYaZD0EokE5yZR8c5jd7chIiIiIkmn5CidlZRoNCgd1de33OeViHjnsbvbEBEREZGkU3KUzgoLg3tT8vJa7ncZFM6hER2JyM0NPkciGmVKRHFx13UguOeobZtHz8PSpd2bUCH2PA4bdmjbEBEREZGk02x16e6SS+CMMzRbXabPVhd7HjVbnYiIiEha0mx1IiLSI5qtrmPqp0REUk+z1YmIiIiIiHSTkiMRERERERGUHImIiIiIiACakOHQVFa2vrF+40Z47bWWSQLy8+Gtt4LJAY4/vvXEAZEIbNgQTAaQn98yMUJ00gN3eOONYFazI48MJgoYOhT27YOyMjjllKD+K68E+z94MJj04N13g8kF5s8P1snLg02bICcniHXatGB/ZkG8U6cG+5o1q+XBqKNGBZMZTJsWTDU9eTLs3x+8NzS0TFhQUAAffhjsb8aM+BMWtG2j6CQICxbAySfHb8e230VERERE+pAmZOiu5cth8eIg4amrC5KVP/6xZXl2NjQ29m1MqRZti+jU14sXB1NVR8uPOQbefrul/oIFcNVVrdux7TpLlwYzvIlI2tOEDB3ThAwiIqnXnX5KyVF3VFbC+PFQU9N3++yvoklQR/LyYOtWjSCJZAAlRx1TciQiknqarS5ZtmzRg1b7SiQStLeIiIiISB9RctQdJSWdj3ZI76mvb3m4rYiIiIhIH1By1B2FhcG9MHl5wYQJeXnB/TOxsrNTE1sqRUfTcnODNlmypHUbzZjRuv6CBbBsWes6bddZulSX1ImIiIhIn9JsdR2Jzq42Zw48+WQw01xZWTAr23e+Azt2wOzZMGRIMNPc6tVw4onB7G9btwbrmMGXvhTMClddHcxSN2RIMOPbuHHBxA1HHx3MCOcO778fzBj30UeZP1vdHXd0PVvdGWe0rtN2HRERERGRPqQJGeJZsKD1DHR9bcYMWL8+dfsXEekGTcjQMU3IICKSepqQoSdefDG1iREEz0hauTK1MYiIiIiIDDADNznauBHuvz94j/Xss6mJp60nnkh1BCIiIiIiA8rATI6uvx6OPTZ4EOmxxwbfo9pOsJAqF1yQ6ghERERERAaUgZccbdwIv/hF67Jf/KJlBOnkk1OfIM2YAeeem9oYREREREQGmIE3W91rr3VcPnVq8PkPf+h8trq2s7i98go89xycdlowY9369fDoo8GDTM86K5j5LRIJZqsbOzaY6e7oo2H37mB5WRm8916wjwsuUGIkIiIiIpICA2+2uo0bg0vp2nrnnZbkSEREEqbZ6jqm2epERFJPs9V1ZurU4IGjsZYsUWIkIiIiIjLApVVyZGZnmdkmM9tsZt9N2o7uvTcYKVq2LHi/996k7UpERERERDJD2txzZGbZwD8DZwIVwBoze8rd30nKDqdO1WiRiIiIiIg0S6eRo7nAZnf/wN3rgEeA81Mck4iIiIiIDBDplByNA7bFfK8Iy1oxs2vNrNzMyisrK/ssOBERkUSonxIRyVzplBwlxN3vc/cydy8rLCxMdTgiIiKtqJ8SEclc6ZQcbQeKY74XhWUiIiIiIiJJlzbPOTKzQcB7wOkESdEa4FJ339DJOpXA1iSGNRr4NInbT5ZMjRsUeypkatyg2FMhXtzj3V1DJHGon+pQpsYNij0VMjVuUOyp0KN+Km1mq3P3BjNbAvwByAZ+21liFK6T1M7YzMoz8cGGmRo3KPZUyNS4QbGnQqbGnSrqp+LL1LhBsadCpsYNij0Vehp32iRHAO7+DPBMquMQEREREZGBJ53uORIREREREUkZJUeduy/VARyiTI0bFHsqZGrcoNhTIVPj7q8y9Xxkatyg2FMhU+MGxZ4KPYo7bSZkEBERERERSSWNHImIiIiIiKDkSEREREREBFByBICZFZvZKjN7x8w2mNm3w/I7zWy7ma0LX2enOtZ4zGyLmb0Vxlgelo0ysz+a2fvh+8hUxxnLzKbEtOs6M/vczG5M1zY3s9+a2Sdm9nZMWdw2tsDPzWyzma03s+NTF3mHsf8/ZvZuGN+/m9mIsLzEzGpi2v9fUhY4Hcbe4c+ImX0vbPdNZrYwNVF3GPejMTFvMbN1YXm6tXlHvw8z4ue9v1I/lRqZ1Fepn0oN9VN9L+n9lLsP+BdwJHB8+HkowcNojwXuBL6T6vgSiH8LMLpN2T3Ad8PP3wV+nOo4O4k/G/gYGJ+ubQ58CTgeeLurNgbOBv4/wIATgVfTMPYFwKDw849jYi+JrZfqVwexx/0ZCf/NvgnkABOA/way0yXuNsv/EbgjTdu8o9+HGfHz3l9f6qdS/0r3vkr9VFrFrn4qubEntZ/SyBHg7jvd/fXw8z5gIzAutVH12PnA/eHn+4ELUhdKl04H/tvdk/kU+R5x9xeAz9oUd9TG5wMPeOAVYISZHdkngcYRL3Z3f9bdG8KvrwBFfR5YAjpo946cDzzi7gfd/UNgMzA3acF1orO4zcyArwDL+zSoBHXy+zAjft77K/VTaSGt+yr1U6mhfqrvJbufUnLUhpmVAMcBr4ZFS8IhuN+m45B/yIFnzWytmV0blo1x953h54+BMakJLSFfpfU/wExoc+i4jccB22LqVZDe/4m5muAvKlETzOwNM3vezL6YqqC6EO9nJFPa/YvALnd/P6YsLdu8ze/D/vLznvHUT6VMJvZV/eXfrfqpvjWg+yklRzHMLB94HLjR3T8HfgUcA5QCOwmGGNPRKe5+PPBl4Ftm9qXYhR6MKablnO1mNhg4D/h9WJQpbd5KOrdxZ8zs+0AD8FBYtBM4yt2PA24CHjazYamKrwMZ+TMS4xJa/wcrLds8zu/DZpn6894fqJ9Kjf7QV6V7G3dE/VRKDOh+SslRyMwiBA38kLv/G4C773L3RndvAv6VFA19dsXdt4fvnwD/ThDnruiQYfj+Seoi7NSXgdfdfRdkTpuHOmrj7UBxTL2isCytmNlVwLnAZeEvEcKh/qrw81qC66EnpyzIODr5GUn7djezQcBfA49Gy9KxzeP9PiTDf977A/VTKZWpfVVG/7tVP9X31E8pOQKar61cCmx095/ElMdej3gh8HbbdVPNzA4zs6HRzwQ3ML4NPAVcGVa7EngyNRF2qdVfJzKhzWN01MZPAVeEs6OcCOyNGeZNC2Z2FnArcJ67H4gpLzSz7PDz0cAk4IPURBlfJz8jTwFfNbMcM5tAEPtrfR1fF84A3nX3imhBurV5R78PyeCf9/5A/VTKZWpflbH/btVPpYz6KU+DWSdS/QJOIRh6Ww+sC19nAw8Cb4XlTwFHpjrWOLEfTTDzyZvABuD7YXkB8CfgfeC/gFGpjjVO7IcBVcDwmLK0bHOCTnEnUE9wrerijtqYYDaUfyb4y8pbQFkaxr6Z4Prb6M/7v4R1Lwp/jtYBrwN/lYaxd/gzAnw/bPdNwJfTKe6wfBnwjTZ1063NO/p9mBE/7/31pX4qpfFnRF+lfiqtYlc/ldzYk9pPWbiSiIiIiIjIgKbL6kRERERERFByJCIiIiIiAig5EhERERERAZQciYiIiIiIAEqOREREREREACVHIiIiIiIigJIjERERERERQMmRSFKY2RVmtt7M3jSzB82sxMyeC8v+ZGZHhfWWmdnFMetVh+/zzOwFM3vazDaZ2b+Ymf69ioiIiCSR/rMl0svMbBrwA+A0d58FfBu4F7jf3WcCDwE/T2BTc4HrgWOBY4C/Tk7EIiIiIgJKjkSS4TTg9+7+KYC7fwacBDwcLn8QOCWB7bzm7h+4eyOwPMF1REREROQQKTkSSa0Gwn+H4WVzg2OWeZu6bb+LiIiISC9SciTS+54D/sbMCgDMbBTwEvDVcPllwJ/Dz1uA2eHn84BIzHbmmtmEMGlaBPwlyXGLiIiIDGiDUh2ASH/j7hvM7C7geTNrBN4guHfod2Z2C1AJfD2s/q/Ak2b2JvCfwP6YTa0BfgFMBFYB/95HhyAiIiIyIJm7rtQRSTdmNg/4jrufm+JQRERERAYMXVYnIiIiIiKCRo5EREREREQAjRyJiIiIiIgASo5EREREREQAJUciIiIiIiKAkiMRERERERFAyZGIiIiIiAgA/z/VvdPc+rzWDgAAAABJRU5ErkJggg==\n", "text/plain": ["
"]}, "metadata": {"needs_background": "light"}, "output_type": "display_data"}], "source": ["import matplotlib.pyplot as plt\n", "fig, ax = plt.subplots(2, 2, figsize=(14, 4), sharey=True, sharex=True)\n", "df.plot(x='coup', y='score', kind='scatter', title=\"Score / Coup\", label=\"Strat\u00e9gie 1\", ax=ax[0, 0])\n", "df2.plot(x='coup', y='score', kind='scatter', title=\"Score / Coup\", label=\"Strat\u00e9gie 2\", ax=ax[1, 0], color='red');\n", "df2.plot(x='coup', y='score', kind='scatter', title=\"Score / Coup\", label=\"Strat\u00e9gie 2\", ax=ax[0, 1], color='red');"]}, {"cell_type": "markdown", "id": "0f4e3858", "metadata": {}, "source": ["La strat\u00e9gie 2 para\u00eet meilleure : jouer al\u00e9atoire dans toutes les directions est plus efficace que dans deux directions."]}, {"cell_type": "code", "execution_count": 19, "id": "fa6d1750", "metadata": {}, "outputs": [], "source": []}], "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.9.5"}}, "nbformat": 4, "nbformat_minor": 5}