-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathday_23.ex
123 lines (103 loc) · 2.87 KB
/
day_23.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
defmodule AdventOfCode.Y2017.Day23 do
@moduledoc """
--- Day 23: Coprocessor Conflagration ---
Problem Link: https://adventofcode.com/2017/day/23
Difficulty: m
Tags: op-code
"""
alias AdventOfCode.Helpers.{InputReader, Transformers}
@state %{
registers: %{
"a" => 0,
"b" => 0,
"c" => 0,
"d" => 0,
"e" => 0,
"f" => 0,
"g" => 0,
"h" => 0
},
index: 0,
muls: 0
}
def input, do: InputReader.read_from_file(2017, 23)
def run(input \\ input()) do
input = parse(input)
{run_1(input), run_2(input)}
end
defp run_1(input) do
process(@state, input)
end
defp run_2(_input) do
{:todo, 2}
end
def parse(data \\ input()) do
data
|> Transformers.lines()
|> Enum.map(fn line ->
line
|> String.split(" ")
|> parse_line()
end)
|> Enum.with_index()
|> Map.new(fn {v, k} -> {k, v} end)
end
defp parse_line([cmd, op1, op2]) do
{cmd, parse_arg(op1), parse_arg(op2)}
end
defp parse_arg(arg) do
case Integer.parse(arg) do
{num, ""} -> num
_ -> arg
end
end
defp process(%{index: index, muls: muls}, commands)
when index > map_size(commands) - 1 or index < 0,
do: muls
defp process(%{index: index} = state, commands) do
case commands[index] do
{"set", x, y} -> process(:set, state, commands, x, y)
{"sub", x, y} -> process(:sub, state, commands, x, y)
{"mul", x, y} -> process(:mul, state, commands, x, y)
{"jnz", 0, _} -> process(:jnz, state, commands)
{"jnz", x, y} -> process(:jnz, state, commands, x, y)
end
end
defp process(:set, %{index: index, registers: registers} = state, commands, x, y) do
y_value = (is_integer(y) && y) || registers[y]
state
|> Map.merge(%{registers: %{registers | x => y_value}, index: index + 1})
|> process(commands)
end
defp process(:sub, %{index: index, registers: registers} = state, commands, x, y) do
y_value = (is_integer(y) && y) || registers[y]
state
|> Map.merge(%{
registers: %{registers | x => registers[x] - y_value},
index: index + 1
})
|> process(commands)
end
defp process(:mul, %{index: index, registers: registers, muls: muls} = state, commands, x, y) do
y_value = (is_integer(y) && y) || registers[y]
state
|> Map.merge(%{
registers: %{registers | x => registers[x] * y_value},
index: index + 1,
muls: muls + 1
})
|> process(commands)
end
defp process(:jnz, %{index: index, registers: registers} = state, commands, x, y) do
y_value = (is_integer(y) && y) || registers[y]
jump_value = (registers[x] == 0 && 1) || y_value
state
|> Map.put(:index, index + jump_value)
|> process(commands)
end
defp process(:jnz, %{index: index} = state, commands) do
state
|> Map.put(:index, index + 1)
|> process(commands)
end
end