Ziegenproblem

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
fledermausland
User
Beiträge: 12
Registriert: Freitag 22. Januar 2010, 15:38

Nachtrag: das hätte wohl besser in 'Codesnippets' gepasst, hoppla

Hey ho

ich hatte vorhin mal wieder etwas über das allbekannte Ziegenproblem gelesen, und darum ein kurzes Simulationsscript erstellt. Die Auskommentierten Sachen waren ursprünglich dazu da, um den Spielverllauf nachzuvollziehen, aber bei mehr als 100 Durchgängen ist es dann auch überflüssig.

Code: Alles auswählen

import random

def mixlist(data):
    ''' Mix the incoming list up '''
    size = len(data)
    a =  []
    while size:
        size = size - 1
        index = random.randint(0, size)
        elem = data[index]
        data[index] = data[size]
        a.append(elem)
    return a

def game(n, switch):
    game_gates = mixlist(['Car','Goat','Goat'])
    for i in xrange(n):        
        # print '1\t2\t3'
        # print '%s\t%s\t%s' % (game_gates[0], game_gates[1], game_gates[2])
        cand_choice = random.randint(1,3)
        # print 'Candidate chooses gate %s' % cand_choice
        mod_choice = cand_choice
        while (mod_choice == cand_choice) or (game_gates[mod_choice - 1] == 'Car'):
            # Just find a gate with a goat which is not chosen by candidate
            mod_choice = random.randint(1,3)
        # print 'Moderator opens gate %s' % mod_choice
        # if not switch:
            # print 'Candidate stays with gate %s' % cand_choice
        if switch:
            i = 1
            while (i == cand_choice) or (i == mod_choice):
                # Find the only gate left to choose
                i += 1
            cand_choice = i            
            # print 'Candidate switches to gate %s' % cand_choice
        if game_gates[cand_choice - 1] == 'Car':
            # print 'The candidate won\n'
            yield 1
        else:
            # print 'The candidate lost\n'
            yield 0

def testrun():
    n = raw_input('How many games shall be simulated? [100] :')
    try:
        n = int(n)
    except:
        print 'Not a valid number, using default. [100]'
        n = 100
    if n < 1:
        n = 100
    won_stay = game(n, 0)
    won_stay = sum(won_stay)
    won_switch = game(n, 1)
    won_switch = sum(won_switch)
    print 'The candidate won %s of %s rounds without switching. (%.2f percent)' % \
            (won_stay, n, won_stay*100.0/float(n))
    print 'The candidate won %s of %s rounds with switching. (%.2f percent)' % \
            (won_switch, n, won_switch*100.0/float(n))

testrun()
Besonders interessant, wie sich das Ergebnis bei immer größeren Zahlen an die mathemathische Wahrscheinlichkeit annähert (1/3 ohne Wechsel, 2/3 mit)

Code: Alles auswählen

user@l:~/testing$ python ziege.py 
How many games shall be simulated? [100] :12
The candidate won 3 of 12 rounds without switching. (25.00 percent)
The candidate won 9 of 12 rounds with switching. (75.00 percent)

user@l:~/testing$ python ziege.py 
How many games shall be simulated? [100] :123
The candidate won 38 of 123 rounds without switching. (30.89 percent)
The candidate won 80 of 123 rounds with switching. (65.04 percent)

user@l:~/testing$ python ziege.py 
How many games shall be simulated? [100] :1234
The candidate won 416 of 1234 rounds without switching. (33.71 percent)
The candidate won 816 of 1234 rounds with switching. (66.13 percent)

user@l:~/testing$ python ziege.py 
How many games shall be simulated? [100] :12345
The candidate won 4188 of 12345 rounds without switching. (33.92 percent)
The candidate won 8250 of 12345 rounds with switching. (66.83 percent)

user@l:~/testing$ python ziege.py 
How many games shall be simulated? [100] :123456
The candidate won 41315 of 123456 rounds without switching. (33.47 percent)
The candidate won 82413 of 123456 rounds with switching. (66.75 percent)

