Carrés semi-magiques

Nous travaillons dans cet exercice sur des tableaux carrés d'entiers positifs.

Nous appelons « carré d'ordre \(n\) » un tableau de \(n\) lignes et \(n\) colonnes dont chaque case contient un entier positif.

Carré semi-magique

Un carré est dit « semi-magique » lorsque les sommes des éléments situés sur chaque ligne, chaque colonne sont égales. Cette somme est appelée constante magique ou densité du carré semi-magique.

Exemples avec trois carrés

1 7
7 1

carre_2 est semi-magique car la somme de chaque ligne et de chaque colonne est égale à 8.

3 4 5
4 4 4
5 4 3

carre_3 est semi-magique car la somme de chaque ligne et de chaque colonne est égale à 12.

2 9 4
7 0 3
6 1 8

carre_3_bis n'est pas semi-magique car la somme de la première ligne est égale à 15 alors que celle de la deuxième ligne est égale à 10.

La classe Carre ci-après contient des méthodes qui permettent de manipuler des carrés.

  • La méthode __init__ permet de créer un carré sous forme d'un tableau à deux dimensions à partir d'un p-uplet d'entiers nombres. Nous remarquons que l'ordre du carré créé est la racine carrée de la longueur du p-uplet passé en paramètre. Par exemple avec un p-uplet de taille 4, on crée un carré d'ordre 2, avec un de taille 9, un carré d'ordre 3.

  • La méthode affiche permet d'afficher le carré créé.

Exemples

🐍 Console Python
>>> nombres_3 = (2, 9, 4, 7, 0, 3, 6, 1, 8)
>>> carre_3_bis = Carre(nombres_3)
>>> carre_3_bis.affiche()
[2, 9, 4]
[7, 0, 3]
[6, 1, 8]
  • La méthode somme_ligne prend en paramètre un entier i et renvoie la somme des éléments de la ligne i du carré.

Exemple

🐍 Console Python
>>> carre_3_bis.somme_ligne(0)
15
  • La méthode somme_colonne prend en paramètre un entier j et renvoie la somme des éléments de la colonne j du carré.

Exemple

🐍 Console Python
>>> carre_3_bis.somme_colonne(1)
10
  • La méthode est_semi_magique renvoie True si le carré est semi magique, False sinon.

Exemples

🐍 Console Python
>>> carre_2.est_semi_magique()
True
>>> carre_3.est_semi_magique()
True
>>> carre_3_bis.est_semi_magique()
False

Compléter le code ci-dessous, puis le tester sur les carrés carre_2, carre_3 et carre_3_bis.

