Seite 1 von 2
Problem mit 1000 mal Würfel
Verfasst: Sonntag 28. Oktober 2012, 15:27
von Schrauber1
Hallo bin neu hier und habe gleich mal ein Problem. Ich weiß nicht wie man die zwei Aufgaben unten löst. Könnte mir bitte einer helfen?
Lg Schrauber1
Untersuche mit einem Programm, ob der mit dem Zufallsgenerator von Python simulierte Würfel fair ist. Hierzu soll ein Würfel 1000 mal (bzw. eine vom Benutzer eingegebene Anzahl mal) geworfen werden. Dabei soll mitgezählt werden, wie oft eine 6 fällt. Ausgegeben werden soll die Gesamtanzahl der Würfe und die Anzahl der Treffer (hier: 6). Wie kann man aus den beiden Zahlen auf Fairness schließen?
Entwickle ein Programm, mit dem man herausfinden kann, wie oft man durchschnittlich würfeln muss, bis man eine 6 erhält. Benutze hierzu zwei ineinander geschachtelte Wiederholungen. Beginne mit einem Struktogramm oder Flussdiagramm. Wenn die Ablauflogik stimmt, dann übersetze das Diagramm in ein Programm.
Re: Problem mit 1000 mal Würfel
Verfasst: Sonntag 28. Oktober 2012, 16:00
von BlackJack
@Schrauber1: Bitte das Thema
An alle Schüler und Studenten mit Informatikproblemen lesen, zumindest die ersten Beiträge.
Was hast Du denn schon? Wo liegt das konkrete Problem? Welche Materialien verwendest Du um Python und programmieren zu lernen?
Re: Problem mit 1000 mal Würfel
Verfasst: Sonntag 28. Oktober 2012, 16:11
von Schrauber1
Also was ich schon kann ist das:
Code: Alles auswählen
from random import randint
Augenzahl=randint(1,6)
zaehler=0
while Augenzahl!=6:
Augenzahl=randint(1,6)
zaehler=zaehler+1
print('Der Würfl zeigt:',Augenzahl)
print('Anzahl der Versuche:',zaehler)
Ich will es versuchen mir es selbst bei zu bringen. Die Übung ist von dieser Seite:
http://www.inf-schule.de/index.php?vers ... ltwuerfeln
Re: Problem mit 1000 mal Würfel
Verfasst: Sonntag 28. Oktober 2012, 16:19
von BlackJack
@Schrauber1: Das ist ja mehr oder weniger das Programm von der Webseite. Jetzt musst Du Dir halt überlegen wie Programme aussehen müssten, welche die Aufgaben 4 und 5 lösen.
Re: Problem mit 1000 mal Würfel
Verfasst: Sonntag 28. Oktober 2012, 16:37
von Schrauber1
Hier mal ein Struktogramm wie ich es machen würde.

Re: Problem mit 1000 mal Würfel
Verfasst: Sonntag 28. Oktober 2012, 16:58
von BlackJack
@Schrauber1: Sieht doch gut aus. Das ist ein Programm umsetzen und dann noch die Frage am Ende von Aufgabe 4 beantworten und diese Aufgabe ist gelöst.
Re: Problem mit 1000 mal Würfel
Verfasst: Sonntag 28. Oktober 2012, 17:02
von Schrauber1
Habe es glaube ich!
Code: Alles auswählen
from random import randint
eins=0
zwei=0
drei=0
vier=0
fünf=0
sechs=0
for k in range(1000):
z=randint(1,6)
if z==1:
eins=eins+1
if z==2:
zwei=zwei+1
if z==3:
drei=drei+1
if z==4:
vier=vier+1
if z==5:
fünf=fünf+1
if z==6:
sechs=sechs+1
print("Die 1 kam genau ",eins," mal vor, das entspricht",eins/1000*100,"%")
print("Die 2 kam genau ",zwei," mal vor, das entspricht",zwei/1000*100,"%")
print("Die 3 kam genau ",drei," mal vor, das entspricht",drei/1000*100,"%")
print("Die 4 kam genau ",vier," mal vor, das entspricht",vier/1000*100,"%")
print("Die 5 kam genau ",fünf," mal vor, das entspricht",fünf/1000*100,"%")
print("Die 6 kam genau ",sechs," mal vor, das entspricht",sechs/1000*100,"%")
Re: Problem mit 1000 mal Würfel
Verfasst: Sonntag 28. Oktober 2012, 17:55
von cofi
Ein Ausblick, um dir zu zeigen, dass Python jede menge praktische Sachen mitbringt:
Code: Alles auswählen
In [1]: import random, collections
In [2]: collections.Counter(random.randint(1, 6) for _ in xrange(1000))
Out[2]: Counter({4: 183, 5: 178, 2: 168, 1: 166, 6: 154, 3: 151})
Noch viel Spass mit Python

