Das Ziegenproblem
-
Ein altes mathematisches Verwirrspiel - einst Zankapfel großer Mathematiker und Logiker:
Ein Kandidat einer Spieleshow steht vor drei verschlossenen Toren. Hinter einem davon verbirgt sich der Hauptpreis. Hinten den beiden anderen befindet sich jeweils eine Ziege (=Niete). Der Kandidat wählt ein beliebiges Tor.Sagen wir Tor 1. Die Wahrscheinlichkeit, das Richtige zu treffen (Hauptgewinn) ist 1/3.
Nachdem der Kandidat gewählt hat, öffnet der Moderator - der weiss wo der Hauptgewinn ist - ein anderes Tor, hinter dem eine Ziege steht.Nehmen wir an, es ist Tor 2. Er bietet dem Kandidaten an, sein zuvor gewähltes und noch verschlossenes Tor mit dem noch ebenso verschlossenen Tor 3 zu tauschen. Erhöht sich die Gewinnchance des Kandidaten, wenn er wechselt?Die überall publizierte Lösung ist ja: Sie verdoppelt sich und beträgt somit 2/3. (nachzulesen z.B. bei Wikipedia)
Ich habe einen Simulator programmiert, um das zu testen:
Durchgang wird beliebig oft - meist 100mal - gestartet (Kandidat nimmt Alternative an):private bool DurchgangStarten(bool alt) { int pos_gewinn,pos_offen,tipp; pos_gewinn=pos_offen=tipp=0; bool moegliches_oeffnen=false; pos_gewinn=ZufallsPosition(); tipp=ZufallsPosition(); while(moegliches_oeffnen==false) if((pos_offen=ZufallsPosition())!=tipp && pos_offen!=pos_gewinn) moegliches_oeffnen=true; for(int i=0;i<3;i++) if(i!=pos_offen && i!=tipp) if(alt==true)tipp=i; //Treffer oder nicht? return (tipp==pos_gewinn); } private int ZufallsPosition() { System.Random rand=new Random(); int zufall=rand.Next(3); System.Threading.Thread.Sleep( new TimeSpan (0,0,0,0,rand.Next(300))); return zufall; }
Bei jedem Simulationslauf kommt bei mir einen Trefferhäufigkeit von etwa 50% bei Annehmen der Alternative raus? Liegt das daran, dass das Programm keine "echten" Zufallszahlen produziert? Der Algorithmus müsste passen.
Oder erhöht sich die Wahrscheinlichkeit doch nur auf 50% statt 66%?
-
Algorithmus ist fehlerhaft. Du wählst immer das letzte nichtoffene Tor.
BTW: Der Stil ist schlimm.
Bye, TGGC
-
Ja, ich wähle das letzte nichtoffene Tor. Das ist auch der Sinn der Sache, wenn man die Alternative nimmt
Und der Stil ist in Ordnung. Es ging mir nicht darum, den elegantesten Quellcode zu schreiben, sondern um das Wesentliche.
-
Ich habe deinen Code jetzt nicht ueberprueft, aber habe auch schonmal ein Programm dafuer geschrieben:
#include <stdio.h> int main(int argc, char *argv[]) { unsigned long int i, i2, success=0, nosuccess=0; int choice=0, choice2; int door, dooropen; //Tor mit Auto und Tor, welches der Moderator oeffnen wird srand(time(NULL)); for (i2=1; i2 <= 10000; i2++) { door = rand()%3 + 1; //Tor mit Auto choice = rand()%3 + 1; //gewaehltes Tor for (i=1;i<=3;i++) { // if (i != door && i != choice) dooropen=i; // Ein Tor mit Ziege oeffnen } // for (i=1; i<=3; i++) { if (i != dooropen && i != choice) { choice2 = i; // Auf das andere Tor gewechselt break; } } if (choice2==door) success++; else nosuccess++; } printf("Erfolge:\t%d\n",success); printf("Misserfolge:\t%d\n\n",nosuccess); system("Pause"); return 0; }
Da kommt das auch immer ungefaehr raus .
-
SliderMaxx schrieb:
Ja, ich wähle das letzte nichtoffene Tor. Das ist auch der Sinn der Sache, wenn man die Alternative nimmt
Du wählst das letzte nicht offene Tor, auch wenn es deinem ursprünglichen Tipp entspricht. Und das ist nicht Sinn der Sache, wenn man die Alternative nimmt
if(alt==true)tipp=i;
Da gehört noch ein break mit rein.
-
SliderMaxx schrieb:
Das ist auch der Sinn der Sache, wenn man die Alternative nimmt
Falsch.
Bye, TGGC (Demo or Die)
-
#include <stdlib.h> #include <stdio.h> #include <math.h> #include <time.h> #include <limits.h> int giveRandomNr() { return rand() % 3; } int main() { const int N_TRIES = SHRT_MAX; int winningDoor, chosenDoor, eliminatedDoor; int i; int cnt = 0; srand(time(0)); for (i = 0; i < N_TRIES; ++i) { winningDoor = giveRandomNr(); chosenDoor = giveRandomNr(); do { eliminatedDoor = giveRandomNr(); } while (eliminatedDoor == chosenDoor); if (winningDoor != chosenDoor) ++cnt; } printf("%d von %d mal haette man durch wechseln gewonnen. Das sind %f %%\n", cnt, N_TRIES, ((float) cnt) / N_TRIES); return 0; }
Ausgabe:
21781 von 32767 mal haette man durch wechseln gewonnen. Das sind 0.664724 %
EDIT: misst zu langsam, wieso kompilier ich immer mit -Wall
-
TGGC schrieb:
SliderMaxx schrieb:
Das ist auch der Sinn der Sache, wenn man die Alternative nimmt
Falsch.
Bye, TGGC (Demo or Die)
Naja, er meint schon das Richtige, eben das andere Tor nach dem Oeffnen eines falschen Tores zu nehmen, also zu wechseln.
Ich habe den Code, wie gesagt nicht ueberprueft, aber wenn das stimmt, was bashar sagt dann hat er das nur nicht richtig in seinem Programm umgesetzt.
-
Vielleicht hilft dieses Programm beim verstehen, was da eigentlich passiert:
#include <iostream> int main() { int siege = 0; const int spiele = 100000; for(int i = 0; i != spiele; ++i) { int siegtor = rand()%3; // Wo ist das Auto? int tipp = rand()%3; // Spieler wählt ein Tor // Wenn der Spieler nicht das Auto gewählt hat, führt der Wechsel zum Sieg, // denn dann ist hinter dem letzten verschlossenen Tor das Auto. if(tipp != siegtor) siege++; } std::cout << siege/double(spiele) << "%"; }
-
XFame schrieb:
TGGC schrieb:
SliderMaxx schrieb:
Das ist auch der Sinn der Sache, wenn man die Alternative nimmt
Falsch.
Bye, TGGC (Demo or Die)
Naja, er meint schon das Richtige, eben das andere Tor nach dem Oeffnen eines falschen Tores zu nehmen, also zu wechseln.
Ich habe den Code, wie gesagt nicht ueberprueft, aber wenn das stimmt, was bashar sagt dann hat er das nur nicht richtig in seinem Programm umgesetzt.
Hab ich doch von Anfang an gesagt.
Bye, TGGC (Demo or Die)
-
for(int i=0;i<3;i++) if(i!=pos_offen && i!=tipp) if(alt==true)tipp=i;
Ein Tor ist getippt, ein anderes offen. Eines bleibt über, zu diesem muss ich wechseln. Ich iteriere das Array,finde die Position, die weder offen noch getippt ist und wechsle wenn alt(=alternativwahl aktiveren) wahr ist.
Wo is hier der Fehler? Die Variable alt soll dazu dienen auch die Variante des Nicht-Wechseln in der Funktion testen zu können.Blue-Tiger:
Dass es bei dir genau 2/3 sind, ist nicht verwunderlich:
Bei dir passiert folgendes. Nehmen wir an, das winningdoor=1, das chosendoor=2
das eliminierte Tor darf nicht mit dem gewählten Tor übereinstimmen:do { eliminatedDoor = giveRandomNr(); } while (eliminatedDoor == chosenDoor);
Es kann aber mit dem winningdoor übereinstimmen. Dann wird der Hauptpreis geöffnet. Aber egal: Letzendlich überprüfst du nur, ob das winning door!=chosendoor ist.
Bei 3 Toren ist die Wahrscheinlichkeit dafür genau 2/3. Und das ist das Ergebnis.Gruß,
SLiderMaxx
-
SliderMaxx schrieb:
for(int i=0;i<3;i++) if(i!=pos_offen && i!=tipp) if(alt==true)tipp=i;
Ein Tor ist getippt, ein anderes offen. Eines bleibt über, zu diesem muss ich wechseln. Ich iteriere das Array,finde die Position, die weder offen noch getippt ist und wechsle wenn alt(=alternativwahl aktiveren) wahr ist.
Debugger benutzen. Artikel daszu gibts ja mittlerweile...
Bye, TGGC (Demo or Die)
-
Blue-Tiger schrieb:
Ausgabe:
21781 von 32767 mal haette man durch wechseln gewonnen. Das sind 0.664724 %
21781 von 32767 sind aber 66,4724% .
-
SliderMaxx schrieb:
for(int i=0;i<3;i++) if(i!=pos_offen && i!=tipp) if(alt==true)tipp=i;
Ein Tor ist getippt, ein anderes offen. Eines bleibt über, zu diesem muss ich wechseln. Ich iteriere das Array,finde die Position, die weder offen noch getippt ist und wechsle wenn alt(=alternativwahl aktiveren) wahr ist.
Genau, aber was passiert, *nachdem* du gewechselt hast? BTW, ich hätt ja die Funktion wenigstens ein paar mal mit Testausgaben durchlaufen lassen, dann hätte man das Problem sofort gesehen
-
Ja, klar. So ein dämlicher Fehler
ein 'break' genügt. Habs neu kompiliert und siehe da: im Schnitt 2/3.
Bin jetzt voll lang auf der Leitung gestanden
-
SliderMaxx schrieb:
Blue-Tiger:
Dass es bei dir genau 2/3 sind, ist nicht verwunderlich:
Bei dir passiert folgendes. Nehmen wir an, das winningdoor=1, das chosendoor=2
das eliminierte Tor darf nicht mit dem gewählten Tor übereinstimmen:do { eliminatedDoor = giveRandomNr(); } while (eliminatedDoor == chosenDoor);
Es kann aber mit dem winningdoor übereinstimmen. Dann wird der Hauptpreis geöffnet. Aber egal: Letzendlich überprüfst du nur, ob das winning door!=chosendoor ist.
Bei 3 Toren ist die Wahrscheinlichkeit dafür genau 2/3. Und das ist das Ergebnis.Gruß,
SLiderMaxx
*in die Ecke stell & schaem*
-
mein Fehler war nicht weniger schlimm
-
2/3 ?
Ich kenn das anders:
Beim ersten mal hat man 1/3 Gewinnchance.
Wenn man dann wechseln darf, wählt man aus 2 Toren, also Gewinnchanche 0.5. Daher soll man (aus mathematischer Sicht) das Tor wechseln, da 0.5 ja größer als 1/3 ist.
Klingt komisch is aber so^^
-
Das klingt nicht nur komisch, das ist auch Unfug.
-
Hi Pellaeon,
diese Begründung ist unsinn, da man ja wenigstens auf eine
Gesamtsumme der Wahrscheinlichkeiten von 1 kommen sollte.Jockel
-
Einfach mal folgende Überlegung anstellen. Spiele folgende Strategie: Du wechstelst auf jeden Fall.
Angenommen Du triffst beim ersten Tipp (WK 1/3). Dann wechselst Du nachher auf jeden Fall aufs falsche Tor und verlierst.
Angenommen Du triffst nicht beim ersten Tipp (WK 2/3). Dann macht der Showmaster Dir eine falsche Möglichkeit weg und nach dem Wechsel bist Du bei der richtigen Tür.
MfG Jester