Python :: Aufgabe #106

6 Lösungen Lösungen öffentlich

Simulation des Monty-Hall-Problems

Anfänger - Python von hollst - 19.05.2016 um 13:44 Uhr
Das Monty-Hall-Problem ist eines der erstaunlichsten Paradoxa der Wahrscheinlichkeitsrechnung und ein sehr gutes Beispiel dafür, wie durch eine (teilweise bewusst) irreführende Fragestellung der Blick auf die Problemlösung verschleiert werden kann. Selbst gestandene Mathematiker sollen sich daran schon die Zähne ausgebissen und getäuscht haben, obwohl die Lösung doch recht einfach ist.

Das Problem: Beteiligt sind ein Kandidat, ein Moderator und drei verschlossene Container. In einem der drei Container befindet sich der Hauptgewinn, in den zwei anderen jeweils ein Trostpreis. Der Moderator, der weiss, in welchem Container sich der Hauptgewinn befindet, bittet den Kandidaten, den "Hauptgewinn-Container" zu erraten. Der Kandidat entscheidet sich bspw. für Container # 1. Daraufhin geht der Moderator zu einem anderen Container mit Trostpreisinhalt, öffnet diesen Container und bietet dem Kandidaten gleichzeitig an, seine Wahlentscheidung noch einmal zu überdenken und gegebenenfalls zu wechseln.

Wie soll sich der Kandidat entscheiden? Es ist klar, dass sich in einem der zwei noch verschlossenen Container der Hauptgewinn befindet, in welchem, ist nur mit einer Wahrscheinlichkeit von 50 % bekannt. Wir wollen nun von zwei unterschiedlichen Kandidatentypen ausgehen: Typ 1 (konventioneller Typ) sagt sich, bei einer 50 : 50 Chance ist es egal, ob man wechselt, aber die Erfahrung sagt ihm, dass oftmals der erste Gadanke der beste ist, also entscheidet sich Typ 1 für NICHT WECHSELN. Typ 2 (gutgläubiger Typ) denk sich, wenn der Moderator ihm schon die Chance zum Wechseln anbietet, sollte er diese wahrnehmen, denn der Moderator würde ihm sicher nichts nachteiliges anbieten, also entscheidet sich Typ 2 für WECHSELN.

Mit der Simulation soll statistisch bekräftigt werden, ob (a) WECHSELN vorteilhaft ist, (b) gar keinen Einfluss hat oder (c) sogar nachteilig wäre. Wer Lust hat, kann das Simulationsergebnis auch noch zu erklären versuchen.

Im Bild ist exemplarisch eine Gewinnverteilung für die zwei Kandidaten-Typen nach vier Spielversuchen (Simulationen) dargestellt. Vier Versuche sind allerdings zu wenig, um sich bereits eine Meinung bilden zu können.

Lösungen:

vote_ok
von Veigar (1120 Punkte) - 25.05.2016 um 11:15 Uhr
Quellcode ausblenden Python-Code
import random
m=[0,0]

o=int(input("wie viele versuche sollen unternommen werden?"))

def tester():
    #Hauptgewinn
    a=random.randint(1,3)
    #gewählt
    b=random.randint(1,3)
    if a==b:
        #wechsel lohnt sich nicht
        m[0]=m[0]+1
    else:
        #wechsel lohnt sich
        m[1]=m[1]+1

for i in range(o):
    tester()


print("bei ",o," Versuchen hat es sich in ",m[1]," Versuchen gelohnt zu wechseln und dementsprechend bei ",m[0]," Versuchen nicht.")
vote_ok
von AnnaIhrs (460 Punkte) - 08.06.2016 um 03:24 Uhr
Quellcode ausblenden Python-Code
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
#
#>>>autor:      Sebastian Müller
#>>>licence:    GPL
#>>>contact:    mypythonmueller@gmail.com

