Meilleur auteur de réponses
Mélanger un tableau d'entiers

Question
-
Bonjour
J'utilise le code suivant pour mélanger un tableau d'Integer :
Si j'exécute plusieurs fois le mélange, le PC ralentit considérablement je ne comprends pas pourquoi (ceci quel que soit la méthode utilisée)Dim LesUnités() As Integer = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} Try 'Shuffle(LesUnités) ShuffleArray(LesUnités) 'Array.Sort(LesUnités, New Melangeur()) Catch ex As ArgumentException MessageBox.Show(ex.Message) End Try
Private Shared ReadOnly _shuffleRnd As New Random() ' nécessaire pour la méthode ShuffleArray Public Shared Sub ShuffleArray(ByVal array As Integer()) Dim arrayLength As Integer = array.Length ' parcours de la liste en partant de la fin For i As Integer = arrayLength - 1 To 2 Step -1 ' tirage au sort d'un index entre 0 et la valeur courante de "i" Dim randomIndex As Integer = _shuffleRnd.[Next](i) ' intervertion des éléments situés aux index "i" et "randomIndex" Dim temp As Integer = array(i) array(i) = array(randomIndex) array(randomIndex) = temp Next End Sub Public Class Melangeur Implements System.Collections.IComparer Private Shared rnd As Random Shared Sub New() rnd = New Random() End Sub Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare If Object.Equals(x, y) Then Return 0 Else Return rnd.Next(-1, 1) End If End Function End Class Public Shared Function Shuffle(ByVal order As Integer()) As Integer() Dim rnd As Integer Dim val As Integer Dim max As Integer = (order.Length - 1) For i As Integer = 0 To max val = order(i) rnd = RndGen.Next(0, max + 1) order(i) = order(rnd) order(rnd) = val Next Return order End Function
Y a-t-il un meilleur moyen de mélanger un array ?
merci
Cordialement
Pascal
http://www.scalpa.info
Réponses
-
Bonjour
Je ne déclare
Public Shared RndGen As System.Random = New System.Random
qu'au début de la classe.
Puis dans chaque fonction où j'en ai besoin, je fais par exemple
Public Shared Function GenNbreEntier(ByVal low As Integer, _ ByVal high As Integer) As Integer
Dim NbreTire As Integer
NbreTire = Int(RndGen.Next(low, high + 1))
Return NbreTire
Ce n'est pas la bonne méthode?End Function
Cordialement
Pascal
http://www.scalpa.info- Marqué comme réponse scalpa vendredi 6 mai 2011 07:02
Toutes les réponses
-
Si j'exécute plusieurs fois le mélange, le PC ralentit considérablement je ne comprends pas pourquoi (ceci quel que soit la méthode utilisée)
Y a-t-il un meilleur moyen de mélanger un array ?
Bonjour Pascal,
Cette méthode là, un peu différente ne plante pas :
Option Explicit On Public Class Form1 Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim u(10) As Integer ' utilisation de 1 à 10 Dim i As Integer Dim j As Integer For i = 1 To 10 ' 1er remplissage Randomize() u(i) = Int((9 - 0 + 1) * Rnd() + 0) Next i bis: ' fin remplissage si doublons For i = 1 To 10 For j = 1 To 10 If i <> j And u(i) = u(j) Then Randomize() u(j) = Int((9 - 0 + 1) * Rnd() + 0) GoTo bis End If Next j Next i End Sub End Class
' NOMBRE PSEUDO ALEATOIRES ' Nombre entiers entre maxi et mini avec un pas de 1 Dim hasard As long Randomize hasard = Int((maxi - mini + 1) * Rnd + mini)
Il y a plein de façons de piquer des nombres pseudo-aléatoires, par exemple du pompe le 1 sur les secondes, le 2 sur les 10eme, le 3, 4, 5 sur les millièmes depuis écoulés depuis le lancement du PC en espaçant de 2, le 6 tu multiplie les heures par les seconde et tu fais une division savante, etc...
Cordialement.
Joe.
Joseph Attila PUSZTAY
EhJoe Logiciels Romans Ecrire
-
Bonjour,
Sur le MSDN il y a des exemples qui fonctionne sans aucun probleme de fonctionne et sans saturé la mémoire
http://msdn.microsoft.com/fr-fr/library/system.random.aspx
A bientot
Cordialement,
Xavier
Alias Troxsa My M@iL -
De plus, si tu utilise le framework 4.0, il existe le Task Parallel Library qui permet d'accélérer ce genre de tâches.
Microsoft MVP C# || gabrielmongeon.com || LinkedIn -
Merci pour vos réponses. Je vais creuser la question... Peut-être que le ralentissement constaté vient d'ailleurs... Est-ce que l'appel répété d'une fonction est "RAM-ovore" par exemple ? faut-il coller un dispose() ou je ne sais quoi quelque part dans le code?
Par exemple :
merci''' <summary> ''' Générateur d'une collection de nombres entiers, uniques ou non. ''' </summary> ''' <param name="Lower">borne inférieure du nombre</param> ''' <param name="Upper">borne supérieure du nombre</param> ''' <param name="HowMany">Combien de nombres?</param> ''' <param name="Unique">Les nombres sont-ils uniques?</param> ''' <returns>Une collection de nombres correspondant aux critères ci-dessus</returns> ''' <remarks>Générateur de nombres</remarks> Public Shared Function GenArrayNbresEntiers(ByVal Lower As Integer, _ ByVal Upper As Integer, _ Optional ByVal HowMany As Integer = 1, _ Optional ByVal Unique As Boolean = True) _ As List(Of Integer) Dim Result As New List(Of Integer) Do Dim Value = GenNbreEntier(Lower, Upper) If Not Unique OrElse Not Result.Contains(Value) Then Result.Add(Value) End If Loop Until Result.Count = HowMany Return Result End Function
Cordialement
Pascal
http://www.scalpa.info -
Bonjour / soir
Je ne pense pas que ça soit RAM-ovore car si on limite sont tableau cela reste quand même de petite taille en mémoire donc pas trop nécessaire de faire un dispose, cela finira dans le GC quand il sera appeler ...
A bientot
Cordialement,
Xavier
Alias Troxsa My M@iL -
Bonjour,
la fonction Randomize() est utile pour initialiser la séquence de nombres aléatoires qui seront renvoyés par Rnd().
(en utilisant l'horloge system comme "graine " pour la séquence)
Vous ne devriez donc n'appeler qu'une seule fois cette fonction et ne pas l'appeler au sein des différentes boucles.
Cordialement
Edit : Effectivement cette remarque ne s'applique pas au code initiale mais aux autres possibilité ou l'on voit la fonction Randomize au sein des boucles- Modifié nikhoModerator mercredi 4 mai 2011 14:47
-
Bonjour
Je ne déclare
Public Shared RndGen As System.Random = New System.Random
qu'au début de la classe.
Puis dans chaque fonction où j'en ai besoin, je fais par exemple
Public Shared Function GenNbreEntier(ByVal low As Integer, _ ByVal high As Integer) As Integer
Dim NbreTire As Integer
NbreTire = Int(RndGen.Next(low, high + 1))
Return NbreTire
Ce n'est pas la bonne méthode?End Function
Cordialement
Pascal
http://www.scalpa.info- Marqué comme réponse scalpa vendredi 6 mai 2011 07:02
-
bonjour,
La méthode est la bonne.
Maintenant tout dépend du type utilser et de la valeur utiliser, là je vois que vous utilisez "integer"
ce qu'il faut connaitre avant d'utiliser Integer c'est les valeur qu'il va recevoir, si les valeurs sont comprise entres -2 147 483 648 à 2 147 483 647 dans ce cas c'est bien ce qu'il faut utiliser et dans ce cas attention a la mémoire cela peux avoir un effet ...si ses valeurs sont trop grande il existe d'autre type plus petit et plus performant, je vous conseil d'aller voir sur le site MSDN, apres c'est a vous de faire l'algo pour que les valeurs entrer ne sorte pas du type sinon il y aura exception ...
A bientot
Cordialement,
Xavier
Alias Troxsa My M@iL