OVH Cloud OVH Cloud

Fonction Recursive

16 réponses
Avatar
Jessy Sempere [MVP]
Bonjour à tous

J'ai fais un bout de code sous Access donc en VBA...

Ce code utilises une fonction récursive qui marche très bien, par contre
elle a 2 arguments :
- un de type string,
- et un tableau.

Les 2 évolues en fonction du niveau de récursivité.

Le problème est la lenteur de cette récursivité, pour éventuellement
accélérer tout ça, j'ai retranscrit
mon code en VB sous visual studio .net...

A mon grand désespoir, la récursivité pour l'argument de type string
fonctionne mais par celle pour l'argument tableau, celui-ci ne garde par ses
valeurs en fonction du son niveau de récursivité ???

Ma question est donc peut-on faire sous VB une fonction récursive avec un
argument tableau où est-ce impossible ???

Merci à tous de vos lumière.

@+
Jessy Sempere - Access MVP
news@access.fr.vu
------------------------------------
Site @ccess : http://access.jessy.free.fr/
Pour l'efficacité de tous :
http://www.mpfa.info/
------------------------------------

10 réponses

1 2
Avatar
Fred
Dans : news:
Jessy Sempere [MVP] écrit :
Bonjour à tous



Bonjour,

[...]

Ma question est donc peut-on faire sous VB une fonction récursive
avec un argument tableau où est-ce impossible ???



Probablement un problème de passage de paramètres.
Peut-on voir un bout de code ?


--
Fred
http://www.cerbermail.com/?3kA6ftaCvT
Avatar
Jean-Marc
"Jessy Sempere [MVP]" a écrit dans le
message de news:
Bonjour à tous

J'ai fais un bout de code sous Access donc en VBA...

Ce code utilises une fonction récursive qui marche très bien, par


contre
elle a 2 arguments :
- un de type string,
- et un tableau.

Les 2 évolues en fonction du niveau de récursivité.

Le problème est la lenteur de cette récursivité, pour éventuellement
accélérer tout ça, j'ai retranscrit
mon code en VB sous visual studio .net...

A mon grand désespoir, la récursivité pour l'argument de type string
fonctionne mais par celle pour l'argument tableau, celui-ci ne garde


par ses
valeurs en fonction du son niveau de récursivité ???

Ma question est donc peut-on faire sous VB une fonction récursive avec


un
argument tableau où est-ce impossible ???



Hello,

Non, pas de problème avec les tableaux.
j'ai fait un exemple débile, c'est sans doute
le calcul de factorielle le plus stupide de la terre,
mais ça illustre le propos :-))

Le princpipe: on calcule la fonction factorielle en passant
2 paramètres, une chaine et un tableau.
La chaine contient le résultat temporaire (initialisé à "1") et
le tableau contient les valeurs des entiers à multiplier. -1 sert
de marqueur de fin de tableau.

Ca donne:
"1" (1 ,2 ,3 ,4 ,5 ,-1)
"1" (2 ,3 ,4 ,5 ,-1,-1)
"2" (3 ,4 ,5 ,-1,-1,-1)
"6" (4 ,5 ,-1,-1,-1,-1)
"24" (5 ,-1,-1,-1,-1,-1)
"120" (-1,-1,-1,-1,-1,-1)

et voila :-)

' 8<----------------------------------
Private Sub Command1_Click()
Dim result As String
Dim tablo(6) As Long
Dim i As Long


result = "1"
tablo(1) = 1
tablo(2) = 2
tablo(3) = 3
tablo(4) = 4
tablo(5) = 5
tablo(6) = -1

Call stupid_fact(result, tablo())

Debug.Print result
For i = 1 To 5
Debug.Print tablo(i); " ";
Next i
Debug.Print

End Sub

Private Sub stupid_fact(result As String, t() As Long)
Dim i As Long
Dim n As Long

If t(1) = -1 Then
Exit Sub
End If
result = Trim$(Str$(Val(result) * t(1)))
n = 2
Do
t(n - 1) = t(n)
If t(n) = -1 Then
Exit Do
End If
n = n + 1
Loop
Debug.Print result
For i = 1 To 5
Debug.Print t(i); " ";
Next i
Debug.Print
Call stupid_fact(result, t())
End Sub

' 8<----------------------------------