Re: Problem mit 1000 mal Würfel
Verfasst: Sonntag 28. Oktober 2012, 18:15
von Leonidas
cofi hat geschrieben:Ein Ausblick, um dir zu zeigen, dass Python jede menge praktische Sachen mitbringt
Beschreibt auch ganz gut warum Struktogramme nur bedingt nützlich sind. Wenn man den Control-Flow eigentlich vollständig durch Datenstrukturen ersetzt ist so ein Struktogramm nur ne Aneinanderreihung von Funktionsaufrufen die nix aussagen.
Re: Problem mit 1000 mal Würfel
Verfasst: Sonntag 28. Oktober 2012, 21:45
von BlackJack
Eine Lösung für Aufgabe 5, beziehungsweise eine, die das Ergebnis liefert, aber nicht nach dem dort geforderten Weg, und die sich auch nicht nicht so gut als Struktogramm zeichnen lässt. Ebenfalls um zu zeigen wie man in Python auch programmieren kann.
Code: Alles auswählen
#!/usr/bin/env python
from __future__ import division, print_function
from functools import partial
from itertools import takewhile
from operator import ne as not_equal
from random import randint
roll_dice = partial(randint, 1, 6)
def iter_dice_rolls():
while True:
yield roll_dice()
def count_rolls_until(expected):
return 1 + sum(
1 for _ in takewhile(partial(not_equal, expected), iter_dice_rolls())
)
def main():
count = 10000
print(sum(count_rolls_until(6) for _ in xrange(count)) / count)
if __name__ == '__main__':
main()
Re: Problem mit 1000 mal Würfel
Verfasst: Sonntag 28. Oktober 2012, 23:44
von jerch
Interessant finde ich die Frage "Wie kann man aus den beiden Zahlen auf Fairness schließen?" - da kann man sich von Modellierung des Zufallsexperimentes in Python über Verteilungen bis zum Hypothesentest mit Fehlerbetrachtung richtig austoben

Re: Problem mit 1000 mal Würfel
Verfasst: Montag 29. Oktober 2012, 18:57
von Hyperion
Schrauber1 hat geschrieben:Habe es glaube ich!
Code: Alles auswählen
from random import randint
# und nun ganz viel grausamer Code...
Auch wenn cofi eine sehr elegante Lösung aufgezeigt hat, so will ich Dir doch mal zeigen, wie man Deine "konventionelle" (für einen Anfänger leichter zu verstehende) Lösung so umbauen kann (und sollte), dass es sich um "echtes" Programmieren handelt und kein Copy und Paste mehr ist.
Als erstes benutzt man Datenstrukturen für das Verwalten von Daten. Die beiden grundlegenden in Python sind Listen und Dictionaries. Für diese Aufgabe eignet sich eine Liste recht gut. Die Idee ist es, die Ergebnisse in *einem* Objekt zusammen zu fassen. Dieses Objekt ist nun einfach ein Listenobjekt. Wir legen es so an, dass es 6 Einträge mit einer 0 hat. Jeder einzelne Integerwert repräsentiert die Anzahl einer bestimmten Zahl. Der "Trick" ist es nun, dass wir festlegen, dass die Zahl 1 auf den Index 0, die Zahl 2 auf den Index 1, usw. abgebildet werden. Da in Python Indizes bei 0 anfangen, ist also immer die gewürfelte Zahle minus eins der Index, hinter dem die Anzahl dieser Zahl verwaltet wird.
Die Zufallsfunktion ermittel also quasi den Index, hinter dem sich der Zählwert erhöhen soll.
Wir sparen dadurch die ganze lästige ``if...elif``-Kaskade sowie die sechs einzelnen ``print``-Funktionen:
Code: Alles auswählen
from random import randint
limit = 1000
counter = [0] * 6
for value in range(limit):
counter[randint(1, 6) - 1] += 1
for index, count in enumerate(counter, 1):
print("Die {} kam genau {} mal vor, das entspricht {}%".format(
index, count, count * 100/ limit))
Du wirst sicherlich zugeben, dass das viel sauberer aussieht.
Re: Problem mit 1000 mal Würfel
Verfasst: Dienstag 30. Oktober 2012, 01:18
von cofi
Kurzer Einwurf: Ich wuerde ein dict (oder ein defaultdict) statt einer Liste nehmen. Ich finde die Index Manipulationen verschleiern die Absicht zu sehr.
Re: Problem mit 1000 mal Würfel
Verfasst: Dienstag 30. Oktober 2012, 01:23
von pillmuncher
Oder mit
collections.Counter:
Code: Alles auswählen
from random import randint
from collections import Counter
limit = 1000
for index, count in sorted(Counter(randint(1, 6) for _ in range(limit)).items()):
print("Die {} kam genau {} mal vor, das entspricht {}%".format(
index, count, count * 100 / limit))
Re: Problem mit 1000 mal Würfel
Verfasst: Dienstag 30. Oktober 2012, 19:18
von Hyperion
cofi hat geschrieben:Kurzer Einwurf: Ich wuerde ein dict (oder ein defaultdict) statt einer Liste nehmen. Ich finde die Index Manipulationen verschleiern die Absicht zu sehr.
Ja, ich hatte noch eine Variante mit Dicts angefangen, dann kam aber die Pizza und meine Freundin quängelte

