Forum de mathématiques - Bibm@th.net
Vous n'êtes pas identifié(e).
- Contributions : Récentes | Sans réponse
#1 17-03-2009 15:36:40
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 17 101
[Python] Construction de carrés magiques impairs, simples ou gigognes.
Bonjour à tous,
En complément de la page http://www.bibmath.net/carres/index.php … oi=impairs, voici la version informatisée.
Ces carrés impairs, si leur dimension n'est pas multiple de 3, sont diaboliques. Voir la page précitée ou le le programme pour une définition de l'adjectif (on dit aussi pandiagonaux).
Une autre particularité intéressante de ce programme est la possibilité de construire des carrés gigognes (à deux dimensions).
Ainsi, vous pouvez construire un carré de dimension 35 (31 maximum pour l'affichage : il sera enregistré) :
- Soit sur la base de 35 = 5 x 7, c'est à dire de 7² = 49 carrés de dimension 5,
- Soit sur la base de 35 = 5 x 7, c'est à dire de 5² = 25 carrés de dimension 7.
Chacun des 49 carrés de dimension 5, ou des 25 carrés de dimension de 7, sera magique et diabolique, le carré de 35 étant lui-même globalement magique et diabolique...
Cela dit, vous pouvez aussi construire un carré "simple" (= à une dimension) d'ordre 35 : vous avez donc 3 carrés magiques et diaboliques possibles d'ordre 35.
Le seul carré gigogne magique et diabolique affichable est celui de 25 = 5 x 5...
Bien sûr la technique utilisée pour construire les carrés gigognes à deux dimensions est extensible à 3, 4... etc dimensions : une explication figure pour 3 dimensions sur la page internet consacrée à ces carrés...
Une assistance, par l'exemple, à la construction de carrés magiques et diaboliques simples (dimension 5 ou 7), une démo détaillée de la construction du carré magique gigogne d'ordre 35 = 3 x 5 et une assistance à la construction du carré magique gigogne d'ordre 15 = 5 x 3 par vos soins sont incluses.
Je n'ai pas prévu la vérification du caractère magique (je vais voir pour la rendre optionnelle)...
# -*- coding: Latin-1 -*-
from os import getcwd
def titre_general():
print
print
print " *********************************************"
print " * CARRES DE DIMENSIONS IMPAIRES *"
print " * simples et gigognes *"
print " *********************************************"
print
def presentation():
print " Ce petit programme se propose de vous faire découvrir un certain type de carrés"
print "magiques de dimension impaire."
print "Tous les carrés construits de dimension multiple de 3 ne seront pas "+ chr(34)+"diaboliques"+chr(34)
print "(ou pandiagonaux), les autres si."
print "Outre les propriétés magiques classiques, pour les carrés non multiples de 3, il faut faire"
print "intervenir la notion de "+chr(34)+" diagonale brisée"+chr(34)+"."
print
print " Exemple de diagonales brisées :"
print " |---|---|---|---|---| |---|---|---|---|---|"
print " | | | | X | | | O | | | | |"
print " |---|---|---|---|---| |---|---|---|---|---|"
print " | | | | | X | | | | | | O |"
print " |---|---|---|---|---| |---|---|---|---|---|"
print " | X | | | | | | | | | O | |"
print " |---|---|---|---|---| |---|---|---|---|---|"
print " | | X | | | | | | | O | | |"
print " |---|---|---|---|---| |---|---|---|---|---|"
print " | | | X | | | | | O | | | |"
print " |---|---|---|---|---| |---|---|---|---|---|"
print
presse()
print
print "La somme des nombres figurés par un X, ou O est aussi égale à la constante magique, soit n(n²+1)/2,"
print "65 pour un carré d'ordre 5."
print "Partons du X sis en ligne 1, colonne 4, descendons d'une case vers la droite. Ensuite, comme"
print "on ne peut sortir du carré, on descend sur la case en dessous et on ricoche vers la gauche "
print "comme au billard !) et on reprend la descente. Le procédé est identique pour le O"
print
print " Le carré cigogne (éventuellement diabolique) lui, est composé de carrés plus petits eux-mêmes"
print "magiques (et éventuellement diaboliques). Ainsi le carré de 15 = 3 x 5 sera composé de 25 carrés"
print "d'ordre 3, mais le carré de 15 = 5 x 3 sera lui composé de 9 carrés d'ordre 5."
print "Il suffit de réfléchir quelques secondes pour voir que les deux carrés obtenus seront différents..."
print " La multiplicationn magique n'est donc PAS COMMUTATIVE !"
print
return
def presse():
print
raw_input(" ... Pour la suite, presser la touche ENTREE ...")
print
def retour():
print
raw_input(" ... Pour revenir au menu, presser ENTREE ...")
print
def voici():
print
print " Voici le carré demandé :"
print
def choix_type(gig):
sortie=0
while not sortie:
try:
gig = int(raw_input("Construction d'un carré simple ou gigogne (1/2) ? "))
print
if gig <1 or gig >2:
print "Désolé ! Vous devez répondre avec 1 ou 2. Veuillez recommencer..."
print
else:
sortie=1
except ValueError:
print "Désolé ! Ce n'est pas un nombre. Essayez encore..."
return gig
def choix_dimension(dim):
sortie=0
while not sortie:
try:
dim = int(raw_input("Veuillez choisir une dimension impaire : "))
if dim % 2 != 1:
print "Désolé ! Vous n'avez pas entré une dimension valide. Veuillez recommencer..."
print
else:
sortie=1
except ValueError:
print "Désolé ! Ce n'est pas un nombre. Essayez encore..."
return dim
def calcul(dim,car_mag):
L=[]
dc,dl=(dim+1-2*(dim%3==0))/2,0
lc,cc=dl,dc
for j in range(dim):
for i in range(dim):
lc=lc-(i>0)
lc+=dim*(lc==-1)
cc=cc-(i>0)
cc+=dim*(cc==-1)
L.append(dim*lc+cc+1)
car_mag.append(L)
L=[]
dl+=2
dl-=dim*(dl>dim)
lc=dl
if dim%3==0:
dc+=1
dc-=dim*(dc==dim)
cc=dc
else:
dc+=3
dc-=dim*(dc>dim-1)
cc=dc
return dim,car_mag
def gigognes(n1,n2,car_nat,car_fin):
dim,fin,car_mag,car_nat,car_fin=n1,n2**2,[],[],[]
L1,L2,n=[],[],n1*n2
dim,car_mag=calcul(dim,car_mag)
for j in range(n):
for i in range(n):
L1.append(0)
L2.append(0)
car_nat.append(L1)
car_fin.append(L2)
L1,L2=[],[]
for no_qd in range(fin):
# correctif pour passage dans le carré d'ordre n
cl=no_qd/n2
cc=no_qd%n2
crl,crc=cl*n1,cc*n1
for l in range(n1):
for c in range(n1):
# coordonnées de la case en cours
j,i=l+crl,c+crc
#print j,i," ",
# nombre du carré n1 à mettre dans cette case
dpl=car_mag[l][c]
# coordonnées relatives dans carré n1 de ce nombre
ll=(dpl-1)/n1
cc=(dpl-1)%n1
# coordonnées absolues dans carré n de ce nombre
jj,ii=ll+crl,cc+crc
car_nat[j][i]=n*jj+ii+1
dim,car_mag=n2,[]
dim,car_mag=calcul(dim,car_mag)
# Boucle des nos de carrés (d'ordre n1) de 0 à n2^2
for no_qd in range(fin):
# Cordonnées des carrés d'ordre n1 (variant de 0 à n2)
l_img=no_qd/n2
c_img=no_qd%n2
# correctif pour passage dans le carré d'ordre n
cj,ci=l_img*n1,c_img*n1
# numéro du carré aà déplacer
ant=car_mag[l_img][c_img]
# coordonnées absolues du 1er nombre du carré antécédent
# variant de 0 à n2
l_ant=(ant - 1)/n2
c_ant=(ant -1)%n2
# correctif pour passage dans le carré d'ordre n
cl,cc=l_ant*n1,c_ant*n1
# Déplacement des nombres du carré antécédent
for l in range(n1):
for c in range(n1):
car_fin[cj+l][ci+c]=car_nat[cl+l][cc+c]
return n1,n2,car_nat,car_fin
def demo3x5():
n1,n2,n,ct,car_nat,car_fin,car_mag=3,5,15,1,[],[],[]
print
print
print " ******************************************************"
print " * CONTRUCTION du CARRE d'ordre 15 = 3 x 5 *"
print " ******************************************************"
print
print "1. On commence par construire le carré naturel d'ordre 15 qu'on remplit avec"
print " les nombres de 1 à 225, puis on matérialise les 25 carrés de 3 x 3 :"
print
n1,n2,car_nat,car_fin=gigognes(n1,n2,car_nat,car_fin)
cpc,cpl,sep=0,0,3
affichage_separations(ct,sep,car_mag)
dim,car_mag=3,[]
presse()
print " 2 7 6"
print "2. A l'aide du carré de 3 que voici : 9 5 1"
print " 4 3 8"
print
print"3. Dans chaque carré de 3 x 3, on déplace chaque nombre selon la structure ci-dessus :"
print
presse()
car_mag=list(car_nat)
ct=2
affichage_separations(ct,dim,car_mag)
presse()
print " ----------------"
print " | 4 23 17 11 10 |"
print "4. On numérote de 1 à 25 les carrés de 3 dans l'ordre normal. | 12 6 5 24 18 |"
print "5. On déplace chaque carré à la place de son numéro dans le | 25 19 13 7 1 |"
print " carré de 5 ci contre : | 8 2 21 20 14 |"
print " | 16 15 9 3 22 |"
print " ----------------"
voici()
car_mag=list(car_fin)
print
affichage_separations(ct,dim,car_mag)
return
def solo5x3():
n1,n2,n,ct,car_nat,car_fin,car_mag=5,3,15,1,[],[],[]
print
print
print " ******************************************************"
print " * CONTRUCTION du CARRE d'ordre 15 = 5 x 3 *"
print " ******************************************************"
print
print "1. Munissez-vous de quoi écrire..."
print "2. Commencez par tracer trois grilles carrées de 15 x 15. Remplissez la"
print " première avec les nombres de 1 à 225, puis matérialisez les 9 carrés"
print " de 5 x 5 :"
n1,n2,car_nat,car_fin=gigognes(n1,n2,car_nat,car_fin)
cpc,cpl,sep,ct=0,0,5,1
presse()
affichage_separations(ct,sep,car_mag)
print
print "3. Construisez les carrés magiques d'ordre 5 et 3,"
presse()
print " -------------------- "
print " | 4 23 17 11 10 | -------"
print " | 12 6 5 24 18 | | 2 7 6 |"
print " | 25 19 13 7 1 | | 9 5 1 |"
print " | 8 2 21 20 14 | | 4 3 8 |"
print " | 16 15 9 3 22 | -------"
print " -------------------- "
print " 4. Complétez chaque carré de base de la deuxième grille, avec les nombres"
print " du carré correspondant de la première grille, placés dans l'ordre de la"
print " strucure du carré d'ordre de 5 ci-dessus,"
presse()
car_mag=list(car_nat)
ct=2
affichage_separations(ct,sep,car_mag)
print
print "5. Numérotez les blocs de la deuxième grille de 1 à 9, puis complétez la"
print " dernière grille en plaçant chaque carré numéroté à la place qu'il occupe"
print " dans le carré de 3."
presse()
car_mag=list(car_fin)
voici()
affichage_separations(ct,sep,car_mag)
return
def affichage_separations(ct,sep,car_mag):
cpl,cpc=0,0
tirets="----"
ligne=" |------------------------------------------------\
-----------------"+tirets[0:4*(sep==3)]+"|"
print ligne
for j in range (15):
print " |",
cpl+=1
for i in range(15):
cpc+=1
if ct==1:
nb=str(15*j+i+1)
else:
nb=str(car_mag[j][i])
lg=len(nb)
if lg==1:
print" "+nb,
elif lg==2:
print" "+nb,
else:
print nb,
if cpc%sep==0 and i>0:
print"|",
print
if cpl%sep==0 and j>0:
print ligne
return
def affichage(dim,n1,n2,car_mag):
if dim<32:
print
for j in range(dim):
for i in range(dim):
if dim<10:
print "%2i" % car_mag[j][i],
else:
print "%3i" % car_mag[j][i],
print
else:
print "... Dimension trop grande pour l'affichage : écriture dans un fichier ..."
presse()
stockage(dim,n1,n2,car_mag)
return
def stockage(dim,n1,n2,car_mag):
rep = getcwd()
if n2>1:
nom = "Impairs_G" + str(n1)+"x"+str(n2)+".txt"
else:
nom = "Impairs_S" + str(dim)+".txt"
chemin_nom=rep+chr(92)+nom
fichier = open(nom,'w')
lgmax = 1 + len(str(dim**2))
blanc = " "
for j in range(dim):
enreg=""
for i in range(dim):
nb = str(car_mag[j][i])
lg = len(nb)
enreg += blanc[0:lgmax-lg]+nb
fichier.write(enreg+"\n")
fichier.close()
print "Vous trouverez votre fichier ici",chemin_nom
return
def gere_carres():
gig,dim,n1,n2,Dim,car_nat,car_fin,car_mag=1,1,1,1,[],[],[],[]
titre_general()
gig=choix_type(gig)
for i in range(gig):
dim=choix_dimension(dim)
Dim.append(dim)
if gig>1:
n1,n2=Dim[0],Dim[1]
n1,n2,car_nat,car_fin=gigognes(n1,n2,car_nat,car_fin)
voici()
dim=n1*n2
car_mag=list(car_fin)
if dim<32:
voici()
affichage(dim,n1,n2,car_mag)
else:
dim,car_mag=calcul(dim,car_mag)
n1=dim
if dim < 32:
voici()
affichage(dim,n1,n2,car_mag)
return
def menu(mode):
while mode >5 or mode <0:
try:
print
print " ***********************"
print " * Menu principal *"
print " ***********************"
print
print "1. Voir un carré simple ou gigogne"
print "2. Voir la méthode de construction d'un carré simple (n = 5 ou 7)"
print "3. Construire vous-même le carré simple de dimension n = 11 et le vérifier"
print "4. Voir la méthode construction du carré gigogne de 3 x 5"
print "5. Construire vous-même le carré gigogne de 5 x 3"
print " 0. Sortie du programme."
print
mode = int(raw_input(" < Votre choix ? > "))
print
if mode > 5 or mode <0 :
print
print "Désolé ! Votre choix n'est pas valide. Veuillez recommencer..."
print
except ValueError:
print "Désolé ! Ce n'est pas un nombre. Essayez encore..."
print
return mode
def methode_car_simple(dim,car_mag):
print
print " ********************************************************"
print " * Méthode de constructions de carrés impairs simples *"
print " ********************************************************"
print
print "Chacun des nombres de ce carré est répéré par un couple de coordonnées (ligne,colonne)"
print "Voici pour chacun des nombres du carré magique, le n° de ligne puis le n° de colonne"
print "donnant sa position dans le carré naturel ci-dessus :"
print " N° de ligne N° de colonne"
dim,car_mag=calcul(dim,car_mag)
affiche_coordonnees(dim,car_mag)
affiche_methode_coordonnees(dim)
if dim==5:
print "(3 ; 3) et donc le nombre 13."
else:
print "(6, 7) et donc le nombre 42."
presse()
print "Voici le carré "+chr(34)+"naturel"+chr(34)+" de dimension",dim,"et le carré magique correspondant"
print
for l in range(dim):
print " ",
for k in range(dim):
nb=dim*l+k+1
print "%2i" % nb,
print " ",
for k in range(dim):
print "%2i" % car_mag[l][k],
print
return
def calcul_solo():
print " ** RAPPEL **"
print
affiche_methode_coordonnees(11)
print "(1 ; 4) dans le carré naturel et donc le nombre 4"
print
print "Construisez vos deux matrices de nos de lignes et de nos de colonne...",
dim,car_mag=11,[]
dim,car_mag=calcul(dim,car_mag)
print
raw_input(" C'est fait ? Alors appuyez sur ENTREE")
print
print " N° de ligne N° de colonne"
affiche_coordonnees(dim,car_mag)
print " C'était juste ? Non ? Relisez encore les explications..."
presse()
voici()
affichage(dim,n1,n2,car_mag)
return
def affiche_methode_coordonnees(dim):
print
print " Pour trouver les n°s de ligne :"
print "Partir de 1."
print "- Horizontalement, chaque n° de ligne se déduit du précédent en lui soustrayant 1."
print " Mais vous devrez ajouter n, dès le 0 atteint, puis reprendre les additions."
print "- Verticalement, chaque n° se déduit du précédent en lui ajoutant 2."
print " Mais vous devrez soustraire n, dès que le n° de ligne dépassera cette valeur."
print " puis reprendre les additions."
print
print " Pour trouver les n°s de colonne :"
print "Partir de (n+3)/2 si la dimension n n'est pas multiple de 3, de (n+1)/2 sinon."
print "Ici : ("+str(dim)+"+3)/2 =",(dim+3)/2,"."
print "- Horizontalement, chaque n° de colonne se déduit du précédent en lui ôtant 1."
print " Mais vous devrez ajouter n, dès que le n° de colonne dès le 0 atteint"
print " puis reprendre les additions."
print "- Verticalement, chaque n° se déduit du précédent en lui ajoutant 3."
print " Mais vous devrez soustraire n dès que le n° de ligne dépassera cette valeur,"
print " puis reprendre les additions."
print
print "Ainsi, dans la case de coordonnées ("+str(dim-2)+" ; " +str((dim+1)/2)+") se trouvera le nombre de"
print "coordonnées",
return
def affiche_coordonnees(dim,car_mag):
print
for j in range(dim):
print " ",
for i in range(dim):
nc=car_mag[j][i]
l=1+(nc-1)/dim
if dim>9:
print "%2i" % l,
else:
print l,
print " ",
for i in range(dim):
nc=car_mag[j][i]
c=1+(nc-1)%dim
if dim>9:
print "%2i" % c,
else:
print c,
print
print
return
# Gestion des choix
mode,pres=10,0
while mode!=0:
pres+=1
titre_general()
if pres==1:
presentation()
car_mag=[]
mode=menu(mode)
if mode==1:
gere_carres()
mode=10
elif mode==2:
dim=choix_dimension(5)
car_mag=[]
dim,car_mag=calcul(dim,car_mag)
methode_car_simple(dim,car_mag)
mode=10
elif mode==3:
titre_general()
calcul_solo()
mode=10
elif mode==4:
demo3x5()
mode=10
elif mode==5:
solo5x3()
mode=10
if mode > 0:
retour()
print
print " Au revoir !"
Si vous décidiez d'exécuter ce grogramme dans une fenêtre DOS remplacer la 2e ligne :
# -*- coding: Latin-1 -*-
par celle-ci :
# -*- coding: cp437 -*-
afin de profiter des caractères accentués.
Réactions, Commentaires bienvenus...
@+
Arx Tarpeia Capitoli proxima...
Hors ligne
#2 18-03-2009 09:09:06
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 17 101
Re : [Python] Construction de carrés magiques impairs, simples ou gigognes.
Bonjour à tous,
J'ai modifié la méthode de stockage et le nommage du fichier : il a donc quelques modifs un peu partout...
Désolé.
J'ai encore aussi purgé le code de différentes "déclarations" inutiles, mais ça ce sont des broutilles...
Enjoy !
@+
Arx Tarpeia Capitoli proxima...
Hors ligne
#3 21-03-2009 19:58:30
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 17 101
Re : [Python] Construction de carrés magiques impairs, simples ou gigognes.
Bonsoir,
Encore une retouche mineure, pour rendre les messages affichés, en cas d'appel au module de stockage, plus aérés...
Voici le code retouché :
if dim<33:
for j in range(dim):
for i in range(dim):
if dim<10:
print "%2i" % car_mag[j][i],
else:
print "%3i" % car_mag[j][i],
else:
print " ... Dimension trop grande pour l'affichage : écriture dans un fichier ..."
stockage(dim,n1,n2,car_mag)
return
def stockage(dim,n1,n2,car_mag):
rep = getcwd()
if n2>1:
nom = "Impairs_G" + str(n1)+"x"+str(n2)+".txt"
else:
nom = "Impairs_S" + str(dim)+".txt"
chemin_nom=rep+chr(92)+nom
fichier = open(nom,'w')
lgmax = 1 + len(str(dim**2))
blanc = " "
for j in range(dim):
enreg=""
for i in range(dim):
nb = str(car_mag[j][i])
lg = len(nb)
enreg += blanc[0:lgmax-lg]+nb
fichier.write(enreg+"\n")
fichier.close()
print
print " Vous trouverez votre fichier ici",chemin_nom
return
Et je mets en ligne un utilitaire de découpe des carrés en vue de l'impression si dimension > 31...
@+
Arx Tarpeia Capitoli proxima...
Hors ligne