# programm nach folgender aufgabenstellung:
# Das Problem: Beteiligt sind ein Kandidat, ein Moderator und drei verschlossene
# Container. In einem der drei Container befindet sich der Hauptgewinn, in den
# zwei anderen jeweils ein Trostpreis. Der Moderator, der weiss, in welchem
# Container sich der Hauptgewinn befindet, bittet den Kandidaten, den "Hauptgewinn-
# Container" zu erraten. Der Kandidat entscheidet sich bspw. für Container
# 1. Daraufhin geht der Moderator zu einem anderen Container mit Trostpreisinhalt,
# öffnet diesen Container und bietet dem Kandidaten gleichzeitig an, seine
# Wahlentscheidung noch einmal zu überdenken und gegebenenfalls zu wechseln.

# zufallsgenerator laden
import random

# funktion die die "container" bestückt
def conti():
    containers = []
    a = "Hauptgewinn"
    b = "Trostpreis1"
    c = "Trostpreis2"
    while len(containers) != 3:
        if len(containers) == 2 and a not in containers:
            containers.append(a)
            break
        verteil = random.randint(1, 3)
        if verteil == 1:
            if a in containers:
                continue
            else:
                containers.append(a)
        if verteil == 2:
            if b in containers:
                continue
            else:
                containers.append(b)
        if verteil == 3:
            if c in containers:
                continue
            else:
                containers.append(c)
    return containers

# zähler initialisieren
player1g = 0
player1t = 0
player2g = 0
player2t = 0
inhalt = 0

# gewinne beschreiben, ich habe trostpreis 1 und 2 da egal wie ich es auch probiert
# habe mit hauptgewinn und ausschlieslich "trostpreis" habe ich ganz seltsame
# verteilungen in den listen bekommen
a = "Hauptgewinn"
b = "Trostpreis1"
c = "Trostpreis2"

# programm erklärung für den user
print("Programm zur evaluierung des Monty-Hall-Probles. ")
print()
print("Für mich gibt es zwei Möglichkeiten dieses Problem zu lösen:")
print("A: Spieler1 und Spieler2 tippen beim ersten Versuch den selben Container.")
print("B: Spieler1 und Spieler2 tippen zufällig und unabhängig voneinander.")
print()
print("Die Verteilung der Gewinne in den Containern allerdings sind sowohl bei")
print("A, oder B, für Spieler1 und Spieler2 in der jeweiligen Runde gleich!")
print()

# user nach gewünschter anzahl an "spielen" fragen, falsche eingaben
# ohne programmabruch möglich
anz = 0
while not anz:
    try:
        anz = int(input("Bitte die Anzahl der zu vergleichenden Runden eingeben. "))
    except:
        print("Eingabe war leider nicht korreckt... Bitte ganze Zahl eingeben!!!")
    if anz < 0:
        print("Soll ich negative Runden Spielen???? Ich glaube nicht!!!!")
        anz = 0

#vwahrscheinlichkeiten nach spielversion A:
for i in range(anz):
    del inhalt
    inhalt = conti()
    tipp = random.randint(0, 2)
    if inhalt[tipp] == a:
        player1g += 1
    else:
        player1t += 1
    player2tip = inhalt[tipp]
# spieler 2 schliest durch seine "wahl, da er ja wechselt diese aus"
    inhalt.remove(player2tip)
# damit der "moderator" nicht immer die "selbe tür" öffnet
    modwechsel = random.randint(1, 2)
# moderator schliest durch seine "enthüllung" eines trostpreises diesen aus"
    if modwechsel == 1:
        if b in inhalt:
            inhalt.remove(b)
        else:
            inhalt.remove(c)
    if modwechsel == 2:
        if c in inhalt:
            inhalt.remove(c)
        else:
            inhalt.remove(b)
# auszählen
    if a in inhalt:
        player2g += 1
    else:
        player2t += 1

# wahrscheinlichkeiten nach spielversion B:

