Excel VBA doppelte Zahlen bei Zufallszahlen

elman

Grünschnabel
Hallo, wer kann mir im folgendem Code so änder dass es keine doppelte Zahlen mehr in einer Zeile gibt.
Danke schon mal fü eure Hilfe.
Visual Basic:
Private Sub ZufallsZahlen(Bereich As Range, ByVal Von As Long, _
ByVal Bis As Long)
Dim vx() As Variant, i As Long, k As Integer
On Error GoTo Fehler
Randomize Timer
With Bereich
  ReDim vx(.Rows.Count - 1)
  ReDim vx(.Rows.Count - 1, .Columns.Count - 1)
  For i = 1 To .Rows.Count
    For k = 1 To .Columns.Count
      vx(i - 1, k - 1) = Int((Bis - Von + 1) * Rnd + Von)
    Next k
  Next i
  .Value = vx()
End With
'Sortieren
For i = 1 To Bereich.Rows.Count
  Bereich.Rows(i).Sort Bereich.Rows(i).Cells(1), Orientation:=2
Next
Exit Sub
Fehler:
MsgBox "Fehler: " & vbCrLf & Err.Description
End Sub
 
Zuletzt bearbeitet von einem Moderator:

Sempervivum

Erfahrenes Mitglied
wer kann mir im folgendem Code so änder dass es keine doppelte Zahlen mehr in einer Zeile gibt.
Das kann ich leider nicht, da keine Ahnung von VBA. Aber das generelle Problem tritt häufig auf und eine einfache Lösung besteht darin, das betr. Array zunächst zu mischen ("shuffle") und dann einfach die Elemente nacheinander vom Anfang auszulesen. Dann bekommst du keine Dubletten. Algorithmus zum Mischen findest Du z. B. hier:
how to shuffle array in VB?
 

Zvoni

Erfahrenes Mitglied
Doppelte Zahlen in einer Lotterie kann nur passieren, wenn du mit "Zurücklegen" spielst, also sitzt da der Hase im Pfeffer.
Wenn die Reihenfolge wichtig ist --> Permutation
Wenn die Reihenfolge nicht wichtig ist --> Kombination

Da du sortieren willst, ist die Reihenfolge egal, also eine Kombination.
Du willst keine Duplikate, also ohne Zurücklegen/Wiederholung
Ist ganz klassisches Lotto-Spiel.
Siehe meinen Link.
Wenn du ein "Von-Bis"-Szenario brauchst gib Bescheid
(Beispiel "10 aus 32 bis 58" anstelle von "6 aus 1 bis 49")
 

Sempervivum

Erfahrenes Mitglied
Mein Verfahren in Javascript, das Vermeiden von Dubletten wird nicht mit Zurücklegen sondern durch Mischen des Quellarrays gelöst. Sicherlich ein Leichtes, diesen Algorithmus auf VBA umzuändern.
Code:
        function lotto(
            first, // Start der Zahlenreihe
            last,  // Ende der Zahlenreihe
            nr // Anzahl der gezogenen Zahlen
        ) {
            // Shuffle array in place, source:
            // https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array
            function shuffle(a) {
                var j, x, i;
                for (i = a.length - 1; i > 0; i--) {
                    j = Math.floor(Math.random() * (i + 1));
                    x = a[i];
                    a[i] = a[j];
                    a[j] = x;
                }
                return a;
            }
            // Array mit aufsteigenden Zahlen vorbereiten:
            let src = [];
            for (let i = first; i <= last; i++) {
                src.push(i);
            }
            //
            // Array mischen:
            shuffle(src);
            // Ergebnis auf die geforderte Anzahl von Zahlen reduzieren:
            let result = src.slice(0, nr);
            // und sortieren:
            result.sort((a, b) => {
                return Number(a) - Number(b);
            });
            // Array mit Zufallszahlen zurück geben:
            return result;
        }
        // Ergebnis ausgeben:
        console.log(lotto(1, 39, 6));
 

Zvoni

Erfahrenes Mitglied
Semper,
ich kenne diese Lösung, finde sie aber "unschön", weil
Nehmen wir mal 1000 Elemente
1) Sowohl in deiner Variante als auch in meiner bereiten wir ein Quell-Array vor (Schleife mit 1000 Zuweisungen)
2a) In deiner Variante hast du für das Shuffle wieder eine Schleife mit 1000 Durchläufen (und pro Durchlauf 3 Zuweisungen --> der swap)
2b) in meiner Variante gibts die zweite Schleife nicht, weil die Zufallszahl das Array-Element bestimmt (Nicht den Wert), aus welchem wir den Wert holen. Und ich habe nur zwei weitere Zuweisungen: 1 mal ersetze gezogenes Element mit letztem Element, sowie dekrement der oberen Grenze.
3a) Du holst die Ergebnis-Menge ab, indem du die "nr" ersten Elemente aus dem Array schneidest
3b) ich fülle das Ergebnis-Array per Schleife auf (inkl. meinem Schritt 2b)

Mir ist natürlich klar, dass mit meinem Code ein Aufruf wie "Lotterie 39,39,True,False" ein volles Shuffle darstellt, und ich dann die ersten 6 Elemente davon abholen könnte

Meinungen?
 
Zuletzt bearbeitet:

elman

Grünschnabel
Mein Verfahren in Javascript, das Vermeiden von Dubletten wird nicht mit Zurücklegen sondern durch Mischen des Quellarrays gelöst. Sicherlich ein Leichtes, diesen Algorithmus auf VBA umzuändern.
Code:
        function lotto(
            first, // Start der Zahlenreihe
            last,  // Ende der Zahlenreihe
            nr // Anzahl der gezogenen Zahlen
        ) {
            // Shuffle array in place, source:
            // https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array
            function shuffle(a) {
                var j, x, i;
                for (i = a.length - 1; i > 0; i--) {
                    j = Math.floor(Math.random() * (i + 1));
                    x = a[i];
                    a[i] = a[j];
                    a[j] = x;
                }
                return a;
            }
            // Array mit aufsteigenden Zahlen vorbereiten:
            let src = [];
            for (let i = first; i <= last; i++) {
                src.push(i);
            }
            //
            // Array mischen:
            shuffle(src);
            // Ergebnis auf die geforderte Anzahl von Zahlen reduzieren:
            let result = src.slice(0, nr);
            // und sortieren:
            result.sort((a, b) => {
                return Number(a) - Number(b);
            });
            // Array mit Zufallszahlen zurück geben:
            return result;
        }
        // Ergebnis ausgeben:
        console.log(lotto(1, 39, 6));
Sorry aber ich behersche weder Javascript noch VBA um das zu ändern ... Danke
 

Zvoni

Erfahrenes Mitglied
Das Problem liegt nicht darin, ob du das JavaScript oder mein VBA "ändern" kannst.
Du hast ein grundlegendes Verständnis-Problem wie eine Lotterie von einem mathematischen bzw. logischem Standpunkt aus funktioniert
 

Sempervivum

Erfahrenes Mitglied
Der Vorteil bei meinem Verfahren ist nicht die Schnelligkeit oder Performance sondern dass es sehr einfach und übersichtlich ist und in abgetrennten Schritten verläuft. Die Prozessoren sind heute sehr schnell, so dass die Schnelligkeit eines Algorithmus in den Hintergrund rückt, schon gar bei einem Lottospiel mit ganzen 39 Zahlen. Und die Lesbarkeit eine größere Priorität hat.