--
Jean-marc
Tester mon serveur (VB6) => http://myjmnhome.dyndns.org
"There are only 10 kind of people
those who understand binary and those who don't."
mailto: remove '_no_spam_' ;
Avatar
X
Bonjour,

Je ne sais pas si j'ai tout compris, surtout sans code, ta fonction est
récursive, elle s'appelle elle-même... Et c'est un tableau "x(y)" qui freine
les performances...

Tout dépend comment et avec quoi est chargé le tableau, tout dépend s'il est
nécessaire de le recharger à chaque appel, et s'il est chargé par des
objets, on peut, peut être transférer dans des variables qui seront plus
rapides...

------
Site logiciels
http://irolog.free.fr
Mail
http://irolog.free.fr/ecrire/index.htm
Site perso
http://irolog.free.fr/joe/index.htm
Pincipe d'utilisation des news Groups
http://support.microsoft.com/directory/worldwide/fr/newsgroup/regles.htm
------------------------------------------------------------------------------------
"Jessy Sempere [MVP]" a écrit dans le message de
news:
Bonjour à tous

J'ai fais un bout de code sous Access donc en VBA...

Ce code utilises une fonction récursive qui marche très bien, par contre
elle a 2 arguments :
- un de type string,
- et un tableau.

Les 2 évolues en fonction du niveau de récursivité.

Le problème est la lenteur de cette récursivité, pour éventuellement
accélérer tout ça, j'ai retranscrit
mon code en VB sous visual studio .net...

A mon grand désespoir, la récursivité pour l'argument de type string
fonctionne mais par celle pour l'argument tableau, celui-ci ne garde par
ses
valeurs en fonction du son niveau de récursivité ???

Ma question est donc peut-on faire sous VB une fonction récursive avec un
argument tableau où est-ce impossible ???

Merci à tous de vos lumière.

@+
Jessy Sempere - Access MVP

------------------------------------
Site @ccess : http://access.jessy.free.fr/
Pour l'efficacité de tous :
http://www.mpfa.info/
------------------------------------




Avatar
Vincent Guichard
Jessy Sempere [MVP] a écrit :
Bonjour à tous


Bonjour,

[...] j'ai retranscrit mon code en VB sous visual studio .net...



Comme indiqué par Jean-Marc, cela marche très bien en VB6. Ensuite, pour
VB.Net, ce n'est pas sûr. Il y a pas mal de différences entre VB.Net et
VB6. De mémoire, le code vb pour acces est proche de celui de vb6, mais
doit donc être différent de celui de VB.Net. Si tu tiens à programmer en
VB.Net, les membres du forum qui lui est dédié pourront probablement
t'aider.

Vincent Guichard
Avatar
Jessy Sempere [MVP]
Bonjour

Merci à tous de m'avoir répondu...

Premièrement, effectivement je pense que j'ai eu la maladresse de penser que
le vb .net était similaire à VB...
Sinon, je n'ai pas le code que j'ai adapter chez moi pour VB .NET, par
contre j'ai mon code VBA, je vais le réduire un maximum pour aller à
l'essentiel et montrer son fonctionnement :
Le but, c'est de comparer une matrice et de voir quelle combinaison peuvent
se couvrir mutuellement, exemple d'une matrice à comparer :

1 2 3 4 5 6 7 8 9 10 11 12
----------------------------------------------------------
1 1 1 1 0 1 0 1 0 0 0 0 0
2 1 1 0 1 0 1 0 1 0 0 0 0
3 1 0 1 1 1 0 0 0 1 0 0 0
4 0 1 1 1 0 1 0 0 0 1 0 0
5 1 0 1 0 1 1 0 0 0 0 1 0
6 0 1 0 1 1 1 0 0 0 0 0 1
7 1 0 0 0 0 0 1 1 1 0 1 0
8 0 1 0 0 0 0 1 1 0 1 0 1
9 0 0 1 0 0 0 1 0 1 1 1 0
10 0 0 0 1 0 0 0 1 1 1 0 1
11 0 0 0 0 1 0 1 0 1 0 1 1
12 0 0 0 0 0 1 0 1 0 1 1 1

Donc cette matrice sera déclarée en globale dans le code, le but de la
fonction, c'est de combiner la colonne 1 avec la 2 et de vérifier que la
somme de chaque ligne soit différente de 0, si on a 0, on combine alor la 1
avec la 3, ensuite la 1 avec la 4... ensuite, 2 et 3, 2 et 4, ...
Si on a rien, on va descendre d'un niveau et combiner la 1 et 2 avec la 3,
la 1 et 2 avec la 4,... , 1 et 3 avec la 4, 1 et 3 avec la 5, ...