Und ohne ausformulierten erklärenden Text wollte ich das nicht halbgar hinterher schießen...
Defaultdict hätte ich danach noch eingeführt... denn ein Anfänger will ja auch nicht zu viel Magie - die hattest Du ja schon präsentiert
@pillmuncher: Den ``Counter`` hatte cofi schon gezeigt - wenn auch nicht so ausgearbeitet wie Du

Re: Problem mit 1000 mal Würfel
Verfasst: Mittwoch 31. Oktober 2012, 00:21
von mutetella
Und hier noch eine total vergurkte Lösung, so wie man es von mir kennt:
Code: Alles auswählen
>>> dice = map([random.randint(1, 6) for _ in xrange(1000)].count, range(1,7))
>>> for count, dice in enumerate(dice):
... print '{0}er: {1} mal'.format(count+1, dice)
1er: 178 mal
2er: 181 mal
3er: 151 mal
4er: 150 mal
5er: 158 mal
6er: 182 mal
mutetella
Re: Problem mit 1000 mal Würfel
Verfasst: Mittwoch 31. Oktober 2012, 01:11
von jbs
Ich finde es gar nicht so schlecht
Ich merke gerade zum ersten mal, dass du muTEtella heißt.
Re: Problem mit 1000 mal Würfel
Verfasst: Mittwoch 31. Oktober 2012, 01:43
von cofi
Na wenigstens wolltest du ihn nicht aufs Brot schmieren
Verkorkst wuerde ich sie nicht nennen, aber es geht schon in Richtung Obfuscated Python
Aus dem Performance-Blickwinkel ist sie auch suboptimal: Du gehst 6x ueber die ganze Liste (was auch heisst, dass du die ganze Liste brauchst und nicht mit einer GenExp davonkommst). Wenn man jetzt "genauere" Ergebnisse haben moechte koennte man das gut merken

Re: Problem mit 1000 mal Würfel
Verfasst: Mittwoch 31. Oktober 2012, 08:23
von mutetella
jbs hat geschrieben:Ich merke gerade zum ersten mal, dass du muTEtella heißt.
cofi hat geschrieben:... die ganze Liste brauchst und nicht mit einer GenExp davonkommst ...
Darüber hab' ich ein Weilchen nachgedacht, zumal ich hier auf der PyCon am Montag das Tutorial "Iteratoren, Generatoren und Decoratoren" besucht hatte und jetzt natürlich alles nur noch mit Generatoren machen möchte... *grins*
mutetella
Re: Problem mit 1000 mal Würfel
Verfasst: Mittwoch 31. Oktober 2012, 09:34
von mutetella
Hoffentlich liest lunar jetzt nicht mit...
cofi hat geschrieben:Aus dem Performance-Blickwinkel ist sie auch suboptimal...
Das scheint mir manchmal schon ein Reflex zu sein: Dies oder das ist mit Listen gelöst, das muss lahm sein...
Aus meiner geringen Erfahrung heraus weiß ich aber, dass das
so oft nicht stimmt. Und nachdem mich das Tutorial schließlich 'n Hunni gekostet hat, hab' ich da gleich mal eine decorator-Übung gemacht *grins*:
Code: Alles auswählen
from timeit import default_timer
import random, collections
def measure(func):
def call_func(*args):
start = default_timer()
result = func(*args)
return result, default_timer() - start
return call_func
@measure
def with_collections(count):
return collections.Counter(random.randint(1, 6) for _ in xrange(count))
@measure
def without_collections(count):
return map([random.randint(1, 6) for _ in xrange(count)].count, xrange(1, 7))
Code: Alles auswählen
>>> with_collections(100000)
(Counter({6: 16785, 4: 16771, 2: 16731, 5: 16657, 3: 16576, 1: 16480}), 0.24344611167907715)
>>> without_collections(100000)
(<map object at 0x1754950>, 0.16588497161865234)
mutetella