몬티홀 문제 Go lang으로 이해해보기

개발개발·2022년 7월 13일
0

몬티홀 문제는 미국의 TV show에서 유래한 확률게임이다.
문제는 아래와 같다.

1. 세 개의 문이 있다.
2. 문 뒤에는 경품으로 줄 자동차 1대와 꽝이 2개가 있다.
3. 게스트는 문 하나를 고른다.
4. MC가 꽝이 있는 문을 보여준다.
5. 선택을 바꿀것인지 묻는다.

이때 당신의 선택은?

과연 선택을 바꾸는게 확률상 유리한 것일까 아니면 확률에 차이가 없을까.

정답은 바꾸는 것이 유리하다. 이것을 코드를 짜서 확인해 보았다. go 를 사용해서 만들었다.

package main
import (
	"fmt"
	"math/rand"
)
func main(){
	Monti(100000, true)// 바꾸기 전략 사용
    Monti(100000, false) // 바꾸기 전략을 사용하지 않음
}
func MontyHal(count int, ok bool) {
	win := 0
	lose := 0

	for i := 0; i < count; i++ {

		answer := 0 // 최종 선택
		doors := make([]int, 3) // 문들
		options := []int{0, 1, 2} // 남은 선택지

		car := rand.Int() % 3 // 자동차가 숨은 문
		myChoose := rand.Int() % 3 // 나의 선택

		doors[car] = 1

		if ok { // 바꾸기 전략 사용
			if car == myChoose {
				remove(&options, car)
				answer = options[0] // options[0] or options[1] 둘다 오답이다. 
			} else {
				remove(&options, car) // mc가 보여주는 선택지에서 car제외
				remove(&options, myChoose) // 바꾸기 전략이므로 나의 선택 제외
				// MC는 options[0]을 보여준다. 나의 선택은 myChoose와 options[0]을 제외하므로 반드시 car를 선택하게 된다.
				answer = car
			}
		} else { // 바꾸기 전략 사용 안함
			answer = myChoose
		}

		// 문을 열어 확인해본다.
		if doors[answer] == 1 {
			win += 1
		} else {
			lose += 1
		}
	}
	fmt.Println(win, lose)
	fmt.Println(win*100/(win+lose), lose*100/(win+lose))
}

func remove(s *[]int, num int) {
	for i, v := range *s {
		if v == num {
			(*s)[i] = (*s)[len(*s)-1]
			(*s) = (*s)[:len(*s)-1]
			return
		}
	}
}

논리적으로 당연하게 생각해 낼 수 있으면 좋겠지만 코드로 짜보면서 확인해보았다.

바꾸기 전략을 사용하지 않는다면 1/3 확률이다.
바꾸기 전략을 사용할때는 두가지 경우의 수로 나뉜다.

  1. 처음 고른 문이 정답인 경우.
    -> 바꾸게 되므로 오답. 이때 처음 고른 문이 정답인 경우는 1/3 이므로 오답을 고를 확률은 1/3

  2. 처음 고른 문이 오답인 경우
    -> MC가 오답인 문을 하나 걸러줌. 즉 남은 문은 정답
    -> 바꾸면 맞는 문이다. 즉 확률은 2/3

선택을 바꿈으로 인해 확률이 2배가 차이가 난다.

profile
청포도루이보스민트티

0개의 댓글