Forum de mathématiques - Bibm@th.net
Vous n'êtes pas identifié(e).
- Contributions : Récentes | Sans réponse
#1 06-03-2009 21:45:28
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 17 223
[Python] Construction de carrés magiques de dimension n=2(2k+1)
Bonsoir,
Voilà revu et corrigé un programme de constructions de carrés magiques de dimension "impairement paire" n = 2(2k+1) avec [tex]k\in \mathbb{N}^*[/tex].
Ainsi que vous le verrez sur la page http://www.bibmath.net/carres/index.php … =impapairs où tout est expliqué pour la construction "à la main", à partir d'un carré déjà rempli, on applique 3 symétries : 2 axiales par rapport à l'horizontale et la verticale et la symétrie centrale.
Toute la difficulté a été
1. D'informatiser ces symétries
2. Et surtout de repérer mathématiquement (puis traduire en Python) l'appartenance d'un nombre à une forme, laquelle forme conditionne son déplacement...
Voilà, essayez-le, regardez la répartition des nombre dont la somme est n^2+1, la répartition pairs/impairs...
# -*- coding: Latin-1 -*-
# Pour un fonctionnement en mode console (DOS), remplacer # -*- coding: Latin-1 -*-
# par # -*-coding:cp437-*-
from os import getcwd
def titre_general():
print
print
print " *********************************************"
print " * CARRES DE DIMENSIONS IMPAIREMENT PAIRE *"
print " * Modèle du Carré du Soleil *"
print " *********************************************"
print
print
print
def initialisation_carres(car_init,car_mag,n):
L1,L2=[],[]
for j in range(n):
for i in range(n):
L1.append(0)
L2.append(0)
car_init.append(L1)
car_mag.append(L2)
L1,L2=[],[]
return car_init,car_mag
def choix_dimension(n):
while 1:
try:
n = int(raw_input("Veuillez choisir la dimension du carré : "))
if n % 2 == 0 and n % 4 != 0:
if (n/2) % 2 == 1:
break
print "Désolé ! Vous n'avez pas entré un nombre valide. Veuillez recommencer..."
except ValueError:
print "Désolé ! Ce n'est pas un nombre. Essayez encore..."
return n
# Procédure centrale de calcul
def calcul(n,mode,car_init,car_mag):
nn,tnb=n/2,0
for no_qd in range(4):
for l in range(nn):
for c in range(nn):
j = l + nn*(no_qd>1)
i = c + nn*(no_qd % 2)
if mode == 1:
tnb=normal(i,j,n,nn,tnb)
elif mode == 2:
tnb=normal_quadr(c,l,no_qd,nn,tnb)
elif mode == 3:
tnb=ip_puis_pa(i,j,n,nn,tnb)
elif mode == 4:
tnb=ip_pa_1li(i,j,n,nn,tnb)
elif mode == 5:
tnb=normal_1s2(i,j,n,nn,tnb)
elif mode == 6:
tnb=pairs_impairs_en_colonnes_sym(i,j,n,nn,tnb)
else:
tnb=normal_1s2_avec_symetrie_centrale_par_paires(i,j,n,nn,tnb)
car_init[j][i] = tnb
if i == j or i+j == n-1: # Les diagonales restent en place
car_mag[j][i] = tnb
else: # initialisation du drapeau d'appartenance à une forme
tem = (i == nn-1 or i == nn) and (j == 0 or j == n-1)
tem = tem + ((j == nn-1 or j == nn) and (i == 0 or i == n-1))
tem = tem + (i == j - 1 or i + j == n-2 or i+j == n or i == j+1)
if no_qd== 0:
quadr1(c,l,i,j,n,nn,car_mag,tnb,tem)
elif no_qd == 1:
quadr2(c,l,i,j,n,nn,car_mag,tnb,tem)
elif no_qd == 2:
quadr3(c,l,i,j,n,nn,car_mag,tnb,tem)
else:
quadr4(c,l,i,j,n,nn,car_mag,tnb,tem)
return car_init,car_mag
def affichage_stockage(car_init,car_mag,mode,n):
print
if n > 34:
print
print "Dimension trop grande : création d'un fichier"
ecriture_dans_fichier(car_mag,mode,n)
else:
affichage(car_mag,car_init,n)
print
print
teste_magie(car_mag,n)
return
# Pour voir le carré initial, remplacer après le print car_mag par car_init
def affichage(car_mag,car_init,n):
print
print "#############################################"
print " Carré d'ordre ",n
print "#############################################"
print
for j in range(n):
for i in range(n):
if n == 6:
print "%2i" % car_mag[j][i],
elif n < 34:
print "%3i" % car_mag[j][i],
print
if n > 10:
print
def ecriture_dans_fichier(car_mag,mode,n):
rep = getcwd()
nom = "Impapairs_" + str(n)+".txt"
chemin_nom=rep+chr(92)+nom
fichier = open(nom,'w')
lgmax = 1 + len(str(n**2))
blanc =" "
for j in range(n):
enreg=""
for i in range(n):
nb = str(car_mag[j][i])
lg = len(nb)
enreg += blanc[0:lgmax-lg]+nb
fichier.write(chaine+"\n")
fichier.close()
print "Vous trouverez votre fichier ici",chemin_nom
return
def teste_magie(car_mag,n):
print "Test des lignes"
for j in range(n):
tot = 0
for i in range(n):
tot = tot + car_mag[j][i]
print tot,
print
print
print "Test des colonnes"
for i in range(n):
tot=0
for j in range(n):
tot = tot + car_mag[j][i]
print tot,
print
print
print "Test des diagonales"
tot1 = 0
tot2 = 0
for j in range(n):
i = j
tot1 = tot1 + car_mag[j][i]
tot2 = tot2 + car_mag[j][i]
print tot1,tot2
print
# Application des symétries dans chaque quadrant
def quadr1(c,l,i,j,n,nn,car_mag,tnb,tem):
if ((c - l) > n/4.0 and c > l) or ((l - c)< n/4.0 and c < l):
car_mag[j][n-1-i] = tnb
else:
car_mag[n-j-1][i]= tnb
return car_mag
def quadr2(c,l,i,j,n,nn,car_mag,tnb,tem):
if (c + l < nn-1 and c + l > n/4.0-1)or c + l > 3*n/4.0-1:
car_mag[n - j-1][i] = tnb
elif tem == 0 and (c + l < n/4.0-1 or (c + l > nn-1 and c + l< 3*n/4.0-1)):
car_mag[j][n-i-1] = tnb
else:
car_mag[n-j-1][n-i-1] = tnb
return car_mag
def quadr3(c,l,i,j,n,nn,car_mag,tnb,tem):
if (c + l> n/4.0 -1 and c + l < nn-1) or c + l> 3*n/4.0-1:
car_mag[j][n-i-1] = tnb
elif tem == 0 and (c + l < n/4.0-1 or (c + l >nn-1 and c + l < 3*n/4.0-1)):
car_mag[n -j- 1][i] = tnb
else:
car_mag[n-j-1][n-i-1] = tnb
return car_mag
def quadr4(c,l,i,j,n,nn,car_mag,tnb,tem):
if tem == 1:
car_mag[n-j-1][n-i-1] = tnb
elif (c<l and l-c > n/4.0) or (c > l and c-l < n/4.0):
car_mag[j][n-i-1] = tnb
else:
car_mag[n-j-1][i]= tnb
return car_mag
# Méthodes de calcul (dans l'ordre)
def normal(i,j,n,nn,tnb):
tnb = n*j + i + 1
return tnb
def normal_quadr(c,l,no_qd,nn,tnb):
tnb = nn**2*no_qd + nn*l + c + 1
return tnb
def ip_puis_pa(i,j,n,nn,tnb):
tnb = (2*i+1+j*2*n)*(j<nn)+(j>=nn)*(2+2*i+(j-nn)*2*n)
return tnb
def ip_pa_1li(i,j,n,nn,tnb):
if j %2 == 0:
tnb = 2 * i+ 1 + 2*n*(j/2)*(j>0)
else:
tnb = 2*(i+1)+ 2*n*(j/2)
return tnb
def normal_1s2(i,j,n,nn,tnb):
tnb = 1+i/2+2*nn**2*(i%2)+nn*j
return tnb
def pairs_impairs_en_colonnes_sym(i,j,n,nn,tnb):
if i == 0 or i == n-1:
tnb=normal(i,j,n,nn,tnb)
else:
dp = (((i+1 - 2*(i>nn-1))/2)% 2 == 1)
if dp == 1:
tnb = n*j + n - i
else:
tnb=normal(i,j,n,nn,tnb)
return tnb
def normal_1s2_avec_symetrie_centrale_par_paires(i,j,n,nn,tnb):
tnb=i/2+1+nn**2*(i%2==1)+nn*j+nn**2*(j>nn-1)
return tnb
mode=10
while mode!= 0:
try:
titre_general()
print
print " 1. Dans l'ordre normal par ligne du carré"
print " 2. Dans l'ordre normal par ligne de quadrant"
print " 3. Tous les nombres impairs, puis les pairs"
print " 4. Avec lignes de nombres impairs et pairs alternées"
print " 5. Ordre normal en sautant une case à chaque fois dans le carré"
print " 6. Par 2 colonnes à la fois avec symétrie dans chaque quadrant"
print " 7. Ordre normal en sautant une case et par paires symétriques de somme n²"
print " 0. Sortie du programme"
print
mode = int(raw_input(" Votre choix : "))
if mode > 7:
print "Désolé ! Vous n'avez pas entré un nombre valide. Veuillez recommencer..."
print
print
elif mode >0:
n=0
n=choix_dimension(n)
car_init,car_mag=[],[]
car_init,car_mag=initialisation_carres(car_init,car_mag,n)
car_init,car_mag=calcul(n,mode,car_init,car_mag)
affichage_stockage(car_init,car_mag,mode,n)
print
raw_input(' ... Appuyer sur ENTREE ... ')
print
except ValueError:
print "Désolé ! Ce n'est pas un nombre. Essayez encore..."
print
print
print
print " Au revoir !"
Commentaires ?
@+
Arx Tarpeia Capitoli proxima...
Hors ligne
#2 07-03-2009 00:18:39
- tibo
- Membre expert
- Inscription : 23-01-2008
- Messages : 1 097
Re : [Python] Construction de carrés magiques de dimension n=2(2k+1)
J'en reste sans voix...
Meme en le poussant à la limite (carré de taille 10002), aprés 2h consécutives de calculs, et je pense le double d'affichage (c'est en cours là), j'obtiens un résultat.
Franchement BRAVO
(allez j'emet quand meme une critique, est-ce vraiment nécéssaire d'afficher les test de lignes, de colonne et de diagonales? que le programme test, oui. afficher le somme, oui. mais pas tout afficher)
bon maintenant je vais décortiquer ton code. Enfin ce week-end, parce que demain j'ai DS de math quand meme, il faudrait relire son cours un peu non?
Dernière modification par tibo (07-03-2009 00:19:18)
A quoi sert une hyperbole?
----- A boire de l'hypersoupe pardi !
Hors ligne
#3 07-03-2009 09:41:28
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 17 223
Re : [Python] Construction de carrés magiques de dimension n=2(2k+1)
Salut,
le test de magie peut s'enlever facilement ou devenir optionnel : je vais voir ça...
n=10002 ??? J'aurais jamais pensé que quelqu'un aille jusque là...
En principe, il n'y a pas d'affichage au delà de n = 34, mais stockage dans un fichier (dans le même dossier que le prog) séquentiel dont le nom te sera donné.
Pourquoi cela ? Pour permettre la récupération via un traitement de textes puis imprimer des morceaux sur une page A4 pour enfin les assembler : je l'avais fait avec une dimension autour de 100...
La taille estimée pour n= 10002 ? Environ 400 Mo !!!!
Je vais voir pour un fichier à accès direct...
Pour avoir une chance de comprendre le code, il faut bien lire la page de BibM@th où la méthode à la main est décrite...
A ma connaissance, personne n'avait pu, jusqu'à ce que je le fasse, sauter le pas de la dimension 6 à 10 et au-delà : des formes nouvelles apparaissent à partir de 10. Depuis le temps que j'affirme cela, je n'ai jamais été démenti...
L'identification de ces formes nouvelles est due à l'un de mes amis ex-libraire et grand amateur de la magie des nombres : il a travaillé avec n = 10. Au delà, c'est un coup de chance et une intuition personnelle, un jour il y a près de 20 ans.
L'étape suivante, l'informatisation, a été longue et semée d'embûches.
Même avec une version de secours qui fonctionnait, sachant ce que j'avais imaginé, la modification du programme pour :
- qu'il fonctionne à partir de l'indice 0 et non plus 1, avec le passage d'une seule liste de n^2 nombres à une liste comprenant n listes de n nombres pour simuler les tableaux (n'existent pas en Python) du BASIC et d'autres langages,
- ne plus utiliser de variables déclarées globales
m'a demandé une dizaine d'heures...
Merci pour cette première réaction...
@+
Arx Tarpeia Capitoli proxima...
Hors ligne
#4 07-03-2009 15:59:27
- tibo
- Membre expert
- Inscription : 23-01-2008
- Messages : 1 097
Re : [Python] Construction de carrés magiques de dimension n=2(2k+1)
oups en effet c'est beaucoup 10002,
j'ai mis un 0 en trop
en fait c'est 1002, et vu le temps que ça m'a pris je ne tenterai pas plus
et bien pensé aussi cette histoire de ficher "annexe", par contre l'affichage est un peu bizar quand les nombres sont trop grands
A quoi sert une hyperbole?
----- A boire de l'hypersoupe pardi !
Hors ligne
#5 18-03-2009 09:21:59
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 17 223
Re : [Python] Construction de carrés magiques de dimension n=2(2k+1)
Bonjour,
Je pense, sans avoir essayé, savoir pourquoi tibo a déclaré que les nombres stockés étaient bizarres.
J'ai modifié la méthode de stockage et de nommage du fichier contenant les nombres du carré magique.
Je n'avais pas testé la méthode avant, mais recopié icelle directement de l'ancien programme de construction, et comme je ne gère plus maintenant une liste, mais une liste de listes, il devait y avoir effectivement quelques "bizarreries".
Dont acte...
S'il y a encore une bricole, me le faire savoir, merci
@+
Arx Tarpeia Capitoli proxima...
Hors ligne
#6 21-03-2009 19:29:34
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 17 223
Re : [Python] Construction de carrés magiques de dimension n=2(2k+1)
Bonsoir,
Encore une (toute) petite destinée à "standardiser" (pour traitement ultérieur --> utilitaire mis en ligne) les noms de carrés magiques enregistrés :
remplacer dans :
def ecriture_dans_fichier(car_mag,mode,n):
nom = "Impapairs_" + str(n) par nom = "Impapairs_"+str(n)+".txt"
@+
Arx Tarpeia Capitoli proxima...
Hors ligne