Forum de mathématiques - Bibm@th.net
Vous n'êtes pas identifié(e).
- Contributions : Récentes | Sans réponse
#1 22-04-2011 15:32:56
- totomm
- Invité
[VBasic puis Python] Pour l'enigme "Vases communicants" de freddy
Bonjour,
@yoshi : ci-dessous en VBasic 2008 express
'Valeurs globales pour la procédure Répartir3N
Private Nmaxi As Integer = 10
Dim Urnes(2) As Integer
Dim De(Nmaxi), Vers(Nmaxi) As Integer 'Mémoire du niveau p
Dim wL As New System.IO.StringWriter 'wL reçoit les lignes à écrire dans RTB
Dim nbSolutions As Integer = 0
Sub Répartir3N(ByRef RTB As RichTextBox) 'RTB reçoit les résultats
wL.WriteLine("Début de calcul")
For NN As Integer = Nmaxi To Nmaxi
Urnes(0) = 3 * NN : Urnes(1) = 0 : Urnes(2) = 0
De(0) = 0 : Vers(0) = 0
NiveauP(NN, 1) 'récursions
Next
wL.WriteLine("Fin de Calcul")
RTB.Text = wL.ToString
wL.Close()
End Sub 'Répartir3N
Sub NiveauP(ByVal NN As Integer, ByVal NP As Integer)
For X As Integer = 0 To 2
For Y As Integer = 0 To 2
If X <> Y AndAlso Urnes(X) >= NP Then
De(NP) = X : Vers(NP) = Y
Urnes(X) -= NP : Urnes(Y) += NP 'transfert
If NP = NN AndAlso Urnes(0) = NN AndAlso Urnes(1) = NN AndAlso Urnes(2) = NN Then
'Si l'on ne veut que les solutions en n étapes,
'ajouter "NP = NN AndAlso " entre if et Urnes(0)
nbSolutions += 1 'Visualiser un résultat
wL.WriteLine("Solution N° " & nbSolutions)
wLignes(NN)
End If
If NP < NN Then NiveauP(NN, NP + 1)
Urnes(X) += NP : Urnes(Y) -= NP 'annuler transfert
End If
Next
Next
End Sub 'NiveauP
Sub wLignes(ByVal NN As Integer)
Dim U(2) As Integer
U(0) = 3 * NN : U(1) = 0 : U(2) = 0
For ii = 0 To NN
U(De(ii)) -= ii
U(Vers(ii)) += ii
Dim Texte As String = "n=" & NN & vbTab & " p=" & ii _
& vbTab & " de " & De(ii) _
& " vers " & Vers(ii) _
& vbTab & " en 0: " & U(0) _
& vbTab & " en 1: " & U(1) _
& vbTab & " en 2: " & U(2)
wL.WriteLine(Texte)
Next
End Sub 'wLignes
End Module
#2 22-04-2011 16:16:54
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 16 948
Re : [VBasic puis Python] Pour l'enigme "Vases communicants" de freddy
Re,
Merci, je vais étudier ça...
Je ne pensais pas que VB était aussi verbeux : ça ne va pas être de la tarte...
Donc tu as un "Module Urnes" et les Sub sont des procédures, des sous-prog dans les Basic que je connais, on y rentrais par Sub(paramètres), voire Gosub et alors il y avait un Return à la fin.
Comment on rentre dans ton prog ? Ou plus exactement, tu lui passes la valeur de nn où ? Comment ?
Tu appelles Sub wLignes(5) par exemple ?
Autant de personnes, autant d'habitudes de programmations..
Moi je veux faire :
def machin(paramètres):
return (valeurs)
def truc(paramètres):
appel de machin(paramètres)
return(valeurs)
# prog principal
Entrée demandée du paramètre n ou directement n = ...
Initialisation des états des urnes
valeurs = machin(paramètres)
print valeurs
Je ne sais pas si je vais arriver déjà à réaliser un organigramme détaillé de ce que te fais ton prog.
Je vais essayer mais j'en doute...
Pourtant, en Turbo Basic, j'avais écrit un programme de calculs astrologiques complet, un programme de calcul des éclipses de lune à venir transcrits du Basic Amstrad CPC 6128 en GFA BAsic (pour Atari) puis en Turbo Basic, de même qu'un prog de calculs financiers que j'ai depuis retraduit en Python, du Basic Amstad, vers Turbo Basic puis Python mes prog de calculs de carrés magiques : donc j'ai quand même une certaine expérience en la matière, mais l'âge aidant, on se rouille...
Je vais essayer. Je ne rendrai les armes qu'en dernier recours...
@+
Arx Tarpeia Capitoli proxima...
Hors ligne
#3 23-04-2011 12:44:55
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 16 948
Re : [VBasic puis Python] Pour l'enigme "Vases communicants" de freddy
Re,
Je commence à démêler l'écheveau...
Je présume que la ligne VB :
For NN As Integer = Nmaxi To Nmaxi
deviendra en Python :
for nn in range(nmaxi,nmaxi+1)
pour qu'il y ait au moins une itération...
Mais pour l'instant je n'ai pas pigé pourquoi nn=nmaxi ne suffirait puisque la boucle est inutile s'il n'y a qu'un tour...
Ou alors, c'est que VB se comporte de façon radicalement différente avec les boucles ?
@+
Arx Tarpeia Capitoli proxima...
Hors ligne
#4 23-04-2011 20:34:14
- totomm
- Invité
Re : [VBasic puis Python] Pour l'enigme "Vases communicants" de freddy
Bonjour,
C'est après quelques essais, pour n'avoir qu'un seul gros résultat sur Nmaxi assez grand (temps de calcul !)
il y avait avant : For NN As Integer = 5 To Nmaxi
Cordialement
#5 23-04-2011 20:57:39
- totomm
- Invité
Re : [VBasic puis Python] Pour l'enigme "Vases communicants" de freddy
Bonjour,
Le VBasic de nos jours est un langage avec tous (ou presque) les atouts du C# ou du C++ : Même langage intermédiaire
Soit on choisit une "application console", mais il faut agir comme avec l'ancien DOS
soit on choisit une application "Windows", c'est-à dire avec une fenêtre et des possibilités de menus, barres d'outils, etc....C'est ce que je fais, mais je remplis la fenêtre avec un "contrôle" TextBox dans lequel je visualise mes résultats.
VBasic est verbeux si on choisit un Typage fort : on y gagne en débogage du programme...
Pour lancer mon programme, le point d'entrée est choisi dans les proriétés de projet et j'y mets un premier appel à ma première procédure
Il n'y a plus depuis longtemps de goto dans les programmes structurés.
les return sont utilisés dans les fonctions et non dans les sub (c'est leur différence)
On se rouille effectivement très vite, car les syntaxes sont trop différentes.
Je me suis mis un peeu à Python qui est très concis, mais j'ai trop d'habitudes avec les langages du Visual Studio.
Cordialement
#6 24-04-2011 19:21:29
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 16 948
Re : [VBasic puis Python] Pour l'enigme "Vases communicants" de freddy
Salut,
Python aussi t'offre la possibilité d'utiliser un environnement graphique : un est livré en standard : Tkinter, d'autres sont téléchargeables : WxPython, PyQt... etc.
Bon, ça y est, j'ai transcrit ton truc.
Mais j'ai un problème d'affichage un peu "farfelu"...
Pour nmaxi=7, j'ai bien Urne A = 7, Urne B = 7, Urne C = 7.
Quand je passe à l'affichage, voilà ce que donne :
p = 0 de A vers A * en A : 21 * en B : 0 * en C : 0 *
p = 1 de A vers B * en A : 20 * en B : 1 * en C : 0 *
p = 2 de A vers B * en A : 18 * en B : 3 * en C : 0 *
p = 3 de A vers B * en A : 15 * en B : 6 * en C : 0 *
p = 4 de A vers B * en A : 11 * en B : 10 * en C : 0 *
p = 5 de A vers B * en A : 6 * en B : 15 * en C : 0 *
p = 6 de A vers B * en A : 0 * en B : 21 * en C : 0 *
p = 7 de B vers C * en A : 0 * en B : 14 * en C : 7 *
Mes tableaux De et Vers sont faux...
J'ai reconstitué les bons à la main, reste à trouver ce qui cloche dans la fonction niveaup0
Ce ne sera pas pour ce soir : j'en ai assez !
@+
Arx Tarpeia Capitoli proxima...
Hors ligne
#7 25-04-2011 08:53:34
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 16 948
Re : [VBasic puis Python] Pour l'enigme "Vases communicants" de freddy
Re,
C'est bon, j'ai corrigé, mais je vais encore réfléchir, parce que pour gérer le compteur de solutions, j'ai dû utiliser une variable globale (c'est le mal !) sinon, à chaque appel de fonction il repartait à zéro ! Pas satisfaisant.
# -*- coding: Latin-1 -*-
## Version 1 ##
def niveaup(nn,np,Urne,De,Vers):
global sol
for x in xrange(3):
for y in xrange(3):
if x!=y and Urne[x]>=np:
De[np],Vers[np]=x,y
Urne[x]-=np
Urne[y]+=np
if np==nn and Urne==[nn,nn,nn]:
sol+=1
print " ---> Solution n°",sol,"<---"
Affiche_resultats(nn,De,Vers)
if np<nn:
niveaup(nn,np+1,Urne,De,Vers)
Urne[x]+=np
Urne[y]-=np
return
def Affiche_resultats(nn,De,Vers):
U=[nn*3,0,0]
for i in xrange(1,nn+1):
U[De[i]]-=i
U[Vers[i]]+=i
print "p =",i,"de ",'ABC'[De[i]],"vers ",'ABC'[Vers[i]],\
" * en A : %2i " % U[0],"* en B : %2i " % U[1],"* en C : %2i " % U[2],"*"
print
# Programme principal
global sol
nmaxi,sol=5,0
De,Vers=[0]*(nmaxi+1),[0]*(nmaxi+1)
print " ##########################"
print " # Début du calcul #"
print " ##########################"
print
nn=nmaxi
Urne=[nn*3,0,0]
niveaup(nn,1,Urne,De,Vers)
print
print " # Fin du calcul #"
Alors pour nmaxi = 5, j'ai 2 solutions, pour 6 j'en ai 4, pour 7 j'en ai 16, pour 8 j'en ai 40, pour 9 j'arrive à 78...
Les urnes B et C (1 et 2 pour toi) étant interchangeables, il doit y avoir des solutions symétriques et donc non réellement diofférentes...
Je vais regarder tout ça, mais aussi tâcher d'améliorer le programme je n'ai que de la copie (presque) servile...
@+
@+
Arx Tarpeia Capitoli proxima...
Hors ligne
#8 27-04-2011 10:06:01
- totomm
- Invité
Re : [VBasic puis Python] Pour l'enigme "Vases communicants" de freddy
Bonjour,
Oui, il faudrait arriver à réduire les solutions en doublons (les urnes à 0 au départ sont interchangeables)
J'ai publié 56 et 104 solutions pour n = 8 et 9 mais avec des solutions où les 3 urnes étaient égales AVANT l'étape finale n.
Comme j'ai maintenant un algorithme (rapide) valable pour tout N (de la forme 3k-1, 3k ou 3k+1) qui utilise par récurrence des solutions "particulières" pour n de 6 à 20, j'incluerai la détermination de ces solutions de base dans l'algorithme général en Python que je publierai en mai
Cordialement
#9 11-05-2011 16:17:34
- totomm
- Invité
Re : [VBasic puis Python] Pour l'enigme "Vases communicants" de freddy
Bonjour,
@yoshi : Code promis. ATTENTION Python version 3.2
vous choisissez le nombre n en début du code.
Cordialement.
# 3 urnes, 3*n billes, Transfert de p billes pour p de 1 à n
#d'une urne dans une autre pour obtenir n, n, n dans les 3 urnes
nchoisi=45 #Nombre choisi
#*****************************************************************************
global dl # dernière ligne vue
global récurrence # un stack
#*****************************************************************************
def Voir(p,a,b,c,t, suite):
# p est le Numéro du transfert (et son contenu), a b et c les urnes,
# t contient les définitions des transferts,
# suite =1 si une suite doit veir en remontant la récurrence
if t[0]<0: print("n =",-t[0]," : Pas de solution")
somme=a+b+c # somme de contrôle de validité
q=len(t)-suite # nombre d'étapes à franchir
for ii in range(p+1,p+q):
v=t[ii-p]
if v==1: a,b = a-ii,b+ii #Codage des 6 mouvements possibles
elif v==2: a,c = a-ii,c+ii
elif v==3: b,c = b-ii,c+ii
elif v==-1: a,b = a+ii,b-ii
elif v==-2: a,c = a+ii,c-ii
elif v==-3: b,c = b+ii,c-ii
else: print("erreur de définition étape",ii)
# Validité de chaque ligne
if a<0 or b<0 or c<0 or (a+b+c)!=somme: Print("ERREUR, LIGNE NON VALIDE")
print("p:%5i"%(ii)," %5i"%a,"%5i"%b,"%5i"%c)
return [p+q,a,b,c] #p+q est le numéro de l'étape suivante
#****************************************************************************
def RèglesdeTransferts(nn):
# nn est le numéro de la dernière ligne (contenu des urnes)
# récurrence est un stack (global) qui contient les numéros de la récurrence
global dl #dl[0] contient l'étape à atteindre,#dl[1] dl[2]et dl[3] les urnes a b et c
global récurrence
#Caractéristiques des 7 familles
v=[0,0,2,2,4,4,3]
ChangeBC=[0,1,0,1,0,1,1] # 1 si transfert entre b et c à la première étape
#4 paramètres pour définir les règles
k,i=(nn-3)//7,(nn-3)%7 # nn=7k+3+i
pp=5*k+v[i] # pp Numéro de la récurrence
bb=dl[2] # >0 si le coté utilisé était b (par opposition à c)
# Définir T (de,vers) pour chaque famille pour la fonction Voir
# indexer par i le codage des transferts
tdébut0 = [[pp,2,2,2],[pp,-3,1,1,1],[pp,2,2],[pp,-3,1,1],
[pp,2,2,2],[pp,-3,1,1],[pp,-3,1,1]]
tdébut1 = [[pp,1,1,1],[pp,3,2,2,2],[pp,1,1],[pp,3,2,2],
[pp,1,1,1],[pp,3,2,2],[pp,3,2,2]]
moinsE = [7,7,5,5,5,3,7]
tmoins0 = [[-2,2],[-2,2],[2,-2],[2,-2],[-2,2],[2,-2],[2,-2]]
tmoins1 = [[-1,1],[-1,1],[1,-1],[1,-1],[-1,1],[1,-1],[1,-1]]
tfin0 = [[-2,-2,-2,2,1],[-2,-2,-2,2,1],[-2,2,-2,1],[-2,2,-2,1],
[-2,-2,1],[-2,1],[-2,2,-2,-2,2,1]]
tfin1 = [[-1,-1,-1,1,2],[-1,-1,-1,1,2],[-1,1,-1,2],[-1,1,-1,2],
[-1,-1,2],[-1,2],[-1,1,-1,-1,1,2]]
if bb==0:
T = tdébut0[i] # -3 vaut (c vers b), 1 vaut (a vers b)
if ChangeBC[i]: bb=1
else:
T = tdébut1[i] # 3 vaut (b vers c), 2 vaut (a vers c)
if ChangeBC[i]: bb=0
nbE=(nn-pp-moinsE[i]-ChangeBC[i])//2
for j in range(0,nbE): #nbE fois
if bb==0: T += tmoins0[i]
else: T += tmoins1[i]
# les dernières étapes pour arriver en n-1 sont ....
# et (dernière ligne si pas de suite qui viendrait de la récurrence)
if bb==0: T += tfin0[i]
else: T += tfin1[i]
if len(récurrence)==0:
dl=Voir(pp-1,dl[1],dl[2],dl[3],T,0)
else:
dl=Voir(pp-1,dl[1],dl[2],dl[3],T,1)
#print("dd",nn,k,i,pp,cvb,dl,récurrence) #constater le pop
#Programme principal********************************************
#Valeurs initiales pour n de 1 à 11.
transferts1_11 = [[-1],[-1],[-2],[3,1,1,2],[-4],[5,1,1,1,1,3],
[6,2,1,1,3,-3,2],[7,1,2,2,-2,2,-3,2],[8,1,1,1,-1,1,-1,1,2],
[9,1,1,1,2,3,2,-2,-3,2],[10,1,1,1,2,-1,2,2,-2,-3,2], \
[11,1,1,1,1,1,-1,-1,1,-1,1,2]]
v=[0,0,2,2,4,4,3] # caractérise les 7 familles
for n in range(nchoisi,nchoisi+1):
if n>11:
récurrence=[n]
k,i=(n-3)//7,(n-3)%7
nr=5*k+v[i]
récurrence.append(nr)
while nr > 11:
k,i=(nr-3)//7,(nr-3)%7
nr=5*k+v[i]
récurrence.append(nr)
if n>11:
print("n =",n," : Total =",3*n," récurrence :",récurrence)
while len(récurrence) > 0:
popR=récurrence.pop()
if popR<12:
dl=Voir(0,3*n,0,0,transferts1_11[popR],1)
else:
RèglesdeTransferts(popR)
else:
print("n =",n," : Total =",3*n)
dl=Voir(0,3*n,0,0, transferts1_11[n],0)
print("Fin du programme principal")
#10 12-05-2011 17:08:14
- totomm
- Invité
Re : [VBasic puis Python] Pour l'enigme "Vases communicants" de freddy
Bonsoir,
J'ai provoqué volontairement une erreur sur une urne et vu que dans le code de la procédure Voir, 3 lignes avant la fin, il y a Print au lieu de print (l'habitude des majuscules en VBasic...)
C'est la seule expression qui soit "inutilisée" dans ce programme.
Cordialement
#11 12-05-2011 18:37:45
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 16 948
Re : [VBasic puis Python] Pour l'enigme "Vases communicants" de freddy
salut,
Pas de lézard, j'avais vu le print.
Pas encore testé.
Mais en principe ton code en Python 2.6 ou 2.7 en remplaçant seulement print(blablabla) par print...
@+
Arx Tarpeia Capitoli proxima...
Hors ligne