-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathday_05.ex
69 lines (59 loc) · 1.9 KB
/
day_05.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
defmodule AdventOfCode.Y2016.Day05 do
@moduledoc """
--- Day 5: How About a Nice Game of Chess? ---
Problem Link: https://adventofcode.com/2016/day/5
Difficulty: s
Tags: slow md5 annoying
"""
def input, do: "cxdnnyjw"
def run(input \\ input()) do
solution_1 = Task.async(fn -> run_1(input) end)
solution_2 = Task.async(fn -> run_2(input) end)
{
Task.await(solution_1, :infinity),
Task.await(solution_2, :infinity)
}
end
def run_1(input) do
Stream.iterate(1, &(&1 + 1))
|> Enum.reduce_while({"", 0}, fn x, {hash, iter} ->
new_hash = md5(input <> to_string(x))
case {five_zeroes?(new_hash), iter + 1} do
{true, 8} -> {:halt, hash <> String.at(new_hash, 5)}
{true, val} -> {:cont, {hash <> String.at(new_hash, 5), val}}
_ -> {:cont, {hash, iter}}
end
end)
end
@valid "01234567"
def run_2(input) do
Stream.iterate(1, &(&1 + 1))
|> Enum.reduce_while(
%{coords: [], done: MapSet.new()},
fn x, %{coords: coords, done: done} = acc ->
hash = md5(input <> to_string(x))
{position, value} = {String.at(hash, 5), String.at(hash, 6)}
valid? = String.contains?(@valid, position) and position not in done
case {five_zeroes?(hash), valid?} do
{true, true} ->
done = MapSet.put(done, position)
coords = [{position, value} | coords]
instruction = (length(coords) == 8 && :halt) || :cont
{instruction, %{coords: coords, done: done}}
_ ->
{:cont, acc}
end
end
)
|> construct_pasword()
end
defp md5(door_id) do
:crypto.hash(:md5, door_id) |> Base.encode16(case: :lower)
end
defp five_zeroes?(door_id), do: String.starts_with?(door_id, "00000")
defp construct_pasword(%{coords: coords}) do
coords
|> Enum.sort_by(&elem(&1, 0))
|> Enum.map_join(fn {_, v} -> v end)
end
end