user@l:~/testing$ python ziege.py 
How many games shall be simulated? [100] :1234567
The candidate won 410350 of 1234567 rounds without switching. (33.24 percent)
The candidate won 822155 of 1234567 rounds with switching. (66.59 percent)

user@l:~/testing$ python ziege.py 
How many games shall be simulated? [100] :12345678
The candidate won 4117087 of 12345678 rounds without switching. (33.35 percent)
The candidate won 8226502 of 12345678 rounds with switching. (66.63 percent)
Sinnfrei, aber nicht uninteressant.
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Habs mal überarbeitet:

Code: Alles auswählen

from random import shuffle, randrange

def game(n, switch):
    gates = [1, 0, 0]
    shuffle(gates)

    for i in xrange(n):       
        candidate = randrange(0,3)
        for index, gate in enumerate(gates):
            if not gate and index!=candidate:
                moderator = index
        if switch:
            candidate = 3 - candidate - moderator
        if gates[candidate]:
            yield True
        else:
            yield False

def testrun():
    default = 100
    n = 0
    try:
        n = int(raw_input('How many games shall be simulated? [%s] :' %default))
    except ValueError:
        print 'Not a valid number, using default. [%s]' %default
    n = n if n > 0 else default
    
    won_stay = sum(game(n, switch=False))
    won_switch = sum(game(n, switch=True))
    print 'The candidate won %s of %s rounds without switching. (%.2f percent)' % \
            (won_stay, n, won_stay*100.0/float(n))
    print 'The candidate won %s of %s rounds with switching. (%.2f percent)' % \
            (won_switch, n, won_switch*100.0/float(n))

if __name__ == '__main__':
    testrun()
Ein paar Sachen waren da noch, die nicht so optimal sind (e.g. die while-Schleifen). Warum mischt du die Liste, wenn du eh zufällige Auswahlen hast?
Ich hab es trotzdem drin gelassen.
[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]
fledermausland
User
Beiträge: 12
Registriert: Freitag 22. Januar 2010, 15:38

Ah, da gabs ja wirklich einiges zu verbessern, danke. Zu dem Mischen am Anfang: es sollte eine möglichst originalgetreue Simulation sein, egal ob das sinnvoll ist oder nicht. Und im "Original" war es ja auch dem Zufall überlassen, was zu Anfang hinter welchem Tor ist.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Na da würde ich noch einmal nachdenken: ;-)

Code: Alles auswählen

if gates[candidate]:
    yield True
else:
    yield False 
Das Leben ist wie ein Tennisball.
fledermausland
User
Beiträge: 12
Registriert: Freitag 22. Januar 2010, 15:38

Ich nehme an, du meinst, dass man sich das "yield False" auch schenken kann?
Zuletzt geändert von fledermausland am Donnerstag 28. Januar 2010, 23:24, insgesamt 1-mal geändert.
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Oh, was ein fauxpas.
[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
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

fledermausland hat geschrieben:Ich nehme an, du meinst, dass sich das "yield False" auch schenken kann?
Jain:

Code: Alles auswählen

yield gates[candidate]
[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]
fledermausland
User
Beiträge: 12
Registriert: Freitag 22. Januar 2010, 15:38

Oh, Tatsache. KISS lässt grüßen.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wobei man, wenn der Wahrheitswert noch relevant ist, hier mit `yield candidate in gates` arbeiten sollte.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hui, das hatte ich doch auch mal versucht umzusetzen.
http://www.python-forum.de/topic-13721.html

Was ist das teilweise krude... :-D
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

snafu hat geschrieben:Wobei man, wenn der Wahrheitswert noch relevant ist, hier mit `yield candidate in gates` arbeiten sollte.
Ich glaube das hilft nicht. gates enthält 0 und 1. candidate kann 0,1 oder 2 sein. candidate ist der index. candidate in gates hilft deshalb nicht.
[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]
Antworten