Lottoziehung "6 aus 49"

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
hansen12345
User
Beiträge: 7
Registriert: Montag 23. Januar 2006, 19:56

Die Lottoziehung "6 aus 49" soll (erweiterbar auf beliebige Ziehungen, z.B.:
3 aus 10 oder 10 aus 100) mit Python simuliert werden.
Verwendet werden soll aus dem Modul random die Funktion: randrage() in der einfachen Form randrage(start,stop) als Zufallsgenerator.
Bedacht werden soll, dass nach jeder Ziehung die jeweils gezogene Zahl entfernt wird, so dass diese nicht mehr im Spiel ist. Und außerdem sich die Möglichkeiten nach jeder Ziehung so um 1 Möglichkeit veringern.
Wie in der Lottoziehung mit Lostrommel im Fernsehen.

Bitte um möglichst einfache Lösungsvorschläge mit möglichst einfachen
Programmierbefehlen.
Die eigene Kreativität reicht nur bis zu einer Ziehung von 3 aus 49, jedoch das grosse Geld ist nur mit 6 aus 49 zu holen. Bitte um HIlfe.

gruß
flo
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Code: Alles auswählen

import random

def kugel():
    return random.randrange(1,50)

def ziehung():
    zahlen = set()
    while len(zahlen) < 6:
        zahlen.add(kugel())
    return list(zahlen)
Das ganze zu erweitern auf 10 aus 100 o.Ä. sollte ja nicht schwer sein, wenn man die kostanten findet. ;-)

Kurz noch eine Erklärung dazu: ich habe bis auf das set keinen speziellen Fall für doppelte Ziehungen. Man kann sich das so vorstellen dass ich aus der Lostrommel alle Zahlen gleichhäufig ziehen kann, allerdings wenn eine Zahl kommt die ich bereits hatte, ich diese wegschmeiße und noch einmal ziehe. Damit hab ich für die Zahl die bereits gezogen wurde die Wahrscheinlichkeit 0 dass sie in zahlen reinkommt, für die anderen die Wahrscheinlichkeit 1/(49-len(zahlen)). Und genau das ist Lotto, blos dass man da nicht zurücklegt, also die Ziehung anders gestaltet.

--- Heiko.
hansen12345
User
Beiträge: 7
Registriert: Montag 23. Januar 2006, 19:56

Danke für die prompte Lösung! Die natürlich auch funktioniert.
Jedoch soll in meiner Vorstellung gerade keine Ziehung verworfen werden.
Die jeweils gezogenen Zahlen werden noch vor der nächsten Ziehung aus der Trommel entnommen. Außerdem soll sich nach jeder Ziehung die Auswahl der Kugeln um eine verringern. Also von randrage(1,50) bei der ersten Ziehung, folgen randrage(1,49)....randrage(1,48) .....usw.

Das selbstgestellte Problem kapriziert sich auf die Verwendung der Funktion
randrage(). Was für Erfahrene - wie Heiko - natürlich umständlich und ineffizient ist. Doch es soll eben der Fall gesetz sein, dass dies das ausschließlich zur Verfügung stehende Werkzeug sein soll.

Allein das Problem der Doppelziehung ist streng genommen nicht bewältigt.

Gruß Flo
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Es ist statistisch egal ob ich die "Doppelziehung" wegwerfe und immer 6 aus 49 ziehe, oder aber ob ich jedes mal die Ziehung verkleinere. Ersteres ist einfacher, weil ich sonst eine diskontinuierliche Funktion anwenden muß, ist allerdings erheblich langsamer wenn ich damit rechnen muß dass ich häufig Doppelziehungen kriege, da ich diese umsonst mache (und ein RNG nicht sonderlich schnell ist). In diesem Fall lohnt sich dann folgendes kleines Beispiel das das Ziehen ohne Zurücklegen implementiert, aber schon erheblich länger ist:

Code: Alles auswählen

import bisect
import random

def kugel(gezogen):
    ziehung = random.randrange(1,50-len(gezogen))
    for z in gezogen:
        if z <= ziehung:
            ziehung += 1
        else:
            break
    return ziehung

def ziehung():
    rv = []
    for i in range(6):
        bisect.insort(rv,kugel(rv))
    return rv
Hierbei ist es wichtig dass die Liste an bereits gezogenen Zahlen sortiert ist (sonst funktioniert ziehung() nicht), deswegen der Aufruf von bisect, da das schneller ist als jedes mal die Zahl anzuhängen und die Liste neu zu sortieren (Faktor log2n gegen n*logn). Allerdings hat dieser Algorithmus aufgrund der Zählschleife in ziehung() auch eine deterministische Laufzeit, nämlich 6 Runden.

<edit>Namen an erstes Beispiel angepasst</edit>

--- Heiko.
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Alternativ

Code: Alles auswählen

import random
Zahlen = range(1,50)
random.shuffle(Zahlen)
print "Die Lottozahlen:",Zahlen[:6],"Zusatzzahl",Zahlen[6]
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Noch eine Alternative:

Code: Alles auswählen

import random
print "Lottozahlen: ", random.sample(range(1,50), 6)
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Wobei aber anzumerken ist das ganz egal welches Verfahren man nutzt nicht alle Lotto-Kombinationen gleichwahrscheinlich sind, weil nämlich die Periode des RNG von Python sehr viel kleiner als 50! ist (heißt, manche kommen in einem kompletten Durchlauf des RNG gar nicht vor, andere mehrmals).

--- Heiko.
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

modelnine hat geschrieben:weil nämlich die Periode des RNG von Python sehr viel kleiner als 50! ist
Das wage ich zu bezweifeln:
help random hat geschrieben:General notes on the underlying Mersenne Twister core generator:

* The period is 2**19937-1
50! mit einer Größe von weniger als 2**215 kann da nicht ganz mithalten!
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Humm... Okay, das ist neu. Ein älterer RNG den Python verwendete hatte eine erheblich kleinere Periode. Gut zu wissen. ;-)

--- Heiko.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

modelnine hat geschrieben:Humm... Okay, das ist neu. Ein älterer RNG den Python verwendete hatte eine erheblich kleinere Periode. Gut zu wissen. ;-)
Das ältere whrandom gibts natürlich auch noch.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
KEBA
User
Beiträge: 16
Registriert: Sonntag 20. April 2008, 16:53

Joghurt hat geschrieben:Alternativ

Code: Alles auswählen

import random
Zahlen = range(1,50)
random.shuffle(Zahlen)
print "Die Lottozahlen:",Zahlen[:6],"Zusatzzahl",Zahlen[6]
Dann hat man den Bug, dass die Zahlen - anders als beim Lotto - nicht in aufsteigender Reihenfolge ausgegeben werden:

Code: Alles auswählen

import random
Zahlen = range(1,50)
random.shuffle(Zahlen)
Lottozahlen = Zahlen[:6]
Lottozahlen.sort()
print "Die Lottozahlen:", Lottozahlen, "Zusatzzahl" ,Zahlen[6]
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

hansen12345 hat geschrieben:Doch es soll eben der Fall gesetz sein, dass dies das ausschließlich zur Verfügung stehende Werkzeug sein soll.
Dabei kann es sich nur um eine (idiotische) akademische Vorgabe handeln :-D
BlackJack

@Hyperion: So ist das halt bei Hausaufgaben. Das war auch 2006 schon so. ;-)
Antworten