Problem mit 1000 mal Würfel

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.
Schrauber1
User
Beiträge: 5
Registriert: Sonntag 28. Oktober 2012, 15:17

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.
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?
Schrauber1
User
Beiträge: 5
Registriert: Sonntag 28. Oktober 2012, 15:17

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
Zuletzt geändert von Anonymous am Sonntag 28. Oktober 2012, 16:14, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
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.
Schrauber1
User
Beiträge: 5
Registriert: Sonntag 28. Oktober 2012, 15:17

Hier mal ein Struktogramm wie ich es machen würde. Bild
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.
Schrauber1
User
Beiträge: 5
Registriert: Sonntag 28. Oktober 2012, 15:17

Habe es glaube ich! :D

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,"%")
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

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 :)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
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()
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

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 :)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Schrauber1 hat geschrieben:Habe es glaube ich! :D

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.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Kurzer Einwurf: Ich wuerde ein dict (oder ein defaultdict) statt einer Liste nehmen. Ich finde die Index Manipulationen verschleiern die Absicht zu sehr.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

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))
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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 :mrgreen: 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 :P

@pillmuncher: Den ``Counter`` hatte cofi schon gezeigt - wenn auch nicht so ausgearbeitet wie Du :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

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
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Ich finde es gar nicht so schlecht ;)

Ich merke gerade zum ersten mal, dass du muTEtella heißt.
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

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 ;)
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

jbs hat geschrieben:Ich merke gerade zum ersten mal, dass du muTEtella heißt.
:D
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
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hoffentlich liest lunar jetzt nicht mit... :roll:
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
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Antworten