# zähler initialisieren
pBlayer1g = 0
pBlayer1t = 0
pBlayer2g = 0
pBlayer2t = 0
inhalt = 0
inhalt2 = 0

a = "Hauptgewinn"
b = "Trostpreis1"
c = "Trostpreis2"

for i in range(anz):
    del inhalt
    inhalt = conti()
    tippP1 = random.randint(0, 2)
    if inhalt[tippP1] == a:
        pBlayer1g += 1
    else:
        pBlayer1t += 1
    del inhalt2
    inhalt2 = conti()
    tippP2 = random.randint(0,2)
    payerB2tip = inhalt2[tippP2]
    inhalt2.remove(payerB2tip)
    modwechsel = random.randint(1, 2)
    if modwechsel == 1:
        if b in inhalt2:
            inhalt2.remove(b)
        else:
            inhalt2.remove(c)
    if modwechsel == 2:
        if c in inhalt2:
            inhalt2.remove(c)
        else:
            inhalt2.remove(b)
    if a in inhalt2:
        pBlayer2g += 1
    else:
        pBlayer2t += 1

#final
print()
print("Spieleversion A:")
print("Spieler1 der bei seiner Entscheidung bleibt, gewinnt von", anz, "Spielen:")
print(player1g, "mal, und verliert bzw erhält den Trostpreis",player1t, "Mal")
print()
print("Spieler2 der wechselt, gewinnt von", anz, "Spielen:")
print(player2g, "mal, und verliert bzw erhält den Trostpreis",player2t, "Mal")
print()

# brüche importieren um wahrscheinlichkeiten automatisch zu kürzen
import fractions
spielAp1 = fractions.Fraction(player1g, anz)
spielAp2 = fractions.Fraction(player2g, anz)
print("Damit ergibt sich für Spieler1 eine Gewinnwahrscheinlichkeit von:")
AP1n = spielAp1.numerator
AP1d = spielAp1.denominator
print(str(AP1n) + ":" + str(AP1d) , "oder", str(round(player1g / anz *100, 5)) +"%,")
print("Spieler2 allerdings hat somit eine Gewinnwahrscheinlichkeint von:")
AP2n = spielAp2.numerator
AP2d = spielAp2.denominator
print(str(AP2n) + ":" + str(AP2d) , "oder", str(round(player2g / anz * 100, 5)) +"%,")
print()
print("Spieleversion B:")
print("Spieler1 der bei seiner Entscheidung bleibt, gewinnt von", anz, "Spielen:")
print(pBlayer1g, "mal, und verliert bzw erhält den Trostpreis",pBlayer1t, "Mal")
print()
print("Spieler2 der wechselt, gewinnt von", anz, "Spielen:")
print(pBlayer2g, "mal, und verliert bzw erhält den Trostpreis",pBlayer2t, "Mal")
print()
import fractions
spielBp1 = fractions.Fraction(pBlayer1g, anz)
spielBp2 = fractions.Fraction(pBlayer2g, anz)
print("Damit ergibt sich für Spieler1 eine Gewinnwahrscheinlichkeit von:")
BP1n = spielBp1.numerator
BP1d = spielBp1.denominator
print(str(BP1n) + ":" + str(BP1d) , "oder", str(round(pBlayer1g / anz *100, 5)) +"%,")
print("Spieler2 allerdings hat somit eine Gewinnwahrscheinlichkeint von:")
BP2n = spielBp2.numerator
BP2d = spielBp2.denominator
print(str(BP2n) + ":" + str(BP2d) , "oder", str(round(pBlayer2g / anz * 100, 5)) +"%,")
# erklärung
print()
print("Es ist also klar, statistisch gesehen, hat Spieler2 die besseren Chanchen!!!")
print("Das ist relaiv einfach zu erklären:")
print('Spieler1 hat eine Trefferchance von 1 Versuch zu 3 "Toren".')
print("Er gewinnt immer dann wenn er richtig liegt.")
print("Für Spieler2 gilt natürlich das Selbe, nur dass er durch den Wechsel,")
print('immer dann, wenn er falsch lag, also 2 von 3 mal, da der "Moderator" einen')
print('Trostpreises ausschliest, nur noch den Gewinn übrig hat und gewinnt.')
print('Wem das nun immer noch nicht klat ist, der kann bei Wikipedia ganz einfach')
print('das "Monty-Hall" bzw. das "Ziegen-Problem" nachlesen.')
print("Das habe ich auch getan, nachdem ich die ersten Ergebnisse meines Programms")
print("gesehen habe!!!")
print("Einen schönen Tag noch!!!! ;)")
vote_ok
von Cryptt (390 Punkte) - 16.08.2016 um 09:40 Uhr
Quellcode ausblenden Python-Code
# Monty Hall Problem
import random

