Ziegenproblem



  • Hey Leute,
    ich schreibe gerade einen Simulator für das Ziegenproblem:
    "Angenommen Sie befinden sich in einer Spielshow und haben die Wahl zwischen drei Toren. Hinter einem Tor ist ein Auto, hinter den anderen sind Ziegen. Das Auto und die Ziegen sind vor der Show zufällig hinter die Tore verteilt worden. Die Regeln der Spielshow sind folgende: Nachdem Sie ein Tor gewählt haben bleibt dieses zunächst geschlossen. Der Showmaster Monty Hall, der weiß was sich hinter den Toren befindet, muss nun eine der beiden verbleibenden Tore öffnen, und hinter dem von ihm geöffneten Tor muss sich eine Ziege befinden. Wenn hinter beiden verbleibenden Toren jeweils eine Ziege steht, öffnet er eines der beiden Tore zufällig. Nachdem Monty Hall ein Tor mit einer Ziege geöffnet hat fragt er Sie, ob Sie bei Ihrer ersten Wahl bleiben oder zum letzten verbleibenden Tor wechseln möchten. Nehmen Sie an Sie wählen Tor 1 und der Showmaster öffnet Tor 3 mit einer Ziege. Er fragt Sie dann: „Möchten Sie zu Tor 2 wechseln?“ Ist es zu Ihrem Vorteil, Ihre Wahl zu ändern?"
    Mein Problem ist es, dass mein Algorythmus gegen die REgel verstößt, das er immer das/die Tor/Tore öffnet, die noch geschloßen, vom Spieler auch noch nicht gewählt worde sind und hinter denen kein Auto ist.
    DAfür benutze ich folgenden Code:

    Code:

    DoorOpen = false;
    for (int i = 0; i < testrow.DoorsToOpen; i++)
        {
            while (!DoorOpen)                // Showmaster oeffnet Tueren
            {
                DoorToOpen = rand() % testrow.countDoors;
                if (!doors[DoorToOpen].selected && doors[DoorToOpen].closed && doors[DoorToOpen].Inhalt != car)
                {
                    DoorOpen = true;
                    doors[DoorToOpen].closed = false;
                }
            }
            DoorOpen = false;
        }
    

    eine andere fehlerquelle könnte in der auswahl des zweiten tores liegen. DEr code dafür:

    Code:

    DoorOpen = false;
    while (!DoorOpen)                                  // Zweite Tuer auswaehlen
        {
            DoorToOpen = rand() % testrow.countDoors;
            if (DoorToOpen != testrow.selectedDoor1 && doors[DoorToOpen].closed)
            {
                testrow.selectedDoor2 = DoorToOpen;
                doors[DoorToOpen].selected = true;
                DoorOpen = true;
            }
        }
    

    Könnt ihr mir sagen wo er Fehler liegt, oder habt ihr einen anderen Vorschlag, wie ich das Auswahlverfahren gestalten könnte?

    Hier nochmal der komplette Code(falls es hilft):

    Code:

    // Ziegenproblem Simulator 0.1
    #include <cstdlib>
    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    // Deklarationen
    
    enum content {goat, car};                                                      
    
    struct GarageDoor
    {
        enum content Inhalt;
        bool closed;
        bool selected;
    };
    
    struct Experiment
    {
        int attempts;
        int number;                                                                 // Index des Versuchs, Anzahl der Versuche
        short countDoors;
        short DoorsToOpen;
        short CarDoor;                                                              // Index (0-2) des Tores mit Auto
        short selectedDoor1, selectedDoor2;                                         // Ausgewaehltes Tor vor, nach Wechsel
        int rightWC;                                                                // Anzahl aller richtigen Auswahlen nach Wechsel
        int rightNC;                                                                // Anzahl aller richtigen Auswahlen ohne Wechsel
        int wrongs;                                                                 // Anzahl aller falschen Auswahlen
        bool rightWithChange;
        bool rightNoChange;
        bool wrong;
    };    
    
    struct GarageDoor* simulation_init(struct Experiment &testrow, short countDoor, short DoorsToOpen, int attempts);
    void simulation_run(struct Experiment &testrow, struct GarageDoor *doors);
    
    //
    int main(int argc, char** argv)
    {
        struct GarageDoor *doors;
        struct Experiment attempt;
        doors = simulation_init(attempt, 3, 1, 10);
        srand(8895);
        while (true){
        simulation_run(attempt, doors);
        cout << attempt.selectedDoor1 << " " << attempt.selectedDoor2 << " " << attempt.CarDoor << endl;
        for (int i = 0; i < attempt.countDoors; i++)
        {
            /*simulation_run(attempt, doors);
            cout << attempt.CarDoor << endl << attempt.selectedDoor1 << endl << attempt.selectedDoor2 << endl;
            getchar();*/
            cout  << doors[i].Inhalt << " " << doors[i].selected << " " << doors[i].closed << endl;
        }
        getchar();
    }
        cout << endl << endl << attempt.rightWC/attempt.attempts << endl << attempt.rightNC/attempt.attempts << endl << attempt.wrongs;
    
        getchar();
    }
    
    // Definitionen
    
    struct GarageDoor* simulation_init(struct Experiment &testrow, short countDoor, short DoorsToOpen, int attempts)// voraussichtlich richtig
    {
        GarageDoor* doors = 0;
        testrow.attempts = attempts;
        testrow.number = 0;
        testrow.CarDoor = 0;
        testrow.selectedDoor1 = testrow.selectedDoor2 = 0;
        testrow.rightWC = testrow.rightNC = 0;
        testrow.wrongs = 0;
        testrow.rightWithChange = testrow.rightNoChange = testrow.wrong = false;
    
        if (3 > countDoor)
        {
            countDoor = 3;
            DoorsToOpen = 1;
            testrow.countDoors = countDoor;
            testrow.DoorsToOpen = DoorsToOpen;
        }
        else if (1000 < countDoor)
        {
            countDoor = 1000;
            testrow.countDoors = countDoor;
            if (DoorsToOpen < countDoor - 1 && DoorsToOpen >= 1)
            {
                testrow.DoorsToOpen = DoorsToOpen;
            }
            else
            {
                DoorsToOpen = 1;
                testrow.DoorsToOpen = DoorsToOpen;
            }
        }
        else
        {
            testrow.countDoors = countDoor;
            if (DoorsToOpen < countDoor - 1 && DoorsToOpen >= 1)
            {
                testrow.DoorsToOpen = DoorsToOpen;
            }
            else
            {
                DoorsToOpen = 1;
                testrow.DoorsToOpen = DoorsToOpen;
            }
        }
    
        doors = new GarageDoor[countDoor];
        return doors;
    }
    
    void simulation_run(struct Experiment &testrow, struct GarageDoor *doors)
    {
        bool DoorOpen = false;
        short DoorToOpen;
        for (int i = 0; i < testrow.countDoors; i++)
        {
            doors[i].closed = true;
            doors[i].selected = false;
            doors[i].Inhalt = goat;
        }
        doors[rand()%testrow.countDoors].Inhalt = car;                              // Auto wird hinter einer Tuer versteckt
        testrow.selectedDoor1 = rand() % testrow.countDoors;                        // Spieler waehlt ein Tor aus
        doors[testrow.selectedDoor1].selected = true;
        /*if (doors[testrow.selectedDoor1].Inhalt == car)
        {
            testrow.rightNC++;
            testrow.number++;
            testrow.rightNoChange = true;
            return;
        }*/
        for (int i = 0; i < testrow.DoorsToOpen; i++)
        {
            while (!DoorOpen)                                                       // Showmaster oeffnet Tueren
            {
                DoorToOpen = rand() % testrow.countDoors;
                if (!doors[DoorToOpen].selected && doors[DoorToOpen].closed && doors[DoorToOpen].Inhalt != car)
                {
                    DoorOpen = true;
                    doors[DoorToOpen].closed = false;
                }
            }
            DoorOpen = false;
        }
        while (!DoorOpen)                                                           // Zweite Tuer auswaehlen
        {
            DoorToOpen = rand() % testrow.countDoors;
            if (DoorToOpen != testrow.selectedDoor1 && doors[DoorToOpen].closed)
            {
                testrow.selectedDoor2 = DoorToOpen;
                doors[DoorToOpen].selected = true;
                DoorOpen = true;
            }
        }
          if (doors[testrow.selectedDoor1].Inhalt == car)
        {
            testrow.rightNC++;
            testrow.number++;
            testrow.rightNoChange = true;
            return;
        }
        else if (doors[testrow.selectedDoor2].Inhalt == car)
        {
            testrow.rightWC++;
            testrow.number++;
            testrow.rightWithChange = true;
            return;
        }
        else
        {
            testrow.wrongs++;
            testrow.number++;
            testrow.wrong = true;
            return;
        }
    }
    

    Vielen Dank schon mal für eure Mühe



  • Nanu, warum so viel Code? Es reicht doch:

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    
    static inline int random(int lim) {return rand()%lim;}
    
    int main()
    {
      int wechselErfolge=0;
      const int tore=3,durchlaeufe=1000000;
      for (int i=0;i<durchlaeufe;i++)
      {
        const int autoTor=random(tore);
        const int wahl=random(tore);
        /*int ziegenTor; //gehört zwar dazu, hat aber keine Auswirkung
        do ziegenTor=random(tore);
        while (ziegenTor==wahl || ziegenTor==autoTor);*/
        if (wahl!=autoTor)wechselErfolge++;
      }
      cout << "Erfolge beim Wechsel: " << wechselErfolge << "/" << durchlaeufe << endl;
    }
    

    Der Teil nach dem "Nehmen Sie an" ist etwas heikel, müsste aber eigentlich durch folgende Anpassung korrekt umgesetzt sein:

    const int autoTor=random(tore);
        if (autoTor==2)
        {
          i--;
          continue;
        }
        const int wahl=0;
    

    ...ohne jegliche Gewähr.



  • PrivateArms schrieb:

    Hey Leute,
    ich schreibe gerade einen Simulator für das Ziegenproblem:
    "Angenommen Sie befinden sich in einer Spielshow und haben die Wahl zwischen drei Toren. Hinter einem Tor ist ein Auto, hinter den anderen sind Ziegen. Das Auto und die Ziegen sind vor der Show zufällig hinter die Tore verteilt worden. Die Regeln der Spielshow sind folgende: Nachdem Sie ein Tor gewählt haben bleibt dieses zunächst geschlossen. Der Showmaster Monty Hall, der weiß was sich hinter den Toren befindet, muss nun eine der beiden verbleibenden Tore öffnen, und hinter dem von ihm geöffneten Tor muss sich eine Ziege befinden. Wenn hinter beiden verbleibenden Toren jeweils eine Ziege steht, öffnet er eines der beiden Tore zufällig. Nachdem Monty Hall ein Tor mit einer Ziege geöffnet hat fragt er Sie, ob Sie bei Ihrer ersten Wahl bleiben oder zum letzten verbleibenden Tor wechseln möchten. Nehmen Sie an Sie wählen Tor 1 und der Showmaster öffnet Tor 3 mit einer Ziege. Er fragt Sie dann: „Möchten Sie zu Tor 2 wechseln?“ Ist es zu Ihrem Vorteil, Ihre Wahl zu ändern?"
    Mein Problem ist es, dass mein Algorythmus gegen die REgel verstößt, das er immer das/die Tor/Tore öffnet, die noch geschloßen, vom Spieler auch noch nicht gewählt worde sind und hinter denen kein Auto ist.
    DAfür benutze ich folgenden Code:
    [/code]

    Musst du dafür eine Simulation schreiben, oder findest du nicht ein bisschen Nachdenken und eine Antwort in drei Sätzen schöner?



  • @Mups, ich kenne die Antwort doch schon: Mit Wechsel p=2/3 ohne p=1/3. Ich schreibe das nur zu Übung.

    @Athar Ja du hast recht, das reicht für drei Tore. Allerdings wollte ich, dass z.B. der Folgende Fall möglich ist: 1000 Tore, aber nur 990 werden geöffnet.
    Die Strukur (Deshalb auch die Init funktion) soll die Date für eine spätere Auswertung speichern. Deshalb so viel (wahrschein zum teil wirklich zu viel) Code...

    naja ist ansonsten dieses Auswahlverfahren vom Prinzip richtig?

    DoorOpen = false;
    while (!DoorOpen)                                  // Zweite Tuer auswaehlen
        {
            DoorToOpen = rand() % testrow.countDoors;
            if (DoorToOpen != testrow.selectedDoor1 && doors[DoorToOpen].closed)
            {
                testrow.selectedDoor2 = DoorToOpen;
                doors[DoorToOpen].selected = true;
                DoorOpen = true;
            }
        }
    

    mfg


Anmelden zum Antworten