Solving Einsteins Riddle with Elixir
Sean Handley has solved Einstein’s riddle in a remarkable way using Ruby. I stand on his shoulders and forced his code through Elixir.
Please checkout out his amazing blog post on Medium: Sean Handley: Solving Einstein’s Riddle with Ruby and/or the corresponding repository on GitHub
How to run?
-
Clone the code from github
-
$ iex einstein.exs
then enterEinstein.solve
defmodule Permutations do
# Nathan Long showed up with this
# http://stackoverflow.com/a/33756397/6601963
def of([]), do: [[]]
def of(list), do: for h <- list, t <- of(list -- [h]), do: [h | t]
end
defmodule Einstein do
def solve do
solve_colors()
end
def left_of?(set_a, val_a, set_b, val_b) do
(0..4)
|> Enum.any?(fn(x) -> Enum.at(set_a, x) == val_a && Enum.at(set_b, x+1) == val_b end)
end
def next_to?(set_a, val_a, set_b, val_b) do
left_of?(set_a, val_a, set_b, val_b) || left_of?(set_b, val_b, set_a, val_a)
end
def implies?(set_a, val_a, set_b, val_b) do
(0..4)
|> Enum.any?(fn(x) -> Enum.at(set_a, x) == val_a && Enum.at(set_b, x) == val_b end)
end
def solve_colors do
all_colors = Permutations.of [:white, :yellow, :blue, :red, :green] |> Enum.shuffle()
for colors <- all_colors,
left_of?(colors, :green, colors, :white),
do: solve_nationalities(colors)
end
def solve_nationalities(colors) do
all_nationalities = Permutations.of [:german, :swedish, :british, :norwegian, :danish,] |> Enum.shuffle()
for nationalities <- all_nationalities,
implies?(nationalities, :british, colors, :red) &&
Enum.at(nationalities, 0) == :norwegian &&
next_to?(nationalities, :norwegian, colors, :blue),
do: solve_pets(colors, nationalities)
end
def solve_pets(colors, nationalities) do
all_pets = Permutations.of [:birds, :cats, :horses, :fish, :dogs] |> Enum.shuffle()
for pets <- all_pets,
implies?(nationalities, :swedish, pets, :dogs),
do: solve_drinks(colors, nationalities, pets)
end
def solve_drinks(colors, nationalities, pets) do
all_drinks = Permutations.of [:beer, :water, :tea, :milk, :coffee] |> Enum.shuffle()
for drinks <- all_drinks,
Enum.at(drinks,2) == :milk &&
implies?(colors, :green, drinks, :coffee) &&
implies?(nationalities, :danish, drinks, :tea),
do: solve_cigars(colors, nationalities, pets, drinks)
end
def solve_cigars(colors, nationalities, pets, drinks) do
all_cigars = Permutations.of [:blends, :pall_mall, :prince, :bluemasters, :dunhill] |> Enum.shuffle()
for cigars <- all_cigars,
next_to?(pets, :horses, cigars, :dunhill) &&
implies?(cigars, :pall_mall, pets, :birds) &&
next_to?(cigars, :blends, drinks, :water) &&
next_to?(cigars, :blends, pets, :cats) &&
implies?(nationalities , :german, cigars, :prince) &&
implies?(colors, :yellow, cigars, :dunhill) &&
implies?(cigars, :bluemasters, drinks, :beer)
do
IO.inspect([colors, nationalities, pets, drinks, cigars])
List.zip([colors, nationalities, pets, drinks, cigars])
|> Enum.each(fn({color, nat, pet, drink, cigar}) ->
IO.puts("The #{nat} lives in the #{color} house, has a #{pet}, drinks #{drink} and prefers #{cigar} when smoking.")
end)
System.halt(0)
end
end
end
⬅️ Read previous Read next ➡️