[Python] Construction de carrés magiques de dimension n=2(2k+1) (Page 1) / Programmation / Forum de mathématiques - Bibm@th.net

Forum de mathématiques - Bibm@th.net

Bienvenue dans les forums du site BibM@th, des forums où on dit Bonjour (Bonsoir), Merci, S'il vous plaît...

Vous n'êtes pas identifié(e).

#1 06-03-2009 20:45:28

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 8 813

[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

  1. #!/usr/bin/env python
  2. # -*- coding: Latin-1 -*-
  3.  
  4. # Pour un fonctionnement en mode console (DOS), remplacer # -*- coding: Latin-1 -*-
  5. # par # -*-coding:cp437-*-
  6.  
  7. from os import getcwd
  8.  
  9. def titre_general():
  10.     print
  11.     print
  12.     print "               *********************************************"
  13.     print "               *   CARRES DE DIMENSIONS IMPAIREMENT PAIRE  *"
  14.     print "               *         Modèle du Carré du Soleil         *"
  15.     print "               *********************************************"
  16.     print
  17.     print
  18.     print  
  19.    
  20. def initialisation_carres(car_init,car_mag,n):
  21.     L1,L2=[],[]
  22.     for j in range(n):
  23.         for i in range(n):
  24.             L1.append(0)
  25.             L2.append(0)
  26.         car_init.append(L1)
  27.         car_mag.append(L2)
  28.         L1,L2=[],[]
  29.     return car_init,car_mag
  30.  
  31. def choix_dimension(n):
  32.     while 1:
  33.         try:
  34.             n = int(raw_input("Veuillez choisir la dimension du carré : "))
  35.             if n % 2 == 0 and n % 4 != 0:
  36.                 if (n/2) % 2 == 1:
  37.                     break
  38.             print "Désolé ! Vous n'avez pas entré un nombre valide. Veuillez recommencer..."
  39.         except ValueError:
  40.             print "Désolé ! Ce n'est pas un nombre. Essayez encore..."
  41.     return n
  42.  
  43. # Procédure centrale de calcul
  44. def calcul(n,mode,car_init,car_mag):
  45.     nn,tnb=n/2,0
  46.     for no_qd in range(4):
  47.         for l in range(nn):
  48.             for c in range(nn):
  49.                 j = l + nn*(no_qd>1)
  50.                 i = c + nn*(no_qd % 2)
  51.                 if mode == 1:
  52.                     tnb=normal(i,j,n,nn,tnb)
  53.                 elif mode == 2:
  54.                     tnb=normal_quadr(c,l,no_qd,nn,tnb)
  55.                 elif mode == 3:
  56.                     tnb=ip_puis_pa(i,j,n,nn,tnb)
  57.                 elif mode == 4:
  58.                     tnb=ip_pa_1li(i,j,n,nn,tnb)
  59.                 elif mode == 5:
  60.                     tnb=normal_1s2(i,j,n,nn,tnb)
  61.                 elif mode == 6:
  62.                     tnb=pairs_impairs_en_colonnes_sym(i,j,n,nn,tnb)
  63.                 else:
  64.                     tnb=normal_1s2_avec_symetrie_centrale_par_paires(i,j,n,nn,tnb)                    
  65.                 car_init[j][i] = tnb
  66.                 if i == j or i+j == n-1:   # Les diagonales restent en place
  67.                     car_mag[j][i] = tnb
  68.                 else:           # initialisation du drapeau d'appartenance à une forme
  69.                     tem = (i == nn-1 or i == nn) and (j == 0 or j == n-1)
  70.                     tem = tem + ((j == nn-1 or j == nn) and (i == 0 or  i == n-1))
  71.                     tem = tem + (i == j - 1 or i + j == n-2 or i+j == n or i == j+1)
  72.                     if no_qd== 0:
  73.                         quadr1(c,l,i,j,n,nn,car_mag,tnb,tem)
  74.                     elif no_qd == 1:
  75.                         quadr2(c,l,i,j,n,nn,car_mag,tnb,tem)
  76.                     elif no_qd == 2:
  77.                         quadr3(c,l,i,j,n,nn,car_mag,tnb,tem)
  78.                     else:
  79.                         quadr4(c,l,i,j,n,nn,car_mag,tnb,tem)
  80.     return car_init,car_mag
  81.  
  82. def affichage_stockage(car_init,car_mag,mode,n):
  83.     print
  84.     if n > 34:
  85.         print
  86.         print "Dimension trop grande : création d'un fichier"
  87.         ecriture_dans_fichier(car_mag,mode,n)            
  88.     else:
  89.         affichage(car_mag,car_init,n)
  90.         print
  91.     print
  92.     teste_magie(car_mag,n)
  93.     return
  94.  
  95. # Pour voir le carré initial, remplacer après le print car_mag par car_init
  96. def affichage(car_mag,car_init,n):
  97.     print
  98.     print "#############################################"
  99.     print "           Carré d'ordre ",n
  100.     print "#############################################"
  101.     print
  102.     for j in range(n):
  103.         for i in range(n):
  104.            if n == 6:
  105.                print "%2i" % car_mag[j][i],
  106.            elif n < 34:
  107.                print "%3i" % car_mag[j][i],
  108.         print
  109.         if n > 10:
  110.             print        
  111.  
  112. def ecriture_dans_fichier(car_mag,mode,n):
  113.     rep = getcwd()
  114.     nom = "Impapairs_" + str(n)+".txt"      
  115.     chemin_nom=rep+chr(92)+nom
  116.     fichier = open(nom,'w')
  117.     lgmax = 1 + len(str(n**2))
  118.     blanc ="                   "
  119.     for j in range(n):
  120.         enreg=""
  121.         for i in range(n):
  122.             nb = str(car_mag[j][i])
  123.             lg = len(nb)
  124.             enreg += blanc[0:lgmax-lg]+nb            
  125.         fichier.write(chaine+"\n")
  126.     fichier.close()
  127.     print "Vous trouverez votre fichier ici",chemin_nom
  128.     return
  129.            
  130. def teste_magie(car_mag,n):
  131.     print "Test des lignes"
  132.     for j in range(n):
  133.         tot = 0
  134.         for i in range(n):
  135.             tot = tot + car_mag[j][i]
  136.         print tot,
  137.     print
  138.     print
  139.     print "Test des colonnes"
  140.     for i in range(n):
  141.         tot=0
  142.         for j in range(n):
  143.             tot = tot + car_mag[j][i]
  144.         print tot,
  145.     print
  146.     print
  147.     print "Test des diagonales"
  148.     tot1 = 0
  149.     tot2 = 0
  150.     for j in range(n):
  151.         i = j
  152.         tot1 = tot1 + car_mag[j][i]
  153.         tot2 = tot2 + car_mag[j][i]
  154.     print tot1,tot2
  155.     print
  156.  
  157. # Application des symétries dans chaque quadrant
  158. def quadr1(c,l,i,j,n,nn,car_mag,tnb,tem):
  159.     if ((c - l) > n/4.0 and c > l) or ((l - c)< n/4.0 and c < l):
  160.         car_mag[j][n-1-i] = tnb
  161.     else:
  162.         car_mag[n-j-1][i]= tnb
  163.     return car_mag
  164.  
  165. def quadr2(c,l,i,j,n,nn,car_mag,tnb,tem):
  166.     if (c + l < nn-1 and c + l > n/4.0-1)or c + l > 3*n/4.0-1:
  167.         car_mag[n - j-1][i] = tnb
  168.     elif tem == 0 and (c + l < n/4.0-1 or (c + l > nn-1 and c + l< 3*n/4.0-1)):
  169.         car_mag[j][n-i-1] = tnb
  170.     else:
  171.         car_mag[n-j-1][n-i-1] = tnb
  172.     return car_mag
  173.  
  174. def quadr3(c,l,i,j,n,nn,car_mag,tnb,tem):
  175.     if (c + l> n/4.0 -1 and c + l < nn-1) or c + l> 3*n/4.0-1:
  176.         car_mag[j][n-i-1] = tnb
  177.     elif tem == 0 and (c + l < n/4.0-1 or (c + l >nn-1 and c + l < 3*n/4.0-1)):
  178.         car_mag[n -j- 1][i] = tnb
  179.     else:
  180.         car_mag[n-j-1][n-i-1] = tnb
  181.     return car_mag
  182.  
  183. def quadr4(c,l,i,j,n,nn,car_mag,tnb,tem):
  184.     if tem == 1:
  185.         car_mag[n-j-1][n-i-1] = tnb
  186.     elif (c<l and l-c > n/4.0) or (c > l and c-l < n/4.0):
  187.         car_mag[j][n-i-1] = tnb
  188.     else:
  189.         car_mag[n-j-1][i]= tnb
  190.     return car_mag
  191.  
  192. # Méthodes de calcul (dans l'ordre)
  193. def normal(i,j,n,nn,tnb):
  194.     tnb = n*j + i + 1
  195.     return tnb
  196.  
  197. def normal_quadr(c,l,no_qd,nn,tnb):
  198.     tnb = nn**2*no_qd + nn*l + c + 1
  199.     return tnb
  200.  
  201. def ip_puis_pa(i,j,n,nn,tnb):
  202.     tnb = (2*i+1+j*2*n)*(j<nn)+(j>=nn)*(2+2*i+(j-nn)*2*n)
  203.     return tnb
  204.  
  205. def ip_pa_1li(i,j,n,nn,tnb):
  206.     if j %2 == 0:
  207.         tnb = 2 * i+ 1 + 2*n*(j/2)*(j>0)
  208.     else:
  209.         tnb = 2*(i+1)+ 2*n*(j/2)
  210.     return tnb
  211.  
  212. def normal_1s2(i,j,n,nn,tnb):
  213.     tnb = 1+i/2+2*nn**2*(i%2)+nn*j          
  214.     return tnb
  215.  
  216. def pairs_impairs_en_colonnes_sym(i,j,n,nn,tnb):
  217.     if i == 0 or i == n-1:
  218.         tnb=normal(i,j,n,nn,tnb)
  219.     else:
  220.         dp = (((i+1 - 2*(i>nn-1))/2)% 2 == 1)
  221.         if dp == 1:
  222.             tnb = n*j + n - i
  223.         else:
  224.             tnb=normal(i,j,n,nn,tnb)
  225.     return tnb
  226.  
  227. def normal_1s2_avec_symetrie_centrale_par_paires(i,j,n,nn,tnb):
  228.     tnb=i/2+1+nn**2*(i%2==1)+nn*j+nn**2*(j>nn-1)
  229.     return tnb
  230.  
  231. mode=10
  232. while mode!= 0:
  233.     try:
  234.         titre_general()
  235.         print
  236.         print " 1. Dans l'ordre normal par ligne du carré"
  237.         print " 2. Dans l'ordre normal par ligne de quadrant"
  238.         print " 3. Tous les nombres impairs, puis les pairs"
  239.         print " 4. Avec lignes de nombres impairs et pairs alternées"
  240.         print " 5. Ordre normal en sautant une case à chaque fois dans le carré"
  241.         print " 6. Par 2 colonnes à la fois avec symétrie dans chaque quadrant"
  242.         print " 7. Ordre normal en sautant une case et par paires symétriques de somme n²"
  243.         print "                   0. Sortie du programme"
  244.         print
  245.         mode = int(raw_input("     Votre choix : "))
  246.         if mode > 7:
  247.             print "Désolé ! Vous n'avez pas entré un nombre valide. Veuillez recommencer..."
  248.             print
  249.             print
  250.         elif mode >0:
  251.             n=0
  252.             n=choix_dimension(n)
  253.             car_init,car_mag=[],[]
  254.             car_init,car_mag=initialisation_carres(car_init,car_mag,n)
  255.             car_init,car_mag=calcul(n,mode,car_init,car_mag)
  256.             affichage_stockage(car_init,car_mag,mode,n)
  257.             print
  258.             raw_input('                ... Appuyer sur ENTREE ... ')
  259.             print
  260.     except ValueError:
  261.         print "Désolé ! Ce n'est pas un nombre. Essayez encore..."
  262.         print
  263. print
  264. print
  265. print "                       Au revoir !"

Commentaires ?

@+


Arx Tarpeia Capitoli proxima...

En ligne

#2 06-03-2009 23:18:39

tibo
Membre actif
Lieu : devant mon ordi
Inscription : 23-01-2008
Messages : 587

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 : 8 813

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...

En ligne

#4 07-03-2009 14:59:27

tibo
Membre actif
Lieu : devant mon ordi
Inscription : 23-01-2008
Messages : 587

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 : 8 813

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...

En ligne

#6 21-03-2009 18:29:34

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 8 813

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...

En ligne

Réponse rapide

Veuillez composer votre message et l'envoyer

Les questions suivantes sont faites pour éviter le spam. Si vous voulez ne plus les avoir, inscrivez-vous!

Quel est le résultat de 43+64?

Quel est le 6 ième chiffre de 7846442?

Pied de page des forums

[ Générées en 0.180 secondes, 8 requêtes exécutées - Utilisation de la mémoire : 3.01 MiB (pic d'utilisation : 3.41 MiB) ]