-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay3.exs
120 lines (105 loc) · 2.83 KB
/
Day3.exs
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
defmodule Parser do
def parse([]), do: 0
def parse(x) do
instruction = "mul("
char_count = instruction |> String.length()
nums = x |> Enum.drop(char_count) |> Enum.join("") |> String.split(",")
if length(nums) != 2 or x |> Enum.take(char_count) != instruction |> String.graphemes() do
0
else
nums
|> Enum.map(fn x ->
case Integer.parse(x) do
{int, _} -> int
:error -> 0
end
end)
|> Enum.product()
end
end
end
data = File.read!("data/day3.txt") |> String.trim() |> String.graphemes()
result =
Enum.reduce(
data,
%{
:sum_part1 => 0,
:sum_part2 => 0,
:chars => [],
:found => false,
:found_toggle => false,
:part2_multiplier => 1
},
fn x, acc ->
return_value =
cond do
# Start of \do\ or \dont\ command
x == "d" ->
%{
acc
| :chars => [x],
:found_toggle => true
}
# Constructed \do\ or \dont\ string, parsing
acc.found_toggle and x == "(" ->
abc =
case acc.chars |> Enum.join("") do
"do" ->
%{
acc
| :chars => [],
:found_toggle => false,
:part2_multiplier => 1
}
"don't" ->
%{
acc
| :chars => [],
:found_toggle => false,
:part2_multiplier => 0
}
_ ->
%{
acc
| :chars => [],
:found_toggle => false
}
end
abc
# Ending \mul(\
x == ")" ->
%{
acc
| :sum_part1 => acc.sum_part1 + Parser.parse(acc.chars),
:sum_part2 => acc.sum_part2 + Parser.parse(acc.chars) * acc.part2_multiplier,
:chars => [],
:found => false,
:found_toggle => false
}
x == "m" ->
%{
acc
| :chars => [x],
:found => true,
:found_toggle => false
}
# Building chars for \do()\, \dont()\ and \mul(...)\
(acc.found or acc.found_toggle) and String.contains?("0123456789,mul(don't(do", x) ->
%{
acc
| :chars => acc.chars ++ [x]
}
# Otherwise, reset
true ->
%{
acc
| :chars => [],
:found => false,
:found_toggle => false
}
end
return_value
end
)
IO.puts(result.sum_part1)
IO.puts(result.sum_part2)