Skip to content

Instantly share code, notes, and snippets.

@joseph-lozano
Created October 8, 2020 13:27
Show Gist options
  • Save joseph-lozano/a8f4e669d022d872bf66e4e2968275ac to your computer and use it in GitHub Desktop.
Save joseph-lozano/a8f4e669d022d872bf66e4e2968275ac to your computer and use it in GitHub Desktop.
defmodule MontyHall do
defstruct [:doors, :hidden]
def play(door_count) do
game = new(door_count)
pick = :crypto.rand_uniform(1, door_count + 1)
with_revealed_doors = first_move(game, pick)
{action, new_pick} =
case Enum.random([:switch, :dont]) do
:switch ->
[new_pick] = Enum.reject(with_revealed_doors.hidden, fn x -> x == pick end)
{:switch, new_pick}
:dont ->
{:dont, pick}
end
{action, Map.get(game.doors, new_pick)}
end
def play(times, door_count) do
for _ <- 1..times do
play(door_count)
end
|> Enum.frequencies()
end
def new(door_count) do
car_index = :crypto.rand_uniform(1, door_count + 1)
doors =
1..door_count
|> Enum.map(fn i -> {i, :goat} end)
|> Enum.into(%{})
|> Map.put(car_index, :car)
%__MODULE__{doors: doors}
end
def first_move(%__MODULE__{doors: doors} = game, pick) do
%__MODULE__{
game
| hidden: [
pick,
case Map.get(doors, pick) do
:goat -> get_car(doors)
:car -> get_goat(doors)
end
]
}
end
def get_goat(doors) do
doors
|> Enum.filter(fn {_, x} -> x == :goat end)
|> Enum.random()
|> elem(0)
end
def get_car(doors) do
doors
|> Enum.find(fn {_, x} -> x == :car end)
|> elem(0)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment