Notebook originel: cc251003_magic.ipynb
CC-251003 Science des données🔗
Consignes🔗
Créez un répertoire CC251003_Nom_Prenom/ dans lequel vous travaillerez, et où sera stocké le package python en développement, selon les instructions ci-dessous.
Vous devez alors mettre ce répertoire sous contrôle git sur un projet dédié sur le serveur https://gitlab.in2p3.fr, et en transmettre l’adresse à y.copin@ipnl.in2p3.fr.
Si, par manque de temps ou de connaissance, vous ne pouvez pas créer un dépôt git, envoyez par mail la distribution source du package voir ci-dessous) à y.copin@ipnl.in2p3.fr (cette solution sera pénalisée dans la notation).
Dans tous les cas, vous devez envoyer quelque chose!
Carré magique🔗
Un carré magique d’ordre n est un tableau carré \(n × n\) dans lequel on écrit une et une seule fois les nombres entiers de 1 à \(n^2\), de sorte que la somme des n nombres de chaque ligne, colonne ou diagonale principale soit constante.
Pour les carrés magiques d’ordre impair, on dispose de l’algorithme suivant — (i,j) désignant la case de la ligne i, colonne j du carré, avec une indexation « naturelle » commençant à 1:
initialisation: la case \((n, (n + 1)/2)\) contient 1 ;
itération: si la case \((i, j)\) contient la valeur \(k\), alors on place la valeur \(k+1\) dans la case \((i + 1, j + 1)\) si cette case est vide, ou dans la case \((i - 1, j)\) sinon. On respecte la règle du carré « torique » (modulo n).
Écrire une fonction
empty_magic_square(n)qui retourne un tableau 2D (liste de listes) \(n×n\) de 0, en utilisant une double liste en compréhension.
[1]:
def empty_magic_square(n):
"""
Retourne un tableau 2D (liste de listes) n×n de 0.
Utiliser une double liste en compréhension.
"""
return [[0]]
Écrire une fonction
init_magic_square(square)qui initialise l’algorithme en remplissant (sur place) la case 1 du tableausquare(supposé être \(n×n\)), et en retournant les coordonnées de cette case (indexation à 1).
[2]:
def init_magic_square(square):
"""
Initialise l'algorithme en remplissant (sur place) la case '1',
et en retournant les coordonnées de la case (indexation à 1).
square est supposé être un tableau n×n.
"""
return 0, 0
Écrire une fonction
iterate_magic_square(square, i, j, k)qui itère l’algorithme en remplissant (sur place) la case \(k+1\) du tableausquare(supposé être \(n×n\)), et en retournant les coordonnées de cette case (indexation à 1), en supposant que la case \(k\), de coordonnées \((i, j)\), est déjà remplie.
[3]:
def iterate_magic_square(square, i, j, k):
"""
Itère l'algorithme en remplissant (sur place) la case 'k+1',
et en retournant les coordonnées de la case (indexation à 1),
en supposant que la case 'k', de coordonnées (i, j), est déjà remplie.
square est supposé être un tableau n×n.
"""
return 0, 0
Écrire une fonction
magic_square(n)qui implémente l’algorithme en retournant le carré magique d’ordre \(n\) (tableau \(n×n\)). Elle doit générer une exceptionAssertionErrorsi l’ordre \(n\) n’est pas impair.
[4]:
def magic_square(n):
"""
Implémentation de l'algo.
* vérifier que l'ordre est impair (assert)
* retourner le carré magique totalement rempli (tableau n×n)
"""
return [[1]]
Écrire une fonction
str_magic_square(n)convertissant un carré magique en une chaîne de caractères correctement formattée, p.ex.
>>> print(str_magic_square(5))
11 18 25 2 9
10 12 19 21 3
4 6 13 20 22
23 5 7 14 16
17 24 1 8 15
[5]:
def str_magic_square(square):
"""
Retourne une représentation str du carré magique.
Utiliser la méthode str.join pour construire la chaîne
à partir des lignes et des cellules, et
f"{val:>{m}d}" pour afficher l'entier val aligné
à droite sur m caractères.
"""
return "1"
Packaging🔗
Créez un package
magic_nom_prenomconstitué du seul modulemagic.pyincluant l’ensemble des fonctions précédemment définies (ne pas ajouter la section de tests), avec l’arborescence suivante:CC251003_Nom_Prenom/ ├── magic_nom_prenom │ ├── magic.py │ └── __init__.py ├── pyproject.toml └── ...
En utilisant les fonctions définies à la partie précédente, ajoutez un fichier
__main__.pyà votre package pour pouvoir exécuter:$ python -m magic 5 11 18 25 2 9 10 12 19 21 3 4 6 13 20 22 23 5 7 14 16 17 24 1 8 15
Ajoutez un point d’entrée
magicsquareà votre package pour pouvoir exécuter:$ magicsquare 5 11 18 25 2 9 10 12 19 21 3 4 6 13 20 22 23 5 7 14 16 17 24 1 8 15
(Vous pouvez créer de nouvelles fonctions intermédiaires si nécessaire.)
Finalement,
commit/pushtoutes vos modifications sur votre répo centralgit, et envoyer l’adresse de ce répo à y.copin@ipnl.in2p3.fr.Si vous n’avez pas réussi à stocker votre package sous
git, générer une distribution des sources de votre package avec la commande$ python -m build
et envoyer l’archive correspondante (générée sous
dist/) à y.copin@ipnl.in2p3.fr.Si vous n’avez pas non plus réussi à configurer votre package, générer manuellement une archive de votre package:
$ tar cvzf CC251003_NOM_Prenom.tgz CC251003_NOM_Prenom/
et envoyer le tarball.
[6]:
import unittest
class TestNotebook(unittest.TestCase):
def test_01_empty(self):
self.assertEqual(empty_magic_square(3), [[0] * 3] * 3)
def test_02_init(self):
sq = empty_magic_square(3)
i, j = init_magic_square(sq)
self.assertEqual((i, j), (3, 2))
self.assertEqual(sq, [[0, 0, 0], [0, 0, 0], [0, 1, 0]])
def test_03_iterate(self):
sq = [[0, 0, 0], [0, 0, 0], [0, 1, 0]]
i, j = iterate_magic_square(sq, 3, 2, 1)
self.assertEqual((i, j), (1, 0))
self.assertEqual(sq, [[0, 0, 2], [0, 0, 0], [0, 1, 0]])
i, j = iterate_magic_square(sq, 1, 0, 2)
self.assertEqual((i, j), (2, 1))
self.assertEqual(sq, [[0, 0, 2], [3, 0, 0], [0, 1, 0]])
def test_04_all(self):
self.assertEqual(magic_square(3), [[4, 9, 2], [3, 5, 7], [8, 1, 6]])
with self.assertRaises(AssertionError):
magic_square(4)
def test_05_str(self):
self.assertEqual(
str_magic_square(magic_square(3)),
'4 9 2\n3 5 7\n8 1 6')
self.assertEqual(
str_magic_square(magic_square(5)),
'11 18 25 2 9\n10 12 19 21 3\n 4 6 13 20 22\n23 5 7 14 16\n17 24 1 8 15')
unittest.main(argv=[''], verbosity=2, exit=False)
test_01_empty (__main__.TestNotebook) ... FAIL
test_02_init (__main__.TestNotebook) ... FAIL
test_03_iterate (__main__.TestNotebook) ... FAIL
test_04_all (__main__.TestNotebook) ... FAIL
test_05_str (__main__.TestNotebook) ... FAIL
======================================================================
FAIL: test_01_empty (__main__.TestNotebook)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_568061/3897433415.py", line 6, in test_01_empty
self.assertEqual(empty_magic_square(3), [[0] * 3] * 3)
AssertionError: Lists differ: [[0]] != [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
First differing element 0:
[0]
[0, 0, 0]
Second list contains 2 additional elements.
First extra element 1:
[0, 0, 0]
- [[0]]
+ [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
======================================================================
FAIL: test_02_init (__main__.TestNotebook)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_568061/3897433415.py", line 11, in test_02_init
self.assertEqual((i, j), (3, 2))
AssertionError: Tuples differ: (0, 0) != (3, 2)
First differing element 0:
0
3
- (0, 0)
+ (3, 2)
======================================================================
FAIL: test_03_iterate (__main__.TestNotebook)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_568061/3897433415.py", line 17, in test_03_iterate
self.assertEqual((i, j), (1, 0))
AssertionError: Tuples differ: (0, 0) != (1, 0)
First differing element 0:
0
1
- (0, 0)
? ^
+ (1, 0)
? ^
======================================================================
FAIL: test_04_all (__main__.TestNotebook)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_568061/3897433415.py", line 24, in test_04_all
self.assertEqual(magic_square(3), [[4, 9, 2], [3, 5, 7], [8, 1, 6]])
AssertionError: Lists differ: [[1]] != [[4, 9, 2], [3, 5, 7], [8, 1, 6]]
First differing element 0:
[1]
[4, 9, 2]
Second list contains 2 additional elements.
First extra element 1:
[3, 5, 7]
- [[1]]
+ [[4, 9, 2], [3, 5, 7], [8, 1, 6]]
======================================================================
FAIL: test_05_str (__main__.TestNotebook)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_568061/3897433415.py", line 29, in test_05_str
self.assertEqual(
AssertionError: '1' != '4 9 2\n3 5 7\n8 1 6'
- 1
+ 4 9 2
3 5 7
8 1 6
----------------------------------------------------------------------
Ran 5 tests in 0.005s
FAILED (failures=5)
[6]:
<unittest.main.TestProgram at 0x7f7ce98f3700>
Cette page a été générée à partir de
cc251003_magic.ipynb.