Forum de mathématiques - Bibm@th.net
Vous n'êtes pas identifié(e).
- Contributions : Récentes | Sans réponse
#1 06-03-2009 20:45:28
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 7 528
[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 \(\displaystyle k\in \mathbb{N}^*\) .
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...
: python
- #!/usr/bin/env python
- # -*- 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 06-03-2009 23:18:39
- tibo
- Membre actif
- Lieu : devant mon ordi
- Inscription : 23-01-2008
- Messages : 520
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 (06-03-2009 23:19:18)
Dieu est le compactifié d'Alexandrov de l'univers
Nicolas Bourbaki
Hors ligne
#3 07-03-2009 08:41:28
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 7 528
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 14:59:27
- tibo
- Membre actif
- Lieu : devant mon ordi
- Inscription : 23-01-2008
- Messages : 520
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
Dieu est le compactifié d'Alexandrov de l'univers
Nicolas Bourbaki
Hors ligne
#5 18-03-2009 08:21:59
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 7 528
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 18:29:34
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 7 528
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