Bon, pour chaque matrice par contre, je déterminer dès le départ le nombre
de combinaison minimum, ici, c'est 3, et pour ce cas les solutions sont :
1;3;12 ou 1;5;10 ou 1;10;12 ou 2;4;11 ou 2;6;9 ou 2;9;11 ou 3;5;8 ou 3;8;12
ou 4;6;7 ou 4;7;11 ou 5;8;10 ou 6;7;9

Voici donc à la grosse ce que fais la fonction récursive sous VBA et elle
fonctionne. Mais, bon, pour ce cas, c'est très rapide mais quand elle fait
200 par 200 avec comme combinaison mimimum, 23 niveau de regroupement, là,
ça ne plante pas, mais c'est très long... D'où, le faire sur un autre
language ???

Voici le code VBA (pas complet) mais qui ne marche pas après conversion sous
VB .NET :

'Déclaration de variables globales :
Dim lngCombi as long 'nombre de niveaux de récursivité
dim tabResult() as integer 'tableaux de comparaison (matrice de l'exemple
supérieur)
dim tabSolution() as string
dim lngSolution as long
dim lngAllGrille as long

function lancement()
lngcombi = 3
lngallgrille
tabresult() = matrice de l'exemple
redim tabcombi(1 to lngallgrille) 'tableau avec une dimension avec que des 0
frecursive_combinaison 1,1,"", tabcombi

end function

Function fRecursive_Combinaison(x, ind, strCombi As String, tabCombi() As
Integer)
'** Fonction récursive pour les combinaisons
Dim lngResult As Long
Dim tabCombi_tmp() As Integer
Dim strCombi_tmp As String

tabCombi_tmp = tabCombi
strCombi_tmp = strCombi

For b = x To lngAllGrille
lngResult = 0
If strCombi_tmp = "" Then
strCombi = b
Else
strCombi = strCombi_tmp & ";" & b
End If

If ind < lngCombi Then
For c = 1 To lngAllGrille
If tabCombi_tmp(c) + tabResult(b, c) = 0 Then
tabCombi(c) = 0
Else
tabCombi(c) = 1
End If
Next
fRecursive_Combinaison b + 1, ind + 1, strCombi, tabCombi
Else
'** resultat
For c = 1 To lngAllGrille
If tabCombi_tmp(c) + tabResult(b, c) <> 0 Then
lngResult = lngResult + 1
Else
Exit For
End If
Next
If lngResult = lngAllGrille Then
'** Chargement d'une solution dans le tableau tabSolution
lngSolution = lngSolution + 1
ReDim Preserve tabSolution(1 To lngSolution)
tabSolution(lngSolution) = strCombi
End If
End If
Next

End Function

Merci
--
@+
Jessy Sempere - Access MVP

------------------------------------
Site @ccess : http://access.jessy.free.fr/
Pour l'efficacité de tous :
http://www.mpfa.info/
------------------------------------
"Vincent Guichard" a écrit dans le message de
news:43f449a3$0$18325$
Jessy Sempere [MVP] a écrit :
> Bonjour à tous
Bonjour,

> [...] j'ai retranscrit mon code en VB sous visual studio .net...

Comme indiqué par Jean-Marc, cela marche très bien en VB6. Ensuite, pour
VB.Net, ce n'est pas sûr. Il y a pas mal de différences entre VB.Net et
VB6. De mémoire, le code vb pour acces est proche de celui de vb6, mais
doit donc être différent de celui de VB.Net. Si tu tiens à programmer en
VB.Net, les membres du forum qui lui est dédié pourront probablement
t'aider.

Vincent Guichard


Avatar
Vincent Guichard
Jessy Sempere [MVP] a écrit :
[...]

La question en fait, c'est "Programmes-tu en VB6 ou VB.Net?"
Si tu programmes en VB6, on pourra essayer de répondre à ta question. Si
tu programmes en VB.Net, il y a de forte chances que les réponses que tu
obtiendra ici soient bancales ou inadaptées, le forum consacré à VB.Net
étant: news://microsoft.public.fr.dotnet.vb