###
# Testsbksl-nlbksl-nlnombrespy-und2 = (1, 7, 7, 1)bksl-nlnombrespy-und3 = (3, 4, 5, 4, 4, 4, 5, 4, 3)bksl-nlnombrespy-und3py-undbis = (2, 9, 4, 7, 0, 3, 6, 1, 8)bksl-nlnombrespy-und4 = (1, 2, 3, 4, 11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34)bksl-nlcarrepy-und2 = Carre(nombrespy-und2)bksl-nlcarrepy-und3 = Carre(nombrespy-und3)bksl-nlcarrepy-und3py-undbis = Carre(nombrespy-und3py-undbis)bksl-nlcarrepy-und4 = Carre(nombrespy-und4)bksl-nlassert carrepy-und2.estpy-undsemipy-undmagique() is Truebksl-nlassert carrepy-und3.estpy-undsemipy-undmagique() is Truebksl-nlassert carrepy-und3py-undbis.estpy-undsemipy-undmagique() is Falsebksl-nlassert carrepy-und4.estpy-undsemipy-undmagique() is Falsebksl-nlbksl-nlbksl-nl# Autres testsbksl-nldef creepy-undmatrice(nombres):bksl-nl n = int(sqrt(len(nombres)))bksl-nl tableau = [[nombres[j + i py-str n] for j in range(n)] for i in range(n)]bksl-nl return tableaubksl-nlbksl-nlbksl-nlnombrespy-und5 = (1, 4, 14, 15, 13, 16, 2, 3, 8, 5, 11, 10, 12, 9, 7, 6)bksl-nlnombrespy-und6 = (1, 4, 14, 15, 13, 16, 2, 3, 8, 5, 11, 10, 12, 9, 7, 5)bksl-nlnombrespy-und7 = (2, 4, 14, 15, 13, 16, 2, 3, 8, 5, 11, 10, 12, 9, 7, 6)bksl-nlnombrespy-und8 = (1, 2, 3, 1, 2, 3, 1, 2, 3)bksl-nlnombrespy-und9 = (1, 1, 1, 2, 2, 2, 3, 3, 3)bksl-nlcarrepy-und5 = Carre(nombrespy-und5)bksl-nlcarrepy-und6 = Carre(nombrespy-und6)bksl-nlcarrepy-und7 = Carre(nombrespy-und7)bksl-nlcarrepy-und8 = Carre(nombrespy-und8)bksl-nlcarrepy-und9 = Carre(nombrespy-und9)bksl-nlbksl-nlfor nombres in [bksl-nl nombrespy-und2,bksl-nl nombrespy-und3,bksl-nl nombrespy-und4,bksl-nl nombrespy-und5,bksl-nl nombrespy-und6,bksl-nl nombrespy-und7,bksl-nl nombrespy-und8,bksl-nl nombrespy-und9,bksl-nl]:bksl-nl assert Carre(nombres).tableau == creepy-undmatrice(nombres), "méthode py-undpy-undinitpy-undpy-und fausse"bksl-nlbksl-nlassert carrepy-und5.estpy-undsemipy-undmagique() is Truebksl-nlassert carrepy-und6.estpy-undsemipy-undmagique() is Falsebksl-nlassert carrepy-und7.estpy-undsemipy-undmagique() is Falsebksl-nlassert carrepy-und8.estpy-undsemipy-undmagique() is False, "faux pour (1, 2, 3, 1, 2, 3, 1, 2, 3)"bksl-nlassert carrepy-und9.estpy-undsemipy-undmagique() is False, "faux pour (1, 1, 1, 2, 2, 2, 3, 3, 3)"bksl-nlbksl-nlbksl-nl# autres tests de Franckbksl-nlbksl-nlfrom random import randrangebksl-nlbksl-nln = 10bksl-nlbase = [randrange(10py-strpy-str9) for py-und in range(n)] py-str 2bksl-nlnombres = []bksl-nlfor i in range(n):bksl-nl nombres.extend(base[i : i + n])bksl-nlbksl-nlgrospy-undtest = tuple(nombres)bksl-nlassert Carre(grospy-undtest).estpy-undsemipy-undmagique() == True, "Erreur avec un gros test"bksl-nlbksl-nltruc = randrange(-(10py-strpy-str8), 10py-strpy-str8)bksl-nltruc = 42 if not truc else trucbksl-nlbksl-nlfor i in range(n):bksl-nl for j in range(n):bksl-nl nombres[i py-str n + j] += trucbksl-nl grospy-undtest = tuple(nombres)bksl-nl assert Carre(grospy-undtest).estpy-undsemipy-undmagique() == False, "Erreur avec un gros test"bksl-nl nombres[i py-str n + j] -= trucbksl-nlbksl-nlfor kpy-unde in range(n - 1):bksl-nl for kpy-unds in range(kpy-unde + 1, n):bksl-nlbksl-nl for i in range(n):bksl-nl nombres[n py-str i + kpy-unds] += trucbksl-nl nombres[n py-str i + kpy-unde] -= trucbksl-nl grospy-undtest = tuple(nombres)bksl-nl assert (bksl-nl Carre(grospy-undtest).estpy-undsemipy-undmagique() == Falsebksl-nl ), "Erreur, il faut aussi vérifier les colonnes"bksl-nlbksl-nl nombres[n py-str i + kpy-unds] -= trucbksl-nl nombres[n py-str i + kpy-unde] += trucbksl-nlbksl-nl for j in range(n):bksl-nl nombres[n py-str kpy-unds + j] += trucbksl-nl nombres[n py-str kpy-unde + j] -= trucbksl-nl grospy-undtest = tuple(nombres)bksl-nl assert (bksl-nl Carre(grospy-undtest).estpy-undsemipy-undmagique() == Falsebksl-nl ), "Erreur, il faut aussi vérifier les lignes"bksl-nlbksl-nl 5/5

