Advent of Code (2016) : Day 5
-- Problem --
You can find Part 1 of the problem statement
here. Part 2 is unlocked on successful completion of Part 1.
-- Solution in Elixir --
defmodule Aoc.Day5 do
def md5_hex(input_string) do
:crypto.hash(:md5, input_string) |> Base.encode16
end
def generate_password_1(door_id) do
do_generate_password_1(door_id, 0, [])
end
def do_generate_password_1(_, _, result) when length(result) == 8 do
Enum.reverse(result)
end
def do_generate_password_1(door_id, index, result) do
input_string = door_id <> Integer.to_string(index)
case md5_hex(input_string) do
"00000" <> rest -> do_generate_password_1(door_id, index + 1, [String.at(rest, 0) | result])
_ -> do_generate_password_1(door_id, index + 1, result)
end
end
def output_1() do
generate_password_1("ffykfhsq")
end
def generate_password_2(door_id) do
do_generate_password_2(door_id, 0, ["0","1","2","3","4","5","6","7"], [])
end
def do_generate_password_2(_, _, [], result) do
IO.puts("Decryption complete")
IO.write("Password is -- ")
Enum.sort(result)
|> Enum.map_join(fn({_,char}) -> char end)
end
def do_generate_password_2(door_id, index, position_list, result) do
input_string = door_id <> Integer.to_string(index)
<< trailing_zeros::40 >> <> << position, password_char >> <> _rest = md5_hex(input_string)
case {<< trailing_zeros::40 >>, << position >> in position_list} do
{"00000", true} ->
IO.puts("Decryption progress -- #{((length(result) + 1) / 8) * 100}% done")
do_generate_password_2(door_id, index + 1, position_list -- [<< position >>], [{<< position >>, << password_char >>} | result])
_ -> do_generate_password_2(door_id, index + 1, position_list, result)
end
end
def output_2() do
generate_password_2("ffykfhsq")
end
end
You can find all my Advent of Code (2016) solutions here.