this repo has no description
1<!-- vim: syntax=markdown -->
2<!-- livebook:{"persist_outputs":true} -->
3
4# Advent of Code 2021
5
6## Setup
7
8```elixir
9Mix.install([])
10```
11
12```output
13:ok
14```
15
16## Day 1
17
18### Load input
19
20```elixir
21stream =
22 File.stream!("day1.txt")
23 |> Stream.map(&String.to_integer(String.trim(&1)))
24```
25
26```output
27#Stream<[
28 enum: %File.Stream{
29 line_or_bytes: :line,
30 modes: [:raw, :read_ahead, :binary],
31 path: "day1.txt",
32 raw: true
33 },
34 funs: [#Function<47.58486609/1 in Stream.map/2>]
35]>
36```
37
38### Task 1
39
40<!-- livebook:{"break_markdown":true} -->
41
42Compute count of consecutive increases
43
44```elixir
45stream
46|> Stream.chunk_every(2, 1, :discard)
47|> Enum.count(fn [a, b] -> a < b end)
48```
49
50```output
511688
52```
53
54### Task 2
55
56<!-- livebook:{"break_markdown":true} -->
57
58Compute count of consecutive increases of sums of trigrams.
59
60However we can notice, that if we have list like:
61
62$$
63[a, b, c, d]
64$$
65
66Then when we want to compare consecutive trigrams then we compare:
67
68$$
69a + b + c < b + c + d \\
70a < d
71$$
72
73So we can traverse each 4 elements and then just compare first and last one
74instead of summing and then traversing it again.
75
76```elixir
77stream
78|> Stream.chunk_every(4, 1, :discard)
79|> Enum.count(fn [a, _, _, b] -> a < b end)
80```
81
82```output
831728
84```
85
86## Day 2
87
88### Load input
89
90We do parsing there, as it will help us with the latter tasks. Pattern matching
91is the simplest approach there, as input is in form of:
92
93```
94forward 10
95up 20
96down 30
97```
98
99We need to `trim/1` input to make sure that the last newline will not interrupt
100`String.to_integer/1` calls.
101
102```elixir
103stream =
104 File.stream!("day2.txt")
105 |> Stream.map(fn input ->
106 case String.trim(input) do
107 "forward " <> n -> {:forward, String.to_integer(n)}
108 "up " <> n -> {:up, String.to_integer(n)}
109 "down " <> n -> {:down, String.to_integer(n)}
110 end
111 end)
112```
113
114```output
115#Stream<[
116 enum: %File.Stream{
117 line_or_bytes: :line,
118 modes: [:raw, :read_ahead, :binary],
119 path: "day2.txt",
120 raw: true
121 },
122 funs: [#Function<47.58486609/1 in Stream.map/2>]
123]>
124```
125
126### Task 1
127
128```elixir
129{h, d} =
130 stream
131 |> Enum.reduce({0, 0}, fn
132 {:forward, n}, {h, d} -> {h + n, d}
133 {:up, n}, {h, d} -> {h, d - n}
134 {:down, n}, {h, d} -> {h, d + n}
135 end)
136
137h * d
138```
139
140```output
1411499229
142```
143
144### Task 2
145
146```elixir
147{h, d, _} =
148 stream
149 |> Enum.reduce({0, 0, 0}, fn
150 {:forward, n}, {h, d, a} -> {h + n, d + a * n, a}
151 {:up, n}, {h, d, a} -> {h, d, a - n}
152 {:down, n}, {h, d, a} -> {h, d, a + n}
153 end)
154
155h * d
156```
157
158```output
1591340836560
160```
161
162## Day 3
163
164### Input
165
166```elixir
167stream =
168 File.stream!("day3.txt")
169 |> Enum.map(&String.trim/1)
170 |> Enum.map(&String.to_charlist/1)
171
172defmodule Day3 do
173 def count(list) do
174 Enum.reduce(list, List.duplicate(0, 12), fn input, acc ->
175 for {value, counter} <- Enum.zip(input, acc) do
176 case value do
177 ?1 -> counter + 1
178 ?0 -> counter
179 end
180 end
181 end)
182 end
183end
184```
185
186```output
187{:module, Day3, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:count, 1}}
188```
189
190### Task 1
191
192```elixir
193half = div(length(stream), 2)
194
195{a, b} =
196 stream
197 |> Day3.count()
198 |> Enum.reduce({0, 0}, fn elem, {a, b} ->
199 if elem > half do
200 {a * 2 + 1, b * 2}
201 else
202 {a * 2, b * 2 + 1}
203 end
204 end)
205
206a * b
207```
208
209```output
2103847100
211```
212
213### Task 2
214
215```elixir
216defmodule Day3.Task2 do
217 def reduce(list, cb), do: reduce(list, 0, cb)
218
219 defp reduce([elem], _, _), do: elem
220
221 defp reduce(list, at, cb) do
222 counts = Day3.count(list)
223
224 half = div(length(list), 2)
225 count = Enum.at(counts, at)
226
227 bit =
228 cond do
229 count == half and cb.(count + 1, half) -> ?1
230 count != half and cb.(count, half) -> ?1
231 true -> ?0
232 end
233
234 reduce(Enum.filter(list, &(Enum.at(&1, at) == bit)), at + 1, cb)
235 end
236end
237
238co2 = List.to_integer(Day3.Task2.reduce(stream, &</2), 2)
239o2 = List.to_integer(Day3.Task2.reduce(stream, &>/2), 2)
240
241co2 * o2
242```
243
244```output
2454105235
246```