from math import sqrtbksl-nlbksl-nlclass Carre:bksl-nl def py-undpy-undinitpy-undpy-und(self, nombres):bksl-nl self.ordre = int(sqrt(len(nombres)))bksl-nl self.tableau = [[nombres[j + ipy-strself.ordre] for ... in range(self.ordre)] for ... in range(self.ordre)]bksl-nlbksl-nl def affiche(self):bksl-nl '''Affiche un carré'''bksl-nl for ligne in self.tableau:bksl-nl print(ligne)bksl-nlbksl-nl def sommepy-undligne(self, i):bksl-nl '''Calcule la somme des valeurs de la ligne i'''bksl-nl ...bksl-nlbksl-nl def sommepy-undcolonne(self, j):bksl-nl '''Calcule la somme des valeurs de la colonne j'''bksl-nl ...bksl-nlbksl-nl def estpy-undsemipy-undmagique(self):bksl-nl sommepy-undcommune = self.sommepy-undligne(0)bksl-nl ...bksl-nl bksl-nlbksl-nl# Testsbksl-nlbksl-nlnombrespy-und2 = (1, 7, 7, 1)bksl-nlnombrespy-und3 = (3, 4, 5, 4, 4, 4, 5, 4, 3)bksl-nlnombrespy-und3py-undbis = (2, 9, 4, 7, 0, 3, 6, 1, 8)bksl-nlnombrespy-und4 = (1, 2, 3, 4, 11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34)bksl-nlcarrepy-und2 = Carre(nombrespy-und2)bksl-nlcarrepy-und3 = Carre(nombrespy-und3)bksl-nlcarrepy-und3py-undbis = Carre(nombrespy-und3py-undbis)bksl-nlcarrepy-und4 = Carre(nombrespy-und4)bksl-nlbksl-nlprint("Carré 4")bksl-nlcarrepy-und4.affiche()bksl-nlbksl-nlassert carrepy-und3.sommepy-undligne(0) == 12bksl-nlassert carrepy-und3py-undbis.sommepy-undcolonne(1) == 10bksl-nlassert carrepy-und2.estpy-undsemipy-undmagique() is Truebksl-nlassert carrepy-und3.estpy-undsemipy-undmagique() is Truebksl-nlassert carrepy-und3py-undbis.estpy-undsemipy-undmagique() is Falsebksl-nlassert carrepy-und4.estpy-undsemipy-undmagique() is Falsebksl-nlbksl-nlfrom math import sqrtbksl-nlbksl-nlbksl-nlclass Carre:bksl-nl def py-undpy-undinitpy-undpy-und(self, nombres):bksl-nl self.ordre = int(sqrt(len(nombres)))bksl-nl self.tableau = [bksl-nl [nombres[j + i py-str self.ordre] for j in range(self.ordre)]bksl-nl for i in range(self.ordre)bksl-nl ]bksl-nlbksl-nl def affiche(self):bksl-nl """Affiche un carré"""bksl-nl for ligne in self.tableau:bksl-nl print(ligne)bksl-nlbksl-nl def sommepy-undligne(self, i):bksl-nl """Calcule la somme des valeurs de la ligne i"""bksl-nl somme = 0bksl-nl for j in range(self.ordre):bksl-nl somme = somme + self.tableau[i][j]bksl-nl return sommebksl-nlbksl-nl def sommepy-undcolonne(self, j):bksl-nl """Calcule la somme des valeurs de la colonne j"""bksl-nl somme = 0bksl-nl for i in range(self.ordre):bksl-nl somme = somme + self.tableau[i][j]bksl-nl return sommebksl-nlbksl-nl def estpy-undsemipy-undmagique(self):bksl-nl sommepy-undcommune = self.sommepy-undligne(0)bksl-nl for k in range(self.ordre):bksl-nl if self.sommepy-undligne(k) != sommepy-undcommune:bksl-nl return Falsebksl-nl if self.sommepy-undcolonne(k) != sommepy-undcommune:bksl-nl return Falsebksl-nl return Truebksl-nlbksl-nl

A

Fonction sum

Nous aurions pu utiliser la fonction "built-in" sum de Python

Lien vers la documentation Python : sum

Réponses alternatives

Autre possibilité de réponses

🐍 Script Python
def somme_ligne(self, i):
    '''Calcule la somme des valeurs de la ligne i'''
    somme = sum(self.tableau[i])
    return somme


def somme_colonne(self, j):
    '''Calcule la somme des valeurs de la colonne j'''
    return sum(self.tableau[i][j] for i in range(self.ordre))

Z