Let’s Make A Deal! Programming Praxis.
Monty Hall 문제로 잘 알려져 있는 확률 문제를 실제로 시뮬레이션 해보는 프로그램.
아래는 OCaml 코드
-
open Random;;
-
open Array;;
-
open Printf;;
-
-
let rec shuffle arr n =
-
if n = 0 then arr
-
else begin
-
let a = Random.int (length arr) in
-
let b = Random.int (length arr) in
-
let va = Array.get arr a in
-
Array.set arr a (Array.get arr b);
-
Array.set arr b va;
-
shuffle arr (n-1)
-
end
-
-
exception Found
-
let find_unchosen_goat arr choice =
-
let ug = ref 0 in
-
try
-
Array.iteri
-
(fun i _ ->
-
if i != choice && Array.get arr i != 1 then begin ug := i; raise Found end
-
else ug := i)
-
arr;
-
0
-
with _ -> !ug
-
-
let find_change_choice arr old_choice unchosen_goat =
-
let cc = ref 0 in
-
try
-
Array.iteri
-
(fun i _ ->
-
if i != old_choice && i != unchosen_goat then begin cc := i; raise Found end
-
else cc := i)
-
arr;
-
0
-
with _ -> !cc
-
-
let check_choice arr choice = Array.get arr choice = 1
-
-
let deal change =
-
let doors = shuffle [|0;0;1;|] 10 in
-
let choice = Random.int 3 in
-
let unchosen_goat = find_unchosen_goat doors choice in
-
let last_choice =
-
if change then find_change_choice doors choice unchosen_goat
-
else choice
-
in
-
check_choice doors last_choice
-
-
(** Written by myself – simulate the whole game *)
-
let simulate ngames =
-
let switch_game_result = Array.map (fun _ -> deal true) (Array.init ngames (fun i -> i)) in
-
let switch_wins = Array.fold_left (fun wins result -> if result then wins+1 else wins) 0 switch_game_result in
-
let stay_game_result = Array.map (fun _ -> deal false) (Array.init ngames (fun i -> i)) in
-
let stay_wins = Array.fold_left (fun wins result -> if result then wins+1 else wins) 0 stay_game_result in
-
Printf.printf "Winning rate for switch choice : %f\n" ((float_of_int switch_wins) /. (|>float_of_int ngames));
-
Printf.printf "Winning rate for stay choice : %f\n" ((float_of_int stay_wins) /. (|>float_of_int ngames))
-
-
(** Translation of suggested solution – simplified simulation*)
-
let monty n =
-
Random.self_init ();
-
let rec monty n switch stay =
-
let auto,pick = Random.int 3, Random.int 3 in
-
if n = 0 then (switch,stay)
-
else
-
if auto = pick then monty (n-1) switch (stay+1)
-
else monty (n-1) (switch+1) stay
-
in
-
monty n 0 0
-
-
(** More simplified *)
-
let monty2 n =
-
Random.self_init ();
-
let rec monty2 n switch =
-
let pick = Random.int 3 in
-
if n = 0 then switch
-
else
-
if pick = 0 then monty2 (n-1) switch
-
else monty2 (n-1) (switch+1)
-
in
-
monty2 n 0
결과를 보면 선택을 바꾼 경우 이길 확률이 2/3가 된다는 것을 볼 수 있다.
# monty2 1000;; - : int = 674 # monty2 10000;; - : int = 6657 # monty2 100000;; - : int = 66647