gewinn1 = 0
gewinn2 = 0
runden = 100000

for i in range(runden):
  inhaltGewinn = random.randint(1,2)
  kandidat1 = random.randint(1,2)
  
  if kandidat1 == 1:
    kandidat2 = 2
  else:
    kandidat2 = 1
  
  if kandidat1 == inhaltGewinn:
    gewinn1 += 1
  else:
    gewinn2 += 1
    
print('Der tradionelle Kandidat gewinnt', gewinn1,'mal den Preis.(',(gewinn1*100/runden),'%)')
print('Der gutglaeubige Kandidat gewinnt', gewinn2,'mal den Preis.(',(gewinn2*100/runden),'%)')

vote_ok
von Nachbar (2820 Punkte) - 03.09.2016 um 10:00 Uhr
Quellcode ausblenden Python-Code
# -*- coding: utf-8 -*-
import random

durchgaenge = 1000
gewinneTyp1, gewinneTyp2 = 0, 0
# 1:Gewinn, 2,3:Niete
car_or_goat = [1,2,3]

while durchgaenge > 0:
    random.shuffle(car_or_goat)
    tip = random.choice(car_or_goat)
    # Nichtwechsler
    if tip == 1:
        gewinneTyp1 = float(gewinneTyp1) + 1 
    # Wechsler
    elif tip != 1:
        gewinneTyp2 = float(gewinneTyp2) + 1 
    durchgaenge = durchgaenge - 1
    
print "Gewinnverteilung:\n\nWechsler: " + str(gewinneTyp2 * 100 / 1000) + "%" \
"\nNichtwechsler: " + str(gewinneTyp1 * 100 / 1000) + "%."

# Da der Nichtwechsler nie wechselt, gewinnt dieser immer dann, wenn er beim 
# ersten mal den richtigen Container wählt (if tip == 1), Chance: 1:3
# Da der Wechsler immer wechselt, gewinnt dieser immer dann, wenn er NICHT beim
# ersten mal den richtigen Container wählt (elif tip != 1), da der Hauptgewinn
# noch im Rennen ist und die zweite Niete durch den Moderator 
# "entschärft" wird, Chance: 2:3
vote_ok
von 0 (0 Punkte) - 23.09.2017 um 12:59 Uhr
Quellcode ausblenden Python-Code
#Monty Hall Simulation
from tkinter import *
from random import randint,choice
def neu():
    zaehler.set(0)
    NW.set(0)
    W.set(0)
    wechsel.set(0)
    keinwechsel.set(0)
def press10():
    z=zaehler.get()
    z+=10
    nw=NW.get()
    w=W.get()
    for i in range(10):
        if versuch('konventionell'):
            nw+=1
        if versuch('unkonventionell'):
            w+=1
    NW.set(nw)
    W.set(w)
    nw=str(nw*100/z)+'%'
    w=str(w*100/z)+'%'
    keinwechsel.set(nw)
    wechsel.set(w)
    zaehler.set(z)
    
