[JAVA] A quick look at the Monty Hall problem

Introduction

What is the Monty Hall problem? According to [Wikipedia](https://ja.wikipedia.org/wiki/Monty Hall problem)

There are three closed doors in front of the player, behind one door is a new prize car, and behind the two doors is a goat, which means off. Players can get a new car by hitting the door of the new car. After the player selects one door, the moderator Monty opens the remaining door with the goat and shows the goat. The player is now told that he may change the door of his choice to the remaining unopened door. Should the player change the door here?

It seems that it is a problem. (* However, Monty knows where to go and always opens the place where the goat is.) At first glance, it seems that the probability does not change whether you change the door or not, but in fact it seems that it is advantageous for the player to change it **. This time I would like to try this experiment a lot and compare the results. The language is always safe Java ~~ (as much as you like) ~~.

Requirements

--Try Monty Hall with the number of doors set to NUMBER_DOORS. --Monty opens the door {NUMBER_DOORS --2} times. (That is, repeat until the last two choices.) --Whether to change the door is represented by CHANGE_DOOR. (If true, change the door. If false, do not change the door.) --Try only TRY_TIMES, and find the ratio of new cars assigned by the number of new cars assigned and TRY_TIMES. --Use Java (Oracle JDK 13).

code

Monty.java


import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.util.Random;

public class Monty {
    public static final int NUMBER_DOORS = 4;
    public static final int TRY_TIMES = 10000;
    public static final boolean CHANGE_DOOR = true; 

    //Randomly get doors other than the specified door
    public static int getOtherDoor(Collection<Integer> doorIndices) {
        List<Integer> notSelectedDoors = new ArrayList<>();
        
        for (int i = 0; i < NUMBER_DOORS; i++) {
            if(!doorIndices.contains(i)){
                notSelectedDoors.add(i);
            }
        }
        Collections.shuffle(notSelectedDoors);
        return notSelectedDoors.get(0);
    }

    //Monty Hall Trial
    public static boolean montyHoll(){
        //The number of times Monty opens the door
        final int OPEN_DORE_TIMES = NUMBER_DOORS - 2;
        
        Random r = new Random();
        int collectDoorIndex = r.nextInt(NUMBER_DOORS);
        int firstSelectDoorIndex = r.nextInt(NUMBER_DOORS);

        Set<Integer> notWillOpenDoorIndices = new HashSet<>();
        Set<Integer> openDoorIndices = new HashSet<>();

        notWillOpenDoorIndices.add(collectDoorIndex);
        notWillOpenDoorIndices.add(firstSelectDoorIndex);

        for (int i = 0; i < OPEN_DORE_TIMES; i++) {
            int otherDoor = getOtherDoor(notWillOpenDoorIndices);
            openDoorIndices.add(otherDoor);
            notWillOpenDoorIndices.add(otherDoor);
        }

        Set<Integer> notWillSelectDoorIndices = new HashSet<>(openDoorIndices);
        notWillSelectDoorIndices.add(firstSelectDoorIndex);

        int secondSelectDoorIndex = CHANGE_DOOR?getOtherDoor(notWillSelectDoorIndices):firstSelectDoorIndex;

        boolean getCar = (collectDoorIndex == secondSelectDoorIndex);
        /*System.out.printf("c:%d,fs:%d,ss:%d,g:%s\n", 
        collectDoorIndex, firstSelectDoorIndex, secondSelectDoorIndex, Boolean.toString(getCar));*/
        return getCar;
    }

    public static void main(String[] args) {
        int getCarTimes = 0;
        for (int i = 0; i < TRY_TIMES; i++) {
            if(montyHoll()){
                getCarTimes++;
            }
        }
        System.out.println((double)getCarTimes / (double)TRY_TIMES);
    }
}

result

――We experimented three times each. ――However, if you change the door and if you do not change it, we will do it separately. (That is, the horizontal direction does not correspond.)

Table 1: Three doors

No. If you change the door If you don't change the door
1 0.6687 0.3401
2 0.6683 0.3409
3 0.6631 0.3351

Table 2: 4 doors

No. If you change the door If you don't change the door
1 0.7561 0.2531
2 0.7486 0.2463
3 0.7534 0.2514

Table 3: Five doors

No. If you change the door If you don't change the door
1 0.8006 0.2086
2 0.8038 0.2059
3 0.8011 0.1947

Summary

――No matter how many doors you have, changing the door seems to have a higher probability. ――The more doors you have, the more advantageous it will be to change them.

in conclusion

Until very recently, this problem didn't go unnoticed. With this, I feel like I was able to swallow it for the time being. After all it is important to confirm.

Recommended Posts

A quick look at the Monty Hall problem
A quick look back at Java over the last five years
Take a quick look at Gradle and read the build.gradle generated by Spring Initializr
Let's take a look at the screen of Quant Analyzer!
A memorandum of the FizzBuzz problem
A solution to the problem of blank spaces at the beginning of textarea
I took a look at the resources of Azure Container Instance
A look at Jenkins, OpenJDK 8 and Java 11
After verifying the Monty Hall problem with Ruby, a story that I could understand well and did not understand well
Let's take a look at the functions of Keycloak's management console (administrator edition)
[At Coder] Solve the ABC183 D problem with Ruby
[At Coder] Solve the ABC182 D problem with Ruby
Let's take a look at the functions of Keycloak's management console (user edition), user account service
Use cryptographically secure pseudo-random numbers to verify that the solution to the Monty Hall problem is not 50%