-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathday_12.ex
78 lines (60 loc) · 2.02 KB
/
day_12.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
70
71
72
73
74
75
76
77
78
defmodule AdventOfCode.Y2016.Day12 do
@moduledoc """
--- Day 12: Leonardo's Monorail ---
Problem Link: https://adventofcode.com/2016/day/12
Difficulty: s
Tags: slow op-code
"""
alias AdventOfCode.Helpers.{InputReader, Transformers}
def input, do: InputReader.read_from_file(2016, 12)
@tokens ~w/a b c d cpy inc dec jnz/
@regs %{"a" => 0, "b" => 0, "c" => 0, "d" => 0}
def run(input \\ input()) do
instructions = parse(input)
solution_1 = Task.async(fn -> run_1(instructions) end)
solution_2 = Task.async(fn -> run_2(instructions) end)
{
Task.await(solution_1, :infinity),
Task.await(solution_2, :infinity)
}
end
def run_1(instructions) do
Map.get(exec(instructions, @regs, 0, Enum.count(instructions)), "a")
end
def run_2(instructions) do
Map.get(exec(instructions, %{@regs | "c" => 1}, 0, Enum.count(instructions)), "a")
end
def parse(data) do
data
|> Transformers.lines()
|> Enum.map(fn instruction ->
instruction
|> String.split(" ")
|> Enum.map(&sanitize/1)
end)
|> Enum.with_index()
|> Map.new(fn {cmd, idx} -> {idx, cmd} end)
end
defp exec(_, regs, s, s), do: regs
defp exec(cmds, regs, idx, s) do
case cmds[idx] do
["cpy", val, reg] when is_integer(val) ->
exec(cmds, %{regs | reg => val}, idx + 1, s)
["cpy", reg_val, reg] ->
exec(cmds, %{regs | reg => regs[reg_val]}, idx + 1, s)
["inc", reg] ->
exec(cmds, %{regs | reg => regs[reg] + 1}, idx + 1, s)
["dec", reg] ->
exec(cmds, %{regs | reg => regs[reg] - 1}, idx + 1, s)
["jnz", 0, _] ->
exec(cmds, regs, idx + 1, s)
["jnz", val, step] when is_integer(val) ->
exec(cmds, regs, idx + step, s)
["jnz", reg_val, step] ->
exec(cmds, regs, jump_on_nz(regs[reg_val], idx, step), s)
end
end
defp jump_on_nz(val, idx, step), do: idx + ((val == 0 && 1) || step)
defp sanitize(reg) when reg in @tokens, do: reg
defp sanitize(reg), do: String.to_integer(reg)
end