Vincent Guichard
Avatar
Jessy Sempere [MVP]
Re,
"Vincent Guichard" a écrit :
La question en fait, c'est "Programmes-tu en VB6 ou VB.Net?"
Si tu programmes en VB6, on pourra essayer de répondre à ta question. Si
tu programmes en VB.Net, il y a de forte chances que les réponses que tu
obtiendra ici soient bancales ou inadaptées, le forum consacré à VB.Net
étant: news://microsoft.public.fr.dotnet.vb



Vu que je programme en VBA, je n'ai pas d'appriori, si VB6 peut me permettre
de générer un executable aussi rapide que du C ou du C++, y'a pas de souci,
je le ferais en VB6...

Par contre, c'est vrai que le problème que je soumettais, concernait VB.
NET.
Donc si VB6 est aussi rapide que VB. NET, et que ma récursivité fonctionne
avec un argument tableau, j'essaierais de la faire en VB6.

Merci à toi

@+
Jessy Sempere - Access MVP

------------------------------------
Site @ccess : http://access.jessy.free.fr/
Pour l'efficacité de tous :
http://www.mpfa.info/
------------------------------------
Avatar
Vincent Guichard
Jessy Sempere [MVP] a écrit :
Bonjour


re,

Quel est la rapidité escomptée?

Après quelques rapides modification de ton code (cf ci-dessous), et sans
optimisations (j'utilise plein de variants...) j'exécute la fonction
fRecursive_Combinaison 10000 fois en environ 33 secondes* sur l'exemple
que tu donnes? Est assez rapide ou pas? Quels sont les temps que tu
obtient en VBA sous access?

Vincent Guichard

*La mesure est vraiment pas précise, et je sais que c'est pas comme ça
qu'on doit faire un benchmark

Code utilisé pour le test rapide:

Option Explicit
Option Base 1


'Déclaration de variables globales :
Dim lngCombi As Long 'nombre de niveaux de récursivité
Dim tabResult() 'tableaux de comparaison (matrice de l'exemple supérieur)
Dim tabSolution() As String
Dim lngSolution As Long
Dim lngAllGrille As Long

Sub Form_Load()
lngCombi = 3
lngAllGrille = 12
tabResult() = Array( _
Array(1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0), _
Array(1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0), _
Array(1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0), _
Array(0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0), _
Array(1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0), _
Array(0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1), _
Array(1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0), _
Array(0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1), _
Array(0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0), _
Array(0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1), _
Array(0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1), _
Array(0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1))
Dim a As Integer
Debug.Print Timer, Now
For a = 0 To 10000
ReDim tabCombi(1 To lngAllGrille) As Integer 'tableau avec une dimension
avec que des 0
fRecursive_Combinaison 1, 1, "", tabCombi
Next a
Debug.Print Timer, Now

End Sub

Function fRecursive_Combinaison(x, ind, strCombi As String, tabCombi()
As Integer)
'** Fonction récursive pour les combinaisons
Dim lngResult As Long
Dim tabCombi_tmp() As Integer
Dim strCombi_tmp As String
Dim b As Integer
Dim c As Integer
tabCombi_tmp = tabCombi
strCombi_tmp = strCombi

For b = x To lngAllGrille
lngResult = 0
If strCombi_tmp = "" Then
strCombi = b
Else
strCombi = strCombi_tmp & ";" & b
End If

If ind < lngCombi Then
For c = 1 To lngAllGrille
If tabCombi_tmp(c) + tabResult(b)(c) = 0 Then
tabCombi(c) = 0
Else
tabCombi(c) = 1
End If
Next
fRecursive_Combinaison b + 1, ind + 1, strCombi, tabCombi
Else
'** resultat
For c = 1 To lngAllGrille
If tabCombi_tmp(c) + tabResult(b)(c) <> 0 Then
lngResult = lngResult + 1
Else
Exit For
End If
Next
If lngResult = lngAllGrille Then
'** Chargement d'une solution dans le tableau tabSolution
lngSolution = lngSolution + 1
ReDim Preserve tabSolution(1 To lngSolution)
tabSolution(lngSolution) = strCombi
End If
End If
Next

End Function
Avatar
Jessy Sempere [MVP]
Re,

Merci de t'interesser à mon problème...
J'ai fais un test avec le même code que toi, et j'obtiens 47 secondes
Si tu veux, je peux t'envoyer une matrice qui fais 54 sur 54...
Perso je l'ai lancé sous VBA et je n'ai pas planté mais après quelques
heures j'ai arrêté le code...

