몬티홀 문제

skyepodium·2022년 5월 5일
23
post-thumbnail

몬티홀 구현해 봅시다.
구현된 링크: https://skyepodium.github.io/montyhall/

1. 개요

당신은, 자동차를 선택해야하는 퀴즈쇼에 들어왔습니다.

3개의 문이 있습니다.

  • 2개의 문에는 염소
  • 1개의 문에는 자동차가 있습니다.

당신은 하나의 문을 선택했습니다.

그런데 사회자가 당신이 선택하지 않은 문중 하나를 열어서 염소가 들어있음을 보여주었습니다.

그리고 물어봅니다.

지금 선택한 문을 바꿀것인가요? 안바꿀 것인가요?

바꾸는 것이 수학적으로 유리하다고 합니다.

바꿨을 때 이길 확률: 66.6%
유지했을 때 이길 확률: 33.3%

2. 계산

자바스크립트로 계산해보면 바꾸는 것이 유리합니다.

바꾸고 이긴 확률 66.82
바꿨는데 진 확률 33.17
유지했는데 이긴 확률 33.17
유지했는데 진 확률 66.82
const getRandomVal = () => {
    return Math.floor(Math.random() * (3))
}

const maxInt = 100000

let changeWinCnt = 0
let changeLoseCnt = 0
let stayWinCnt = 0
let stayLoseCnt = 0

for(let i=0; i<maxInt; i++) {
    const answer = getRandomVal()
    const pick = getRandomVal()

    let close = getRandomVal()
    while(close === answer || close === pick) {
        close = getRandomVal()
    }

    if(pick === answer) stayWinCnt++
    else stayLoseCnt++

    let change = getRandomVal()
    while(close === change || pick === change) {
        change = getRandomVal()
    }

    if(answer === change) changeWinCnt++
    else changeLoseCnt++
}

console.log("바꾸고 이긴 확률", Math.trunc(changeWinCnt * 100 / maxInt * 100) / 100)
console.log("바꿨는데 진 확률", Math.trunc(changeLoseCnt * 100 / maxInt * 100) / 100)
console.log("유지했는데 이긴 확률", Math.trunc(stayWinCnt * 100 / maxInt * 100) / 100)
console.log("유지했는데 진 확률", Math.trunc(stayLoseCnt * 100 / maxInt * 100) / 100)

/*
바꾸고 이긴 확률 66.82
바꿨는데 진 확률 33.17
유지했는데 이긴 확률 33.17
유지했는데 진 확률 66.82
*/

3. 차트

chart.js를 사용했고, 10만번 수행했습니다.

약 66%의 확률로 수렴합니다.

4. 직접 해보기

데모 링크: https://skyepodium.github.io/montyhall/

1) 눌러보기

그냥 직접 눌러서 보고 싶어서 만들어보았습니다.

다만, 1만번 이하로 하는것은 크게 의미가 없었습니다.

반짝반짝 눈아파서, 오래는 못보는데 대략 1만번번 이상 수행해야 성공확률이 약 66%로 수렴합니다.

마치 주사위도 많이 던져야 각 면이 나올 확률이 1/6로 수렴하는것처럼 오래해야합니다.

배운점 - 확률은 많이해야 수렴합니다. 적어도 1만번 이상

2) 10만번 수행하기 API

JS 코드로 10만번 수행했고, 성공 확률: 66%, 실패 확률 33%가 나왔습니다.

주의, 크롬에서 해야합니다. 10만번은 횟수가 커서 브라우저가 느려집니다. 개인적으로 1만번만 수행하는것을 추천합니다.

데모 페이지에서 브라우저 개발자 도구 열고 콘솔창에 아래 코드를 실행합니다.

const getRandomVal = range => {
    return Math.floor(Math.random() * range)
}

const maxInt = 10000

for(let i=0; i<maxInt; i++) {
    const selectDoor = getRandomVal(3)
    const closeDoor = montyHall.selectDoor(selectDoor)

    const chagedDoor = 3 - closeDoor - selectDoor

    montyHall.check(chagedDoor)
}

5.코드

차트와 UI가 있는 모든 코드
https://github.com/skyepodium/montyhall

profile
callmeskye

5개의 댓글

comment-user-thumbnail
2022년 5월 9일

넷플릭스 DP에서 몬티홀 문제라는 것을 알게 되고 신기하다고 생각했는데
이렇게 코드로 또 보게될 줄은 몰랐네요 ㅎㅎㅎ

재밌게 잘 읽었습니다!

답글 달기
comment-user-thumbnail
2022년 5월 9일

좋은 글 감사합니다. ^^

답글 달기
comment-user-thumbnail
2022년 5월 12일

재밌게 잘 읽었습니다

답글 달기
comment-user-thumbnail
2022년 5월 12일

저도 학교 대회용으로 만든적이 있는데 새롭네요 ㅎㅎ
https://hyunsdev.github.io/SSR-monty-hall-problem-p5js/

답글 달기
comment-user-thumbnail
2023년 10월 30일

감사합니다.

답글 달기