def press100():
    z=zaehler.get()
    z+=100
    nw=NW.get()
    w=W.get()
    for i in range(100):
        if versuch('konventionell'):
            nw+=1
        if versuch('unkonventionell'):
            w+=1
    NW.set(nw)
    W.set(w)
    nw=str(nw*100/z)+'%'
    w=str(w*100/z)+'%'
    keinwechsel.set(nw)
    wechsel.set(w)
    zaehler.set(z)
def press1000():
    z=zaehler.get()
    z+=1000
    nw=NW.get()
    w=W.get()
    for i in range(1000):
        if versuch('konventionell'):
            nw+=1
        if versuch('unkonventionell'):
            w+=1
    NW.set(nw)
    W.set(w)
    nw=str(nw*100/z)+'%'
    w=str(w*100/z)+'%'
    keinwechsel.set(nw)
    wechsel.set(w)
    zaehler.set(z)
def press1():
    z=zaehler.get()
    z+=1
    nw=NW.get()
    w=W.get()
    if versuch('konventionell'):
        nw+=1
    if versuch('unkonventionell'):
        w+=1
    NW.set(nw)
    W.set(w)
    nw=str(nw*100/z)+'%'
    w=str(w*100/z)+'%'
    keinwechsel.set(nw)
    wechsel.set(w)
    zaehler.set(z)
def versuch(art):
    tueren=['A','B','C']
    auto=choice(tueren)
    wahl=choice(tueren)
    if wahl==auto:
        if art=='konventionell':
            return True
        elif art=='unkonventionell':
            tueren.remove(auto)
            wahl=choice(tueren)
            if wahl==auto:
                return True
            else: return False
    else:
        if art=='konventionell':
            return False
        elif art=='unkonventionell':
            return True
fenster=Tk()
fenster.title('Monty Hall')
NW=IntVar()
W=IntVar()
zaehler=IntVar()
keinwechsel=StringVar()
wechsel=StringVar()
Label(fenster,text='Versuche: ').pack(anchor=E)
Label(fenster,textvariable=zaehler).pack(anchor=E)
f=Frame(fenster).pack(side=TOP)
Button(f,text='+1',command=press1).pack(anchor=N,side=LEFT)
Button(f,text='+10',command=press10).pack(anchor=N,side=LEFT)
Button(f,text='+100',command=press100).pack(anchor=N,side=LEFT)
Button(f,text='+1000',command=press1000).pack(anchor=N,side=LEFT)
Button(f,text='Neu',command=neu).pack(anchor=N,side=LEFT)
g=Frame(fenster).pack(side=RIGHT)
Label(g,text='Kein Wechsel:\nVersuche').pack(side=TOP)
Label(g,textvariable=NW).pack(anchor=CENTER)
Label(g,textvariable=keinwechsel).pack(anchor=CENTER)
Label(g,text='Wechsel:\nVersuche').pack(anchor=CENTER)

Label(g,textvariable=wechsel).pack(side=BOTTOM)
Label(g,textvariable=W).pack(side=BOTTOM)
vote_ok
von Kotgreifer (1100 Punkte) - 20.01.2020 um 15:39 Uhr
Quellcode ausblenden Python-Code
import random

wiederholungen= 10000
türen = ['X','X','O']
userW={"win":0,"lose":0}
userNW={"win":0,"lose":0}

for i in range(1,wiederholungen):
    random.shuffle(türen)
    if türen.index('O')==random.choice(range(0,3)):
        userW["lose"]+=1
    else:
        userW["win"]+=1

for i in range(1,wiederholungen):
    random.shuffle(türen)
    if türen.index('O')==random.choice(range(0,3)):
        userNW["win"]+=1
    else:
        userNW["lose"]+=1


print("Gewonnene Spiele (Wechsler):          "+str(userW["win"]/wiederholungen*100)+"%")
print("Gewonnene Spiele (Nicht Wechsler):    "+str(userNW["win"]/wiederholungen*100)+"%")