PS : Je pense savoir d'où viens mon problème sous VB.NET, il me semble qu'en
VBA et VB6, les arguments d'une fonction sont passer par défaut par
référence, hors quand j'ai retranscris mon code, mes arguments sont passer
par valeur (byVal) ???

@+
Jessy Sempere - Access MVP

------------------------------------
Site @ccess : http://access.jessy.free.fr/
Pour l'efficacité de tous :
http://www.mpfa.info/
------------------------------------
"Vincent Guichard" a écrit dans le message de
news:43f48392$0$6682$
Jessy Sempere [MVP] a écrit :
> Bonjour
re,

Quel est la rapidité escomptée?

Après quelques rapides modification de ton code (cf ci-dessous), et sans
optimisations (j'utilise plein de variants...) j'exécute la fonction
fRecursive_Combinaison 10000 fois en environ 33 secondes* sur l'exemple
que tu donnes? Est assez rapide ou pas? Quels sont les temps que tu
obtient en VBA sous access?

Vincent Guichard

*La mesure est vraiment pas précise, et je sais que c'est pas comme ça
qu'on doit faire un benchmark

Code utilisé pour le test rapide:

Option Explicit
Option Base 1


'Déclaration de variables globales :
Dim lngCombi As Long 'nombre de niveaux de récursivité
Dim tabResult() 'tableaux de comparaison (matrice de l'exemple supérieur)
Dim tabSolution() As String
Dim lngSolution As Long
Dim lngAllGrille As Long

Sub Form_Load()
lngCombi = 3
lngAllGrille = 12
tabResult() = Array( _
Array(1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0), _
Array(1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0), _
Array(1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0), _
Array(0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0), _
Array(1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0), _
Array(0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1), _
Array(1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0), _
Array(0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1), _
Array(0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0), _
Array(0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1), _
Array(0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1), _
Array(0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1))
Dim a As Integer
Debug.Print Timer, Now
For a = 0 To 10000
ReDim tabCombi(1 To lngAllGrille) As Integer 'tableau avec une dimension
avec que des 0
fRecursive_Combinaison 1, 1, "", tabCombi
Next a
Debug.Print Timer, Now

End Sub

Function fRecursive_Combinaison(x, ind, strCombi As String, tabCombi()
As Integer)
'** Fonction récursive pour les combinaisons
Dim lngResult As Long
Dim tabCombi_tmp() As Integer
Dim strCombi_tmp As String
Dim b As Integer
Dim c As Integer
tabCombi_tmp = tabCombi
strCombi_tmp = strCombi

For b = x To lngAllGrille
lngResult = 0
If strCombi_tmp = "" Then
strCombi = b
Else
strCombi = strCombi_tmp & ";" & b
End If

If ind < lngCombi Then
For c = 1 To lngAllGrille
If tabCombi_tmp(c) + tabResult(b)(c) = 0 Then
tabCombi(c) = 0
Else
tabCombi(c) = 1
End If
Next
fRecursive_Combinaison b + 1, ind + 1, strCombi, tabCombi
Else
'** resultat
For c = 1 To lngAllGrille
If tabCombi_tmp(c) + tabResult(b)(c) <> 0 Then
lngResult = lngResult + 1
Else
Exit For
End If
Next
If lngResult = lngAllGrille Then
'** Chargement d'une solution dans le tableau tabSolution
lngSolution = lngSolution + 1
ReDim Preserve tabSolution(1 To lngSolution)
tabSolution(lngSolution) = strCombi
End If
End If
Next

End Function






Avatar
Clive Lumb
"Jessy Sempere [MVP]" a écrit dans le message de
news:
Re,

Merci de t'interesser à mon problème...
J'ai fais un test avec le même code que toi, et j'obtiens 47 secondes
Si tu veux, je peux t'envoyer une matrice qui fais 54 sur 54...
Perso je l'ai lancé sous VBA et je n'ai pas planté mais après quelques
heures j'ai arrêté le code...

PS : Je pense savoir d'où viens mon problème sous VB.NET, il me semble


qu'en
VBA et VB6, les arguments d'une fonction sont passer par défaut par
référence, hors quand j'ai retranscris mon code, mes arguments sont passer
par valeur (byVal) ???



Dans le mille !!!
1 2