this repo has no description

ft: split solutions to separate notebooks

+69
2021/day1.livemd
···
+
<!-- vim:ft=markdown -->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 1
+
+
## Load input
+
+
```elixir
+
stream =
+
File.stream!("day1.txt")
+
|> Stream.map(&String.to_integer(String.trim(&1)))
+
```
+
+
```output
+
#Stream<[
+
enum: %File.Stream{
+
line_or_bytes: :line,
+
modes: [:raw, :read_ahead, :binary],
+
path: "day1.txt",
+
raw: true
+
},
+
funs: [#Function<47.58486609/1 in Stream.map/2>]
+
]>
+
```
+
+
## Task 1
+
+
Compute count of consecutive increases
+
+
```elixir
+
stream
+
|> Stream.chunk_every(2, 1, :discard)
+
|> Enum.count(fn [a, b] -> a < b end)
+
```
+
+
```output
+
1688
+
```
+
+
## Task 2
+
+
Compute count of consecutive increases of sums of trigrams.
+
+
However we can notice, that if we have list like:
+
+
$$
+
[a, b, c, d]
+
$$
+
+
Then when we want to compare consecutive trigrams then we compare:
+
+
$$
+
a + b + c < b + c + d \\
+
a < d
+
$$
+
+
So we can traverse each 4 elements and then just compare first and last one
+
instead of summing and then traversing it again.
+
+
```elixir
+
stream
+
|> Stream.chunk_every(4, 1, :discard)
+
|> Enum.count(fn [a, _, _, b] -> a < b end)
+
```
+
+
```output
+
1728
+
```
+88
2021/day10.livemd
···
+
<!-- vim:ft=markdown
+
-->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 10
+
+
```elixir
+
input =
+
File.stream!("day10.txt")
+
|> Stream.map(&String.trim/1)
+
+
defmodule Day10 do
+
@parens %{?( => ?), ?[ => ?], ?< => ?>, ?{ => ?}}
+
+
def parse(input), do: parse(input, [])
+
+
defp parse(<<c>> <> rest, stack) when c in '([{<', do: parse(rest, [@parens[c] | stack])
+
defp parse(<<c>> <> rest, [c | stack]), do: parse(rest, stack)
+
defp parse(<<>>, []), do: :ok
+
defp parse(<<>>, rest), do: {:incomplete, rest}
+
defp parse(<<c>> <> _, _), do: {:unexpected, [c]}
+
end
+
```
+
+
```output
+
{:module, Day10, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:parse, 2}}
+
```
+
+
## Task 1
+
+
```elixir
+
points = %{
+
?) => 3,
+
?] => 57,
+
?} => 1197,
+
?> => 25137
+
}
+
+
input
+
|> Enum.map(&Day10.parse/1)
+
|> Enum.map(fn
+
{:unexpected, [c]} -> points[c]
+
_ -> 0
+
end)
+
|> Enum.sum()
+
```
+
+
```output
+
288291
+
```
+
+
## Task 2
+
+
```elixir
+
points = %{
+
?) => 1,
+
?] => 2,
+
?} => 3,
+
?> => 4
+
}
+
+
median = fn list ->
+
sorted = Enum.sort(list)
+
middle = div(length(list), 2)
+
+
Enum.at(sorted, middle)
+
end
+
+
input
+
|> Enum.map(&Day10.parse/1)
+
|> Enum.flat_map(fn
+
{:incomplete, rest} ->
+
[
+
Enum.reduce(rest, 0, fn c, acc ->
+
acc * 5 + points[c]
+
end)
+
]
+
+
_ ->
+
[]
+
end)
+
|> median.()
+
```
+
+
```output
+
820045242
+
```
+101
2021/day11.livemd
···
+
<!-- vim:ft=markdown
+
-->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 11
+
+
```elixir
+
input =
+
File.read!("day11.txt")
+
|> String.split("\n")
+
|> Enum.map(&String.trim/1)
+
|> Enum.map(fn line ->
+
for <<c <- line>>, do: c - ?0
+
end)
+
|> Enum.with_index()
+
|> Enum.flat_map(fn {row, y} ->
+
for {v, x} <- Enum.with_index(row), do: {{x, y}, v}
+
end)
+
|> Map.new()
+
+
defmodule Day11 do
+
def step(map) do
+
updated = Map.new(map, fn {k, v} -> {k, v + 1} end)
+
+
lightup(updated, 0)
+
end
+
+
@diffs for dx <- -1..1, dy <- -1..1, dx != 0 or dy != 0, do: {dx, dy}
+
+
def lightup(map, n) do
+
map
+
|> Enum.reduce({map, 0}, fn
+
{_, v}, acc when v < 10 ->
+
acc
+
+
{{x, y} = k, _}, {map, count} ->
+
new_map =
+
@diffs
+
|> Enum.reduce(map, fn {dx, dy}, acc ->
+
point = {x + dx, y + dy}
+
+
case Map.fetch(acc, point) do
+
{:ok, value} when value != 0 -> %{acc | point => value + 1}
+
_ -> acc
+
end
+
end)
+
|> Map.put(k, 0)
+
+
{new_map, count + 1}
+
end)
+
|> case do
+
{map, 0} -> {map, n}
+
{map, m} -> lightup(map, n + m)
+
end
+
end
+
end
+
```
+
+
```output
+
{:module, Day11, <<70, 79, 82, 49, 0, 0, 11, ...>>, {:lightup, 2}}
+
```
+
+
## Task 1
+
+
```elixir
+
draw = fn map ->
+
for x <- 0..9 do
+
IO.puts(for y <- 0..9, do: ?0 + map[{x, y}])
+
end
+
+
IO.puts("")
+
end
+
+
1..100
+
|> Enum.reduce({input, 0}, fn _, {map, n} ->
+
{new_map, m} = Day11.step(map)
+
{new_map, n + m}
+
end)
+
|> elem(1)
+
```
+
+
```output
+
1688
+
```
+
+
## Task 2
+
+
```elixir
+
Stream.unfold(1, &{&1, &1 + 1})
+
|> Enum.reduce_while(input, fn idx, map ->
+
case Day11.step(map) do
+
{_, 100} -> {:halt, idx}
+
{next, _} -> {:cont, next}
+
end
+
end)
+
```
+
+
```output
+
403
+
```
+83
2021/day12.livemd
···
+
<!-- vim:ft=markdown
+
-->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 12
+
+
```elixir
+
input =
+
File.read!("day12.txt")
+
|> String.split("\n")
+
|> Enum.map(&String.split(&1, "-"))
+
+
graph =
+
Enum.reduce(input, %{}, fn [a, b], acc ->
+
acc
+
|> Map.update(a, [b], &[b | &1])
+
|> Map.update(b, [a], &[a | &1])
+
end)
+
+
defmodule Day12 do
+
def dfs(graph, start, finish), do: dfs(graph, start, finish, [start])
+
+
defp dfs(_graph, vertex, vertex, _visited), do: 1
+
+
defp dfs(graph, vertex, finish, visited) do
+
(graph[vertex] -- visited)
+
|> Enum.reduce(0, fn vertex, acc ->
+
visited = if small?(vertex), do: [vertex | visited], else: visited
+
+
acc + dfs(graph, vertex, finish, visited)
+
end)
+
end
+
+
def dfs2(graph, start, finish), do: dfs2(graph, start, finish, %{start => :inf})
+
+
defp dfs2(_graph, vertex, vertex, _visited), do: 1
+
+
defp dfs2(graph, vertex, finish, visited) do
+
(graph[vertex] -- keys(visited))
+
|> Enum.reduce(0, fn vertex, acc ->
+
visited = if small?(vertex), do: Map.update(visited, vertex, 1, &(&1 + 1)), else: visited
+
+
acc + dfs2(graph, vertex, finish, visited)
+
end)
+
end
+
+
defp keys(map) do
+
if Enum.any?(map, fn {_, v} -> v == 2 end) do
+
# there is already some vertex visited twice
+
Map.keys(map)
+
else
+
for {k, v} <- map, v > 1, do: k
+
end
+
end
+
+
defp small?(<<c>> <> _), do: c in ?a..?z
+
end
+
```
+
+
```output
+
{:module, Day12, <<70, 79, 82, 49, 0, 0, 15, ...>>, {:small?, 1}}
+
```
+
+
## Task 1
+
+
```elixir
+
Day12.dfs(graph, "start", "end")
+
```
+
+
```output
+
4167
+
```
+
+
## Task 2
+
+
```elixir
+
Day12.dfs2(graph, "start", "end")
+
```
+
+
```output
+
98441
+
```
+99
2021/day13.livemd
···
+
<!-- vim:ft=markdown
+
-->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 13
+
+
```elixir
+
[input, folds] =
+
File.read!("day13.txt")
+
|> String.trim()
+
|> String.split("\n\n")
+
+
input =
+
input
+
|> String.split("\n")
+
|> Enum.map(fn line ->
+
[x, y] = String.split(line, ",")
+
+
{String.to_integer(x), String.to_integer(y)}
+
end)
+
|> MapSet.new()
+
+
folds =
+
folds
+
|> String.split("\n")
+
|> Enum.map(fn
+
"fold along " <> <<c>> <> "=" <> rest ->
+
{String.to_atom(<<c>>), String.to_integer(rest)}
+
end)
+
+
defmodule Day13 do
+
def fold({orientation, pos}, set) do
+
Enum.reduce(set, MapSet.new(), fn point, acc ->
+
new_point = folded_coords(orientation, pos, point)
+
+
MapSet.put(acc, new_point)
+
end)
+
end
+
+
defp folded_coords(:x, col, {x, y}) when x > col, do: {abs(2 * col - x), y}
+
defp folded_coords(:y, row, {x, y}) when y > row, do: {x, abs(2 * row - y)}
+
defp folded_coords(_, _, point), do: point
+
+
def draw(set) do
+
set
+
|> Enum.group_by(&elem(&1, 1))
+
|> Enum.sort()
+
|> Enum.map(fn {_, points} ->
+
points
+
|> Enum.map(&elem(&1, 0))
+
|> Enum.sort()
+
|> Enum.chunk_every(2, 1)
+
|> Enum.map(fn
+
[a, b] -> b - a
+
_ -> 0
+
end)
+
|> Enum.map(&String.pad_trailing("█", &1, " "))
+
end)
+
|> Enum.join("\n")
+
end
+
end
+
```
+
+
```output
+
{:module, Day13, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:draw, 1}}
+
```
+
+
## Task 1
+
+
```elixir
+
Day13.fold(hd(folds), input) |> MapSet.size()
+
```
+
+
```output
+
802
+
```
+
+
## Task 2
+
+
```elixir
+
Enum.reduce(folds, input, &Day13.fold/2)
+
|> Day13.draw()
+
|> IO.puts()
+
```
+
+
```output
+
███ █ █ █ █ ████ ████ ██ █ █ ███
+
█ █ █ █ █ █ █ █ █ █ █ █ █ █
+
█ █ ██ ████ ███ █ █ █ █ ███
+
███ █ █ █ █ █ █ █ ██ █ █ █ █
+
█ █ █ █ █ █ █ █ █ █ █ █ █ █
+
█ █ █ █ █ █ █ ████ ███ ██ ███
+
```
+
+
```output
+
:ok
+
```
+
+102
2021/day14.livemd
···
+
<!-- vim:ft=markdown
+
-->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 14
+
+
```elixir
+
[polymer_raw, subs] =
+
File.read!("day14.txt")
+
|> String.split("\n\n")
+
+
<<first, _::binary>> = polymer_raw
+
+
polymer =
+
{first,
+
polymer_raw
+
|> String.to_charlist()
+
|> Enum.chunk_every(2, 1, :discard)
+
|> Enum.frequencies()}
+
+
subs =
+
subs
+
|> String.trim()
+
|> String.split(["\n", " -> "])
+
|> Enum.chunk_every(2)
+
|> Map.new(fn [pair, <<new>>] -> {String.to_charlist(pair), new} end)
+
+
defmodule Day14 do
+
def expand({hd, polymer}, subs) do
+
new =
+
polymer
+
|> Enum.reduce(%{}, fn {[a, b] = pair, count}, acc ->
+
s = Map.fetch!(subs, pair)
+
+
acc
+
|> Map.update([a, s], count, &(&1 + count))
+
|> Map.update([s, b], count, &(&1 + count))
+
end)
+
+
{hd, new}
+
end
+
+
def expand_naive(polymer, subs) do
+
polymer
+
|> to_charlist()
+
|> Enum.chunk_every(2, 1, :discard)
+
|> Enum.flat_map(fn [a, b] = pair ->
+
[a, subs[pair], b]
+
end)
+
|> List.to_string()
+
end
+
+
def frequencies({hd, polymer}) do
+
polymer
+
|> Enum.reduce(%{hd => 1}, fn {[_, b], count}, acc ->
+
Map.update(acc, b, count, &(&1 + count))
+
end)
+
end
+
end
+
```
+
+
```output
+
{:module, Day14, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:frequencies, 1}}
+
```
+
+
## Task 1
+
+
```elixir
+
{{_, min}, {_, max}} =
+
1..10
+
|> Enum.reduce(polymer, fn _, acc ->
+
Day14.expand(acc, subs)
+
end)
+
|> Day14.frequencies()
+
|> Enum.min_max_by(&elem(&1, 1))
+
+
# 2768
+
max - min
+
```
+
+
```output
+
2768
+
```
+
+
## Task 2
+
+
```elixir
+
{{_, min}, {_, max}} =
+
1..40
+
|> Enum.reduce(polymer, fn _, acc ->
+
Day14.expand(acc, subs)
+
end)
+
|> Day14.frequencies()
+
|> Enum.min_max_by(&elem(&1, 1))
+
+
max - min
+
```
+
+
```output
+
2914365137499
+
```
+117
2021/day15.livemd
···
+
<!-- vim:ft=markdown
+
-->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 15
+
+
```elixir
+
input =
+
File.read!("day15.txt")
+
|> String.trim()
+
|> String.split("\n")
+
|> Enum.map(&String.to_charlist/1)
+
|> Enum.with_index()
+
|> Enum.flat_map(fn {row, y} ->
+
row
+
|> Enum.with_index()
+
|> Enum.map(fn {v, x} -> {{x, y}, v - ?0} end)
+
end)
+
|> Map.new()
+
+
{width, height} = Enum.max(Map.keys(input))
+
```
+
+
```output
+
{99, 99}
+
```
+
+
## Task 1
+
+
```elixir
+
shortest_paths =
+
for y <- height..0//-1,
+
x <- width..0//-1,
+
reduce: %{} do
+
acc ->
+
right = acc[{x + 1, y}]
+
bottom = acc[{x, y + 1}]
+
+
value =
+
case {right, bottom} do
+
{nil, nil} -> input[{x, y}]
+
_ -> input[{x, y}] + min(right, bottom)
+
end
+
+
Map.put(acc, {x, y}, value)
+
end
+
+
shortest_paths[{0, 0}] - input[{0, 0}]
+
```
+
+
```output
+
429
+
```
+
+
## Task 2
+
+
```elixir
+
defmodule Day15.Task2 do
+
def expand_grid(board) do
+
{width, height} = Enum.max(Map.keys(board))
+
+
board
+
|> Enum.flat_map(fn {{x, y}, v} ->
+
for rx <- 0..4, ry <- 0..4 do
+
{{x + (width + 1) * rx, y + (height + 1) * ry}, rem(v - 1 + rx + ry, 9) + 1}
+
end
+
end)
+
|> Map.new()
+
end
+
+
def find_path(board, start, finish) do
+
dists = :gb_sets.singleton({0, start})
+
+
find_path(board, finish, dists, MapSet.new())
+
end
+
+
@surround for dx <- -1..1, dy <- -1..1, abs(dx) != abs(dy), do: {dx, dy}
+
+
def find_path(board, finish, dists, visited) do
+
{{dist, {x, y} = curr}, dists} = :gb_sets.take_smallest(dists)
+
+
if curr == finish do
+
dist
+
else
+
visited = MapSet.put(visited, curr)
+
+
dists =
+
for {dx, dy} <- @surround,
+
next = {x + dx, y + dy},
+
next not in visited,
+
is_map_key(board, next),
+
alt = dist + board[next],
+
reduce: dists do
+
acc ->
+
:gb_sets.add_element({alt, next}, acc)
+
end
+
+
find_path(board, finish, dists, visited)
+
end
+
end
+
end
+
```
+
+
```output
+
{:module, Day15.Task2, <<70, 79, 82, 49, 0, 0, 16, ...>>, {:find_path, 4}}
+
```
+
+
```elixir
+
input
+
|> Day15.Task2.expand_grid()
+
|> Day15.Task2.find_path({0, 0}, {499, 499})
+
```
+
+
```output
+
2844
+
```
+610
2021/day16.livemd
···
+
<!-- vim:ft=markdown -->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 16
+
+
## Section
+
+
```elixir
+
defmodule Day16 do
+
defmodule Packet do
+
defstruct [:version, :type, :value]
+
end
+
+
def decode(<<version::3, 4::3, rest::bitstring>>) do
+
{value, rest} = literal(rest, 0)
+
+
{%Packet{type: 4, version: version, value: value}, rest}
+
end
+
+
def decode(<<version::3, type::3, 0::1, length::15, rest::bitstring>>) do
+
<<subpackets::bitstring-size(length), rest::bitstring>> = rest
+
+
{%Packet{type: type, version: version, value: decode_all(subpackets)}, rest}
+
end
+
+
def decode(<<version::3, type::3, 1::1, length::11, rest::bitstring>>) do
+
{value, rest} = Enum.map_reduce(1..length, rest, fn _, acc -> decode(acc) end)
+
+
{%Packet{type: type, version: version, value: value}, rest}
+
end
+
+
def decode_all(input) do
+
case decode(input) do
+
{packet, <<>>} -> [packet]
+
{packet, rest} -> [packet | decode_all(rest)]
+
end
+
end
+
+
defp literal(<<1::1, bits::4, rest::bitstring>>, acc) do
+
literal(rest, acc * 0x10 + bits)
+
end
+
+
defp literal(<<0::1, bits::4, rest::bitstring>>, acc) do
+
{acc * 0x10 + bits, rest}
+
end
+
end
+
+
input =
+
File.read!("day16.txt")
+
|> String.trim()
+
|> Base.decode16!()
+
|> Day16.decode()
+
|> elem(0)
+
```
+
+
```output
+
%Day16.Packet{
+
type: 0,
+
value: [
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{type: 4, value: 20, version: 6},
+
%Day16.Packet{
+
type: 6,
+
value: [
+
%Day16.Packet{type: 4, value: 14747, version: 1},
+
%Day16.Packet{type: 4, value: 14747, version: 6}
+
],
+
version: 2
+
}
+
],
+
version: 1
+
},
+
%Day16.Packet{
+
type: 3,
+
value: [
+
%Day16.Packet{type: 4, value: 15, version: 5},
+
%Day16.Packet{type: 4, value: 10, version: 6}
+
],
+
version: 7
+
},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{
+
type: 7,
+
value: [
+
%Day16.Packet{type: 4, value: 2184, version: 1},
+
%Day16.Packet{type: 4, value: 130250, version: 6}
+
],
+
version: 6
+
},
+
%Day16.Packet{type: 4, value: 5442981, version: 4}
+
],
+
version: 6
+
},
+
%Day16.Packet{type: 4, value: 8281083, version: 0},
+
%Day16.Packet{
+
type: 2,
+
value: [
+
%Day16.Packet{type: 4, value: 102, version: 5},
+
%Day16.Packet{type: 4, value: 647125, version: 7}
+
],
+
version: 1
+
},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{type: 4, value: 178, version: 1},
+
%Day16.Packet{type: 4, value: 176, version: 6}
+
],
+
version: 0
+
},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{
+
type: 6,
+
value: [
+
%Day16.Packet{
+
type: 0,
+
value: [
+
%Day16.Packet{type: 4, value: 13, version: 1},
+
%Day16.Packet{type: 4, value: 8, version: 4},
+
%Day16.Packet{type: 4, value: 4, version: 3}
+
],
+
version: 2
+
},
+
%Day16.Packet{
+
type: 0,
+
value: [
+
%Day16.Packet{type: 4, value: 7, version: 7},
+
%Day16.Packet{type: 4, value: 11, version: 3},
+
%Day16.Packet{type: 4, value: 14, version: 2}
+
],
+
version: 4
+
}
+
],
+
version: 7
+
},
+
%Day16.Packet{type: 4, value: 2724, version: 0}
+
],
+
version: 1
+
},
+
%Day16.Packet{type: 4, value: 9, version: 4},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{
+
type: 5,
+
value: [
+
%Day16.Packet{type: 4, value: 7240238, version: 2},
+
%Day16.Packet{type: 4, value: 233, version: 7}
+
],
+
version: 1
+
},
+
%Day16.Packet{type: 4, value: 37, version: 6}
+
],
+
version: 4
+
},
+
%Day16.Packet{type: 2, value: [%Day16.Packet{type: 4, value: 2, version: 5}], version: 5},
+
%Day16.Packet{type: 4, value: 53749, version: 4},
+
%Day16.Packet{type: 4, value: 11, version: 3},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{type: 4, value: 382979, version: 4},
+
%Day16.Packet{
+
type: 5,
+
value: [
+
%Day16.Packet{
+
type: 0,
+
value: [
+
%Day16.Packet{type: 4, value: 15, version: 1},
+
%Day16.Packet{type: 4, value: 10, version: 0},
+
%Day16.Packet{type: 4, value: 2, version: 6}
+
],
+
version: 5
+
},
+
%Day16.Packet{
+
type: 0,
+
value: [
+
%Day16.Packet{type: 4, value: 4, version: 7},
+
%Day16.Packet{type: 4, value: 7, version: 4},
+
%Day16.Packet{type: 4, value: 2, version: 5}
+
],
+
version: 1
+
}
+
],
+
version: 6
+
}
+
],
+
version: 2
+
},
+
%Day16.Packet{type: 4, value: 21251, version: 1},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{type: 4, value: 163, version: 6},
+
%Day16.Packet{
+
type: 5,
+
value: [
+
%Day16.Packet{type: 4, value: 59, version: 3},
+
%Day16.Packet{type: 4, value: 836848134220, version: 1}
+
],
+
version: 6
+
}
+
],
+
version: 2
+
},
+
%Day16.Packet{
+
type: 2,
+
value: [
+
%Day16.Packet{
+
type: 0,
+
value: [
+
%Day16.Packet{
+
type: 0,
+
value: [
+
%Day16.Packet{
+
type: 2,
+
value: [
+
%Day16.Packet{
+
type: 2,
+
value: [
+
%Day16.Packet{
+
type: 0,
+
value: [
+
%Day16.Packet{
+
type: 3,
+
value: [
+
%Day16.Packet{
+
type: 2,
+
value: [
+
%Day16.Packet{
+
type: 2,
+
value: [
+
%Day16.Packet{
+
type: 3,
+
value: [%Day16.Packet{type: 0, value: [...], ...}],
+
version: 0
+
}
+
],
+
version: 1
+
}
+
],
+
version: 1
+
}
+
],
+
version: 7
+
}
+
],
+
version: 0
+
}
+
],
+
version: 6
+
}
+
],
+
version: 2
+
}
+
],
+
version: 2
+
}
+
],
+
version: 6
+
}
+
],
+
version: 7
+
},
+
%Day16.Packet{type: 1, value: [%Day16.Packet{type: 4, value: 44, version: 4}], version: 7},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{type: 4, value: 255, version: 2},
+
%Day16.Packet{type: 4, value: 91, version: 5},
+
%Day16.Packet{type: 4, value: 176, version: 5},
+
%Day16.Packet{type: 4, value: 23, version: 1}
+
],
+
version: 7
+
},
+
%Day16.Packet{
+
type: 3,
+
value: [
+
%Day16.Packet{type: 4, value: 11520, version: 4},
+
%Day16.Packet{type: 4, value: 6069, version: 0},
+
%Day16.Packet{type: 4, value: 1089149511401, version: 4},
+
%Day16.Packet{type: 4, value: 158, version: 2},
+
%Day16.Packet{type: 4, value: 620605, version: 0}
+
],
+
version: 2
+
},
+
%Day16.Packet{
+
type: 0,
+
value: [
+
%Day16.Packet{type: 4, value: 62788, version: 7},
+
%Day16.Packet{type: 4, value: 9410622, version: 2},
+
%Day16.Packet{type: 4, value: 15912821, version: 4}
+
],
+
version: 4
+
},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{type: 4, value: 22416, version: 5},
+
%Day16.Packet{
+
type: 5,
+
value: [
+
%Day16.Packet{type: 4, value: 246, version: 1},
+
%Day16.Packet{type: 4, value: 246, version: 4}
+
],
+
version: 2
+
}
+
],
+
version: 0
+
},
+
%Day16.Packet{type: 3, value: [%Day16.Packet{type: 4, value: 13008601, version: 5}], version: 0},
+
%Day16.Packet{
+
type: 0,
+
value: [
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{type: 4, value: 3, version: 4},
+
%Day16.Packet{type: 4, value: 14, version: 1},
+
%Day16.Packet{type: 4, value: 5, version: 0}
+
],
+
version: 5
+
},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{type: 4, value: 2, version: 1},
+
%Day16.Packet{type: 4, value: 14, version: 1},
+
%Day16.Packet{type: 4, value: 10, version: 1}
+
],
+
version: 6
+
},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{type: 4, value: 8, version: 3},
+
%Day16.Packet{type: 4, value: 6, version: 6},
+
%Day16.Packet{type: 4, value: 11, version: 0}
+
],
+
version: 1
+
}
+
],
+
version: 5
+
},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{type: 4, value: 32940592237, version: 2},
+
%Day16.Packet{
+
type: 5,
+
value: [
+
%Day16.Packet{type: 4, value: 100, version: 1},
+
%Day16.Packet{type: 4, value: 1393232728, version: 2}
+
],
+
version: 2
+
}
+
],
+
version: 0
+
},
+
%Day16.Packet{type: 4, value: 89, version: 3},
+
%Day16.Packet{
+
type: 2,
+
value: [
+
%Day16.Packet{type: 4, value: 204, version: 6},
+
%Day16.Packet{type: 4, value: 260321821, version: 2},
+
%Day16.Packet{type: 4, value: 225241983, version: 6}
+
],
+
version: 0
+
},
+
%Day16.Packet{
+
type: 0,
+
value: [
+
%Day16.Packet{type: 4, value: 960899, version: 3},
+
%Day16.Packet{type: 4, value: 58997, version: 5},
+
%Day16.Packet{type: 4, value: 54940, version: 6},
+
%Day16.Packet{type: 4, value: 10974, version: 2},
+
%Day16.Packet{type: 4, value: 882043, version: 2}
+
],
+
version: 0
+
},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{
+
type: 6,
+
value: [
+
%Day16.Packet{type: 4, value: 35633017255, version: 4},
+
%Day16.Packet{type: 4, value: 35633017255, version: 2}
+
],
+
version: 3
+
},
+
%Day16.Packet{type: 4, value: 1359, version: 6}
+
],
+
version: 6
+
},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{type: 4, value: 92, version: 4},
+
%Day16.Packet{type: 4, value: 38, version: 3},
+
%Day16.Packet{type: 4, value: 160, version: 5},
+
%Day16.Packet{type: 4, value: 111, version: 1},
+
%Day16.Packet{type: 4, value: 64, version: 4}
+
],
+
version: 4
+
},
+
%Day16.Packet{
+
type: 0,
+
value: [
+
%Day16.Packet{type: 4, value: 2541, version: 3},
+
%Day16.Packet{type: 4, value: 263947, version: 6},
+
%Day16.Packet{type: 4, value: 7686705, version: 5},
+
%Day16.Packet{type: 4, value: 31, version: 4}
+
],
+
version: 2
+
},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{
+
type: 6,
+
value: [
+
%Day16.Packet{type: 4, value: 3193865, version: 1},
+
%Day16.Packet{type: 4, value: 20223, version: 7}
+
],
+
version: 2
+
},
+
%Day16.Packet{type: 4, value: 9328522, version: 5}
+
],
+
version: 0
+
},
+
%Day16.Packet{
+
type: 2,
+
value: [
+
%Day16.Packet{type: 4, value: 5, version: 4},
+
%Day16.Packet{type: 4, value: 7, version: 3},
+
%Day16.Packet{type: 4, value: 179420284, version: 4},
+
%Day16.Packet{type: 4, value: 19890, version: 1},
+
%Day16.Packet{type: 4, value: 2655, version: 0}
+
],
+
version: 7
+
},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{type: 4, value: 862089, version: 1},
+
%Day16.Packet{
+
type: 6,
+
value: [
+
%Day16.Packet{type: 4, value: 248, version: 3},
+
%Day16.Packet{type: 4, value: 3286, version: 5}
+
],
+
version: 3
+
}
+
],
+
version: 3
+
},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{type: 4, value: 93, version: 6},
+
%Day16.Packet{
+
type: 5,
+
value: [
+
%Day16.Packet{type: 4, value: 4269, version: 6},
+
%Day16.Packet{type: 4, value: 240, version: 3}
+
],
+
version: 4
+
}
+
],
+
version: 5
+
},
+
%Day16.Packet{
+
type: 3,
+
value: [
+
%Day16.Packet{type: 4, value: 2938, version: 6},
+
%Day16.Packet{type: 4, value: 3, version: 6},
+
%Day16.Packet{type: 4, value: 211, version: 7}
+
],
+
version: 3
+
},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{
+
type: 7,
+
value: [
+
%Day16.Packet{type: 4, value: 159, version: 0},
+
%Day16.Packet{type: 4, value: 159, version: 5}
+
],
+
version: 0
+
},
+
%Day16.Packet{type: 4, value: 28, version: 1}
+
],
+
version: 4
+
},
+
%Day16.Packet{type: 4, value: 84, version: 4},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{type: 4, value: 235, version: 4},
+
%Day16.Packet{
+
type: 6,
+
value: [
+
%Day16.Packet{type: 0, value: [%Day16.Packet{...}, ...], version: 4},
+
%Day16.Packet{type: 0, value: [...], ...}
+
],
+
version: 3
+
}
+
],
+
version: 6
+
},
+
%Day16.Packet{type: 4, value: 1425, version: 4},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{
+
type: 7,
+
value: [%Day16.Packet{type: 0, value: [...], ...}, %Day16.Packet{type: 0, ...}],
+
version: 5
+
},
+
%Day16.Packet{type: 4, value: 13, version: 2}
+
],
+
version: 2
+
},
+
%Day16.Packet{type: 0, value: [%Day16.Packet{type: 4, value: 3121, version: 6}], version: 5},
+
%Day16.Packet{
+
type: 1,
+
value: [
+
%Day16.Packet{type: 4, value: 51, version: 2},
+
%Day16.Packet{type: 4, value: 61, ...},
+
%Day16.Packet{type: 4, ...}
+
],
+
version: 4
+
},
+
%Day16.Packet{
+
type: 1,
+
value: [%Day16.Packet{type: 4, value: 1393, ...}, %Day16.Packet{type: 5, ...}],
+
version: 3
+
},
+
%Day16.Packet{type: 1, value: [%Day16.Packet{type: 7, ...}, %Day16.Packet{...}], version: 3},
+
%Day16.Packet{type: 1, value: [%Day16.Packet{...}, ...], version: 7},
+
%Day16.Packet{type: 3, value: [...], ...},
+
%Day16.Packet{type: 2, ...},
+
%Day16.Packet{...},
+
...
+
],
+
version: 3
+
}
+
```
+
+
## Task 1
+
+
```elixir
+
defmodule Day16.Task1 do
+
alias Day16.Packet
+
+
def sum(%Packet{type: 4, version: version}), do: version
+
+
def sum(%Packet{version: version, value: value}) do
+
Enum.reduce(value, version, &(sum(&1) + &2))
+
end
+
end
+
+
Day16.Task1.sum(input)
+
```
+
+
```output
+
949
+
```
+
+
## Task 2
+
+
```elixir
+
defmodule Day16.Task2 do
+
alias Day16.Packet
+
+
def evaluate(%Packet{type: 0} = packet), do: reduce(packet, 0, &+/2)
+
def evaluate(%Packet{type: 1} = packet), do: reduce(packet, 1, &*/2)
+
def evaluate(%Packet{type: 2} = packet), do: reduce(packet, :inf, &min/2)
+
def evaluate(%Packet{type: 3} = packet), do: reduce(packet, 0, &max/2)
+
+
def evaluate(%Packet{type: 4, value: value}), do: value
+
+
def evaluate(%Packet{type: 5} = packet), do: compare(packet, &>/2)
+
def evaluate(%Packet{type: 6} = packet), do: compare(packet, &</2)
+
def evaluate(%Packet{type: 7} = packet), do: compare(packet, &==/2)
+
+
defp reduce(%Packet{value: value}, initial, op) do
+
Enum.reduce(value, initial, &op.(evaluate(&1), &2))
+
end
+
+
defp compare(%Packet{value: [a, b]}, op) do
+
if op.(evaluate(a), evaluate(b)), do: 1, else: 0
+
end
+
end
+
+
Day16.Task2.evaluate(input)
+
```
+
+
```output
+
1114600142730
+
```
+185
2021/day17.livemd
···
+
<!-- vim:ft=markdown -->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 17
+
+
## Setup
+
+
```elixir
+
input = File.read!("day17.txt")
+
# input = "target area: x=117..7310, y=-9546..-89"
+
+
IO.puts(input)
+
+
%{"a_x" => a_x, "a_y" => a_y, "b_x" => b_x, "b_y" => b_y} =
+
Regex.named_captures(
+
~r/target area: x=(?<a_x>-?\d+)\.\.(?<b_x>-?\d+), y=(?<a_y>-?\d+)\.\.(?<b_y>-?\d+)/,
+
input
+
)
+
+
a = %{x: String.to_integer(a_x), y: String.to_integer(a_y)}
+
b = %{x: String.to_integer(b_x), y: String.to_integer(b_y)}
+
+
[a: a, b: b]
+
```
+
+
```output
+
target area: x=288..330, y=-96..-50
+
```
+
+
```output
+
[a: %{x: 288, y: -96}, b: %{x: 330, y: -50}]
+
```
+
+
## Task 1
+
+
### Lemma 1
+
+
The horizontal velocity there can be ignored, as we can always find a horizontal velocity
+
that will reach the target area and will reduce the velocity to $$0$$, which mean that all
+
further movement will happen only in one dimension. That velocity is:
+
+
$$
+
v_x = \lceil \frac{-1 + \sqrt{1 + 8b_x}}{2} \rceil
+
$$
+
+
#### Proof:
+
+
Which came from the fact that distance traveled by the projectile is sum of the arithmetic
+
sequence with $$r = -1$$, so the distance traveled is:
+
+
$$
+
s_x = \frac{2v_{x0} - t + 1}{2}t
+
$$
+
+
Where $$t$$ is travel time. As $$v_x(t) = v_{x0}$$ then $$v_x(t) = 0 \implies t = v_{x0}$$,
+
so after substituting $$t$$ we get:
+
+
$$
+
s_x = \frac{2v_{x0} - v_{x0} + 1}{2}v_{x0} \\
+
s_x = \frac{v_{x0} + 1}{2}v_{x0} \\
+
s_x = \frac{v_{x0}^2 + v_{x0}}{2}
+
$$
+
+
As we want to find the nearest column where we want to stop movement in $$OX$$ then
+
we are looking at $$s_x = b_x$$:
+
+
$$
+
b_x = \frac{v_{x0}^2 + v_{x0}}{2} \\
+
2b_x = v_{x0}^2 + v_{x0} \\
+
0 = v_{x0}^2 + v_{x0} - 2b_x
+
$$
+
+
The soultions for these equation are in form of:
+
+
$$
+
v_{x0} = \frac{-1 \mp \sqrt{1 + 8b_x}}{2}
+
$$
+
+
As we assume that $$b_x \gt 0$$, then the solutions will always be trivial. Additionally
+
we do not care about negative roots, so we can take only:
+
+
$$
+
v_{x0} = \frac{-1 + \sqrt{1 + 8b_x}}{2}
+
$$
+
+
As this can be fractional and we want $$v_x0 \in \mathbb{Z}$$ and assume that target is
+
big enough to have at least one point that we can land on, then we can simply round velocity
+
up:
+
+
$$
+
v_x = \lceil \frac{-1 + \sqrt{1 + 8b_x}}{2} \rceil\\
+
$$
+
+
$$\blacksquare$$
+
+
### Lemma 2
+
+
TODO
+
+
As
+
+
$$
+
v_{y0} = \frac{2a_y - t + t^2}{2t}
+
$$
+
+
Left to prove that $$v_0$$ will have highest possible value for $$t = -2a_y$$.
+
Then above equation reduces like that:
+
+
$$
+
v_{y0} = \frac{2a_y + 2a_y + 4a_y^2}{4a_y} \\
+
v_{y0} = \frac{4a_y + 4a_y^2}{4a_y} \\
+
v_{y0} = 1 + a_y
+
$$
+
+
```elixir
+
v_y = -min(a.y, b.y) - 1
+
+
{v_y, v_y * (v_y + 1) / 2}
+
```
+
+
```output
+
{95, 4560.0}
+
```
+
+
## Task 2
+
+
```elixir
+
solveq_pos = fn a, b, c ->
+
[
+
(-b - :math.sqrt(b * b - 4 * a * c)) / (2 * a),
+
(-b + :math.sqrt(b * b - 4 * a * c)) / (2 * a)
+
]
+
|> Enum.filter(&(&1 > 0))
+
end
+
+
v_xmin_rest = ceil(hd(solveq_pos.(1, 1, -2 * min(a.x, b.x))))
+
v_xmax_rest = floor(hd(solveq_pos.(1, 1, -2 * max(a.x, b.x))))
+
+
v_ymax = -min(a.y, b.y) - 1
+
v_ymin = min(a.y, b.y)
+
+
{xmin, xmax} = Enum.min_max([a.x, b.x])
+
{ymin, ymax} = Enum.min_max([a.y, b.y])
+
+
offset = fn
+
0 -> {1, -1}
+
v_y when v_y > 0 -> {2 * v_y + 1, -v_y - 1}
+
v_y -> {0, v_y}
+
end
+
+
v_y_pairs =
+
for v_y <- v_ymin..v_ymax,
+
{offset, fv_y} = offset.(v_y),
+
tmin <- solveq_pos.(-1, 2 * fv_y + 1, -2 * ymax),
+
tmax <- solveq_pos.(-1, 2 * fv_y + 1, -2 * ymin),
+
ceil(tmin) <= floor(tmax),
+
t <- ceil(tmin)..floor(tmax),
+
do: {v_y, t + offset}
+
+
v_x_pairs =
+
for t <- Enum.uniq(Enum.map(v_y_pairs, &elem(&1, 1))),
+
v_xmin_move = ceil((2 * xmin / t + t - 1) / 2),
+
v_xmax_move = floor((2 * xmax / t + t - 1) / 2),
+
xrange = Enum.filter(v_xmin_move..v_xmax_move, &(&1 >= t)),
+
xrange =
+
if(v_xmin_rest < t,
+
do: Enum.concat(xrange, v_xmin_rest..min(t, v_xmax_rest)),
+
else: xrange
+
),
+
v_x <- MapSet.new(xrange),
+
do: {t, v_x}
+
+
pairs =
+
for {v_y, t} <- v_y_pairs,
+
{^t, v_x} <- v_x_pairs,
+
into: MapSet.new(),
+
do: {v_x, v_y}
+
+
MapSet.size(pairs)
+
```
+
+
```output
+
3344
+
```
+1
2021/day17.txt
···
+
target area: x=288..330, y=-96..-50
+172
2021/day18.livemd
···
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 18
+
+
## Input
+
+
```elixir
+
input =
+
File.stream!("day18.txt")
+
|> Enum.map(&elem(Code.eval_string(&1), 0))
+
```
+
+
```output
+
[
+
[[[6, [8, 3]], [2, 0]], [[[9, 5], [9, 1]], 3]],
+
[[[9, [2, 2]], [5, 4]], [[[2, 2], [9, 6]], '\a\a']],
+
[[[0, [3, 2]], 1], [[0, [2, 8]], [2, [0, 4]]]],
+
[[4, 4], [[[7, 0], 5], [3, 1]]],
+
[[5, 4], 1],
+
[[[[7, 6], 4], 9], [[9, 1], 9]],
+
[[[1, '\a\b'], ['\a\a', [1, 6]]], [1, [6, [7, 1]]]],
+
[[[[6, 8], [5, 6]], [[1, 1], 8]], [[[2, 0], [3, 1]], [2, [2, 6]]]],
+
[[[6, 3], [3, [7, 1]]], 8],
+
[[[9, 4], [3, [0, 6]]], [[2, [3, 6]], ['\t\b', [1, 6]]]],
+
[9, [0, [[0, 7], 2]]],
+
[[[[8, 4], 7], [[9, 2], [0, 9]]], ['\a\t', [8, [0, 9]]]],
+
[[1, 1], [[5, [3, 8]], [3, [4, 7]]]],
+
[[[9, [2, 9]], [2, [2, 9]]], [[[3, 5], 5], [[3, 3], 2]]],
+
[[[[5, 4], 9], 0], [[[5, 7], 2], [[5, 2], 9]]],
+
[[2, [[1, 0], [6, 2]]], 0],
+
[[[3, 7], [7, 6]], [[[2, 8], 5], [3, '\t\a']]],
+
[[2, [2, '\b\b']], [['\t\t', [1, 1]], [[8, 6], [0, 3]]]],
+
[[8, 1], [3, 5]],
+
[[7, [[7, 6], [2, 0]]], 4],
+
[[5, 4], [[1, 3], [5, [2, 8]]]],
+
'\a\t',
+
[[[[6, 9], 0], [1, [5, 0]]], [[[6, 4], 3], 7]],
+
[[[[3, 7], 3], [2, 6]], [[0, 4], '\t\t']],
+
[[[[1, 5], [5, 0]], [9, 4]], [[[8, 3], 3], [8, [3, 6]]]],
+
[[[[3, 7], 5], [[8, 5], [1, 5]]], [[0, 6], [3, 4]]],
+
[[[[4, 0], 2], [7, [8, 4]]], [0, [5, '\a\b']]],
+
[[[[0, 8], [0, 4]], [9, 3]], [[[5, 4], [4, 8]], [[1, 6], [5, 4]]]],
+
[[0, [0, 3]], [[3, [1, 5]], [[9, 6], [0, 6]]]],
+
[[9, [8, 4]], [7, 1]],
+
[[[[1, 9], '\a\a'], 9], [[6, [4, 5]], [8, [3, 2]]]],
+
[5, [[2, [9, 5]], [3, [4, 0]]]],
+
[[[6, 2], [[1, 8], 5]], 6],
+
[[8, [6, [6, 4]]], [0, ['\t\b', 7]]],
+
[[[[6, 3], [8, 0]], [8, [2, 7]]], 8],
+
[[[6, [3, 6]], [[4, 0], [4, 7]]], [0, [[4, 0], [4, 5]]]],
+
[[[3, [8, 1]], 1], [2, 3]],
+
[[[6, [7, 0]], [[3, 5], [3, 4]]], 7],
+
[[[[8, 0], 3], 8], [[[1, 6], 3], [[0, 5], 2]]],
+
[[[3, 7], ['\t\b', 8]], [[[8, 4], 7], [3, [1, 7]]]],
+
[[[0, 5], [[5, 5], '\a\b']], [9, [5, [2, 2]]]],
+
[[2, 9], [[[7, 4], 4], [[8, 0], [6, 9]]]],
+
[[['\a\b', '\b\b'], 0], 9],
+
[[[4, [0, 6]], [[5, 9], [0, ...]]], [3, [6, 7]]],
+
[[[7, [6, ...]], [5, [...]]], [[[3, ...], 6], [[...], ...]]],
+
[3, [[[...], ...], [...]]],
+
[[[3, ...], [...]], [[...], ...]],
+
[['\t\a', ...], [...]],
+
[[...], ...],
+
[...],
+
...
+
]
+
```
+
+
```elixir
+
defmodule Day18 do
+
def add(a, b) do
+
sum = reduce([a, b])
+
+
# IO.puts("""
+
# #{inspect(a, charlists: :as_list)}
+
# + #{inspect(b, charlists: :as_list)}
+
# = #{inspect(sum, charlists: :as_list)}
+
# """)
+
+
sum
+
end
+
+
defp reduce(list) do
+
# First try to explode
+
# If that returned list in the same form, then try to split it
+
# If all above returned input list, then we have reached fixed point
+
with ^list <- explode(list),
+
^list <- split(list) do
+
list
+
else
+
new_list -> reduce(new_list)
+
end
+
end
+
+
defp explode(list) do
+
{_, _, exploded} = explode(list, 0)
+
+
exploded
+
end
+
+
defp explode(num, _) when is_number(num), do: {0, 0, num}
+
+
defp explode([a, b], 4), do: {a, b, 0}
+
+
defp explode([a, b], n) do
+
{la, ra, na} = explode(a, n + 1)
+
{lb, rb, nb} = explode(explode_add(ra, b), n + 1)
+
+
{la, rb, [explode_add(na, lb), nb]}
+
end
+
+
defp explode_add([a, b], v), do: [a, explode_add(b, v)]
+
defp explode_add(v, [a, b]), do: [explode_add(v, a), b]
+
defp explode_add(a, b), do: a + b
+
+
defp split(n) when n in 0..9, do: n
+
defp split(n) when is_integer(n), do: [div(n, 2), div(n + 1, 2)]
+
+
defp split([a, b]) do
+
with {:a, ^a} <- {:a, split(a)},
+
{:b, ^b} <- {:b, split(b)} do
+
[a, b]
+
else
+
{:a, mod} -> [mod, b]
+
{:b, mod} -> [a, mod]
+
end
+
end
+
+
def magnitude(n) when is_number(n), do: n
+
def magnitude([a, b]), do: 3 * magnitude(a) + 2 * magnitude(b)
+
end
+
```
+
+
```output
+
{:module, Day18, <<70, 79, 82, 49, 0, 0, 12, ...>>, {:magnitude, 1}}
+
```
+
+
## Task 1
+
+
```elixir
+
flip = fn f -> &f.(&2, &1) end
+
+
input
+
|> Enum.reduce(flip.(&Day18.add/2))
+
|> IO.inspect(charlists: :as_list)
+
|> Day18.magnitude()
+
```
+
+
```output
+
[[[[7, 7], [7, 8]], [[8, 7], [0, 7]]], [[[6, 6], [6, 7]], 6]]
+
```
+
+
```output
+
3411
+
```
+
+
## Task 2
+
+
```elixir
+
for a <- input,
+
b <- input,
+
a != b,
+
m1 = Day18.magnitude(Day18.add(a, b)),
+
m2 = Day18.magnitude(Day18.add(b, a)),
+
reduce: 0 do
+
acc -> max(acc, max(m1, m2))
+
end
+
```
+
+
```output
+
4680
+
```
+100
2021/day18.txt
···
+
[[[6,[8,3]],[2,0]],[[[9,5],[9,1]],3]]
+
[[[9,[2,2]],[5,4]],[[[2,2],[9,6]],[7,7]]]
+
[[[0,[3,2]],1],[[0,[2,8]],[2,[0,4]]]]
+
[[4,4],[[[7,0],5],[3,1]]]
+
[[5,4],1]
+
[[[[7,6],4],9],[[9,1],9]]
+
[[[1,[7,8]],[[7,7],[1,6]]],[1,[6,[7,1]]]]
+
[[[[6,8],[5,6]],[[1,1],8]],[[[2,0],[3,1]],[2,[2,6]]]]
+
[[[6,3],[3,[7,1]]],8]
+
[[[9,4],[3,[0,6]]],[[2,[3,6]],[[9,8],[1,6]]]]
+
[9,[0,[[0,7],2]]]
+
[[[[8,4],7],[[9,2],[0,9]]],[[7,9],[8,[0,9]]]]
+
[[1,1],[[5,[3,8]],[3,[4,7]]]]
+
[[[9,[2,9]],[2,[2,9]]],[[[3,5],5],[[3,3],2]]]
+
[[[[5,4],9],0],[[[5,7],2],[[5,2],9]]]
+
[[2,[[1,0],[6,2]]],0]
+
[[[3,7],[7,6]],[[[2,8],5],[3,[9,7]]]]
+
[[2,[2,[8,8]]],[[[9,9],[1,1]],[[8,6],[0,3]]]]
+
[[8,1],[3,5]]
+
[[7,[[7,6],[2,0]]],4]
+
[[5,4],[[1,3],[5,[2,8]]]]
+
[7,9]
+
[[[[6,9],0],[1,[5,0]]],[[[6,4],3],7]]
+
[[[[3,7],3],[2,6]],[[0,4],[9,9]]]
+
[[[[1,5],[5,0]],[9,4]],[[[8,3],3],[8,[3,6]]]]
+
[[[[3,7],5],[[8,5],[1,5]]],[[0,6],[3,4]]]
+
[[[[4,0],2],[7,[8,4]]],[0,[5,[7,8]]]]
+
[[[[0,8],[0,4]],[9,3]],[[[5,4],[4,8]],[[1,6],[5,4]]]]
+
[[0,[0,3]],[[3,[1,5]],[[9,6],[0,6]]]]
+
[[9,[8,4]],[7,1]]
+
[[[[1,9],[7,7]],9],[[6,[4,5]],[8,[3,2]]]]
+
[5,[[2,[9,5]],[3,[4,0]]]]
+
[[[6,2],[[1,8],5]],6]
+
[[8,[6,[6,4]]],[0,[[9,8],7]]]
+
[[[[6,3],[8,0]],[8,[2,7]]],8]
+
[[[6,[3,6]],[[4,0],[4,7]]],[0,[[4,0],[4,5]]]]
+
[[[3,[8,1]],1],[2,3]]
+
[[[6,[7,0]],[[3,5],[3,4]]],7]
+
[[[[8,0],3],8],[[[1,6],3],[[0,5],2]]]
+
[[[3,7],[[9,8],8]],[[[8,4],7],[3,[1,7]]]]
+
[[[0,5],[[5,5],[7,8]]],[9,[5,[2,2]]]]
+
[[2,9],[[[7,4],4],[[8,0],[6,9]]]]
+
[[[[7,8],[8,8]],0],9]
+
[[[4,[0,6]],[[5,9],[0,1]]],[3,[6,7]]]
+
[[[7,[6,9]],[5,[6,4]]],[[[3,9],6],[[0,1],1]]]
+
[3,[[[6,9],7],[5,8]]]
+
[[[3,9],[[3,5],2]],[[[2,5],[4,6]],[8,0]]]
+
[[[9,7],3],[[[2,7],[0,9]],[3,[0,3]]]]
+
[[3,[4,0]],[[6,6],[4,5]]]
+
[[0,0],[[5,9],1]]
+
[[[6,8],[2,6]],[[[1,1],3],7]]
+
[[[4,4],[[1,0],[2,4]]],[2,6]]
+
[[[[6,0],6],[8,[9,9]]],[[4,2],[[1,8],[5,3]]]]
+
[[[[1,6],[4,3]],[5,5]],[[7,[9,9]],4]]
+
[[[[6,9],7],[9,3]],[[[9,6],5],0]]
+
[[3,[[7,2],[8,1]]],[[7,[3,0]],1]]
+
[0,[0,[1,3]]]
+
[[[0,5],[[6,1],[4,6]]],[[[0,4],8],[[4,5],9]]]
+
[[[[7,5],[7,0]],[6,[7,2]]],[7,[3,[4,1]]]]
+
[[3,3],[0,[6,2]]]
+
[[[3,8],[[7,3],6]],[[[0,8],3],[[8,9],[2,9]]]]
+
[[4,[[5,6],[4,0]]],[[7,[7,5]],[5,0]]]
+
[[[[2,5],[5,4]],9],[[[6,0],[0,0]],[[5,1],8]]]
+
[[2,[[1,7],7]],[[[4,5],[7,9]],0]]
+
[[[0,9],[[5,4],3]],3]
+
[[9,[[1,9],[1,6]]],[[9,[0,3]],[[8,8],[0,7]]]]
+
[[[[7,2],4],[7,8]],[[[4,1],[3,1]],[2,5]]]
+
[[[[1,8],3],[2,5]],[[0,[5,8]],[[1,3],[5,2]]]]
+
[[3,9],[[9,6],[5,[7,1]]]]
+
[1,[[3,[6,5]],[5,[2,7]]]]
+
[[[5,8],6],[8,[[9,4],[0,4]]]]
+
[0,[[5,[6,6]],[[7,4],[4,6]]]]
+
[[[[6,8],2],[[1,6],[8,2]]],6]
+
[7,2]
+
[[3,1],7]
+
[[[2,[9,5]],0],[[[7,3],4],8]]
+
[[[[0,0],[4,2]],5],[[8,6],2]]
+
[[1,[7,8]],[2,[[6,6],[5,7]]]]
+
[[[3,[6,0]],3],[[7,[4,4]],8]]
+
[[[9,[8,7]],[[4,2],4]],[[6,1],[[3,3],[2,2]]]]
+
[[[8,1],[[7,4],[5,9]]],9]
+
[[[2,[8,6]],[[9,8],2]],[[9,5],[1,[9,8]]]]
+
[[[[6,1],[3,1]],[[4,5],1]],[[[6,4],[6,2]],2]]
+
[[[[4,0],[0,1]],[[1,4],6]],7]
+
[[[[8,9],[0,2]],4],[[[9,8],8],[0,[0,6]]]]
+
[0,[[[0,9],1],7]]
+
[[1,[[3,7],3]],[[[2,4],3],0]]
+
[[[[7,6],3],8],[[5,5],9]]
+
[[2,[1,3]],[[[6,7],3],[[3,8],7]]]
+
[[[[0,6],6],6],[[5,[0,9]],[8,[2,4]]]]
+
[4,[[[3,0],[2,5]],[[7,4],1]]]
+
[[[[7,9],3],[0,[8,2]]],[[8,[3,4]],[[2,3],[1,6]]]]
+
[[[3,[6,3]],5],[[3,4],2]]
+
[[[[1,9],[0,3]],[0,8]],[[[4,2],[4,3]],[[8,9],5]]]
+
[[[[2,8],[4,9]],[[3,5],6]],[[6,[1,5]],[0,[9,7]]]]
+
[[6,3],[[[7,7],[1,7]],[[6,5],[0,8]]]]
+
[[1,[1,[5,8]]],7]
+
[[0,6],[9,[[3,4],0]]]
+
[[[[0,2],7],9],9]
+
[9,6]
+306
2021/day19.livemd
···
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 19
+
+
## Section
+
+
```elixir
+
# File.read!("day19.txt")
+
input =
+
File.read!("day19.txt")
+
|> String.split("\n\n")
+
|> Enum.map(fn scanner ->
+
scanner
+
|> String.split("\n", trim: true)
+
|> Enum.drop(1)
+
|> Enum.map(fn coords ->
+
coords
+
|> String.split(",")
+
|> Enum.map(&String.to_integer/1)
+
|> Enum.zip(~w[x y z]a)
+
|> Map.new(fn {v, k} -> {k, v} end)
+
end)
+
|> MapSet.new()
+
end)
+
+
length(input)
+
```
+
+
```output
+
34
+
```
+
+
$$
+
\left\{
+
\begin{alignat*}{3}
+
b_{x_1} r_x + b_{x_0} = a_{x_1} \\
+
b_{x_2} r_x + b_{x_0} = a_{x_2}
+
\end{alignat*}
+
\right.
+
\left\{
+
\begin{alignat*}{3}
+
b_{y_1} r_y + b_{y_0} = a_{y_1} \\
+
b_{y_2} r_y + b_{y_0} = a_{y_2} \\
+
\end{alignat*}
+
\right.
+
\left\{
+
\begin{alignat*}{3}
+
b_{z_1} r_z + b_{z_0} = a_{z_1} \\
+
b_{z_2} r_z + b_{z_0} = a_{z_2} \\
+
\end{alignat*}
+
\right.
+
$$
+
+
Where $$r_x, r_y, r_z \in \{-1, 1\}$$ and $$a_{xyz}, b_{xyz} = \text{const}$$.
+
This mean that we need to solve:
+
+
$$
+
B_x x + b_0 = a_x \\
+
B_y y + b_0 = a_y \\
+
B_z z + b_0 = a_z
+
$$
+
+
Where:
+
+
$$
+
B_d = \begin{bmatrix}
+
{b_1}_d & 1 \\
+
{b_2}_d & 1 \\
+
\end{bmatrix}
+
d = \begin{bmatrix}
+
r_d \\
+
b_{d_0}
+
\end{bmatrix}
+
a_d = \begin{bmatrix}
+
{a_1}_d \\
+
{a_2}_d
+
\end{bmatrix}
+
$$
+
+
By applying [Cramer's Rule](https://en.wikipedia.org/wiki/Cramer%27s_rule) we can solve these
+
linear equations with:
+
+
$$
+
e_d = \frac{
+
\begin{vmatrix}
+
{b_1}_d & 1 \\
+
{b_2}_d & 1
+
\end{vmatrix}
+
}{
+
\begin{vmatrix}
+
{a_1}_d & 1 \\
+
{a_2}_d & 1
+
\end{vmatrix}
+
} = \frac{{b_1}_d - {b_2}_d}{{a_1}_d - {a_2}_d} \\
+
b_{d_0} = \frac{
+
\begin{vmatrix}
+
{a_1}_d & {b_1}_d \\
+
{a_2}_d & {b_2}_d
+
\end{vmatrix}
+
}{
+
\begin{vmatrix}
+
{a_1}_d & 1 \\
+
{a_2}_d & 1
+
\end{vmatrix}
+
} = \frac{{a_1}_d {b_2}_d - {b_1}_d {a_2}_d}{{a_1}_d - {a_2}_d}
+
+
```elixir
+
defmodule Day19 do
+
def rebase(base, pairs1) do
+
pairs0 = pairs(base)
+
# Take common points
+
pa = Map.take(pairs0, Map.keys(pairs1))
+
pb = Map.take(pairs1, Map.keys(pairs0))
+
+
# Merge them
+
[{{a, b, axes1}, {_, _, axes2}} = p0 | others] =
+
Map.merge(pa, pb, fn _, a, b -> {a, b} end)
+
|> Map.values()
+
+
p1 = Enum.find(others, fn {{x, y, _}, _} -> a in [x, y] end)
+
p2 = Enum.find(others, fn {{x, y, _}, _} -> b in [x, y] end)
+
+
axes = axes_transformations(axes1, axes2)
+
+
a_1 = a
+
a_2 = b
+
b_1 = reaxe(select_common(p0, p1), axes)
+
b_2 = reaxe(select_common(p0, p2), axes)
+
+
transform =
+
for i <- ~w[x y z]a, into: %{} do
+
a_1 = a_1[i]
+
a_2 = a_2[i]
+
b_1 = b_1[i]
+
b_2 = b_2[i]
+
det_b = b_1 - b_2
+
r = div(a_1 - a_2, det_b)
+
+
b_0 = div(b_1 * a_2 - a_1 * b_2, det_b)
+
+
{i, {r, b_0}}
+
end
+
+
new_points =
+
pairs1
+
|> Map.values()
+
|> Enum.flat_map(&[elem(&1, 0), elem(&1, 1)])
+
|> Enum.uniq()
+
|> Enum.map(&reaxe(&1, axes))
+
|> do_rebase(transform)
+
|> MapSet.new()
+
+
%{x: {_, sx}, y: {_, sy}, z: {_, sz}} = transform
+
scanner = %{x: sx, y: sy, z: sz}
+
+
{new_points, scanner}
+
end
+
+
defp do_rebase(points, transform) do
+
points
+
|> Enum.map(fn p ->
+
Map.merge(p, transform, fn _k, d, {r, b} -> d * r + b end)
+
end)
+
|> MapSet.new()
+
end
+
+
defp select_common(a, b) do
+
case {a, b} do
+
{{_, {_, x, _}}, {_, {_, x, _}}} -> x
+
{{_, {x, _, _}}, {_, {x, _, _}}} -> x
+
{{_, {_, x, _}}, {_, {x, _, _}}} -> x
+
{{_, {x, _, _}}, {_, {_, x, _}}} -> x
+
end
+
end
+
+
defp axes_transformations(a, b) do
+
Map.merge(a, b, fn
+
_, a, b -> {a, b}
+
end)
+
|> Map.values()
+
|> Map.new()
+
end
+
+
defp reaxe(point, axes) do
+
%{
+
x: point[axes[:x]],
+
y: point[axes[:y]],
+
z: point[axes[:z]]
+
}
+
end
+
+
def pairs(points) do
+
for a <- points,
+
b <- points,
+
a < b,
+
dx = abs(a.x - b.x),
+
dy = abs(a.y - b.y),
+
dz = abs(a.z - b.z),
+
into: %{},
+
do: {{dx ** 2 + dy ** 2 + dz ** 2, dx + dy + dz}, {a, b, %{dx => :x, dy => :y, dz => :z}}}
+
end
+
end
+
```
+
+
```output
+
{:module, Day19, <<70, 79, 82, 49, 0, 0, 26, ...>>, {:pairs, 1}}
+
```
+
+
```elixir
+
[first | rest] = Enum.map(input, &Day19.pairs/1)
+
+
{joinable, later} =
+
Enum.split_with(rest, fn pairs ->
+
s1 = MapSet.new(first, fn {k, _} -> k end)
+
s2 = MapSet.new(pairs, fn {k, _} -> k end)
+
+
case MapSet.size(MapSet.intersection(s1, s2)) do
+
66 -> true
+
x when x < 66 -> false
+
end
+
end)
+
+
{length(joinable), length(later)}
+
```
+
+
```output
+
{3, 30}
+
```
+
+
```elixir
+
# Distances between each pair of points in `first`
+
+
points_set = MapSet.new(hd(input))
+
+
{points_set, scanners} =
+
Enum.reduce_while(
+
1..34,
+
{points_set, joinable, later, []},
+
fn i, {set, joinable, later, scanners} ->
+
{time, {set, scanners}} =
+
:timer.tc(fn ->
+
Enum.reduce(joinable, {set, scanners}, fn new, {base, scanners} ->
+
{new, scanner} = Day19.rebase(base, new)
+
+
{MapSet.union(new, base), [scanner | scanners]}
+
end)
+
end)
+
+
IO.inspect(time / 1_000_000)
+
+
current = Day19.pairs(set)
+
+
Enum.split_with(later, fn pairs ->
+
s1 = MapSet.new(current, fn {k, _} -> k end)
+
s2 = MapSet.new(pairs, fn {k, _} -> k end)
+
+
MapSet.size(MapSet.intersection(s1, s2)) >= 66
+
end)
+
|> case do
+
{[], []} ->
+
{:halt, {set, scanners}}
+
+
{joinable, later} ->
+
IO.inspect({length(joinable), length(later)}, label: i)
+
{:cont, {set, joinable, later, scanners}}
+
end
+
end
+
)
+
+
MapSet.size(points_set)
+
```
+
+
```output
+
0.002822
+
1: {5, 25}
+
0.017052
+
2: {5, 20}
+
0.0355
+
3: {7, 13}
+
0.134655
+
4: {6, 7}
+
0.229952
+
5: {5, 2}
+
0.288351
+
6: {1, 1}
+
0.076665
+
7: {1, 0}
+
0.071942
+
```
+
+
```output
+
396
+
```
+
+
```elixir
+
for(
+
a <- scanners,
+
b <- scanners,
+
do: abs(a.x - b.x) + abs(a.y - b.y) + abs(a.z - b.z)
+
)
+
|> Enum.max()
+
```
+
+
```output
+
11828
+
```
+949
2021/day19.txt
···
+
--- scanner 0 ---
+
-731,-763,-425
+
832,-512,-437
+
571,657,-514
+
594,551,-569
+
-604,638,718
+
-536,524,776
+
629,721,-564
+
-623,-444,440
+
-708,-610,437
+
550,-524,759
+
355,515,510
+
-683,877,-615
+
763,-622,-365
+
-833,-795,-362
+
-663,840,-668
+
-676,876,-848
+
7,-92,-35
+
560,-560,695
+
-559,539,599
+
528,-504,779
+
-709,-874,-390
+
457,445,563
+
841,-410,-363
+
-742,-511,374
+
422,463,367
+
+
--- scanner 1 ---
+
598,477,221
+
687,-702,-850
+
-586,-650,-945
+
-588,-636,-820
+
-676,-819,603
+
431,-621,738
+
-790,449,456
+
339,566,-635
+
386,708,-671
+
466,672,-647
+
245,-629,714
+
-674,520,398
+
-20,-191,-108
+
624,398,329
+
-712,486,-889
+
-851,477,396
+
-791,580,-833
+
627,330,296
+
623,-679,-824
+
-859,-833,629
+
697,-847,-874
+
-463,-586,-905
+
-607,554,-853
+
-789,-836,551
+
-168,-4,-10
+
413,-642,724
+
+
--- scanner 2 ---
+
676,816,-834
+
614,746,-853
+
-592,-743,-408
+
-72,47,-39
+
-744,-404,762
+
444,-703,786
+
753,-784,-474
+
-534,-783,-416
+
735,717,-765
+
568,482,582
+
-343,434,-675
+
-488,758,370
+
545,517,368
+
-489,888,446
+
-642,-821,-498
+
-351,372,-463
+
384,-705,874
+
-827,-527,719
+
624,-720,837
+
88,-28,74
+
503,604,524
+
-640,-593,761
+
-419,427,-552
+
690,-818,-490
+
-353,831,437
+
650,-734,-583
+
+
--- scanner 3 ---
+
-561,681,-898
+
-696,-781,-955
+
674,322,-753
+
-631,640,-859
+
421,399,364
+
-559,-639,519
+
451,-574,320
+
-599,-747,467
+
-813,515,442
+
809,328,-802
+
478,-579,460
+
-710,-656,-826
+
455,-597,-612
+
-600,-812,-818
+
555,-700,367
+
593,379,413
+
382,-629,-639
+
810,259,-767
+
-46,21,-86
+
-662,548,550
+
-618,-569,546
+
-710,453,457
+
-805,672,-885
+
479,482,472
+
444,-658,-572
+
75,-100,-5
+
+
--- scanner 4 ---
+
-720,-688,-429
+
75,21,146
+
-524,-443,905
+
-455,739,547
+
28,-141,13
+
-697,-360,919
+
826,-631,876
+
-556,623,540
+
710,450,-593
+
-545,-345,887
+
697,394,-509
+
767,-745,773
+
875,-803,856
+
614,-573,-535
+
542,624,862
+
-794,439,-772
+
561,-428,-543
+
-746,370,-754
+
-683,-626,-394
+
469,634,823
+
-628,431,-669
+
-754,-741,-370
+
741,613,-533
+
489,522,847
+
-374,623,575
+
664,-373,-571
+
+
--- scanner 5 ---
+
699,-825,730
+
537,-594,-346
+
346,566,583
+
-631,-481,703
+
-787,-523,790
+
859,752,-606
+
585,-767,662
+
424,-689,-351
+
-648,384,-472
+
684,-648,707
+
-709,511,419
+
-683,421,-534
+
-38,84,173
+
-707,350,-419
+
-342,-793,-586
+
765,684,-628
+
-573,-546,825
+
493,-563,-373
+
-785,510,549
+
701,831,-589
+
-718,375,476
+
-335,-697,-642
+
383,619,603
+
-293,-795,-521
+
347,799,590
+
117,6,18
+
+
--- scanner 6 ---
+
-716,-702,538
+
795,547,748
+
-711,527,-540
+
601,413,-940
+
-863,-529,-512
+
388,-501,-871
+
-723,-534,-539
+
787,759,810
+
-637,-524,557
+
719,670,755
+
300,-440,423
+
580,395,-842
+
-816,-655,-616
+
345,-571,505
+
554,-554,-934
+
-633,593,601
+
-741,560,752
+
547,-535,-827
+
753,381,-925
+
359,-597,479
+
-819,444,-482
+
10,13,-72
+
-664,-594,498
+
-770,424,-654
+
-726,498,649
+
+
--- scanner 7 ---
+
-582,-761,459
+
-453,-839,-862
+
804,-878,437
+
-612,749,581
+
436,398,564
+
-487,-795,-703
+
807,842,-463
+
750,-880,275
+
-549,511,-891
+
718,787,-531
+
145,-81,-100
+
-503,-738,369
+
-600,814,464
+
429,-893,-497
+
-599,645,571
+
-540,-758,410
+
718,-866,393
+
461,-908,-649
+
-523,537,-905
+
595,780,-455
+
-506,-902,-696
+
417,468,502
+
505,497,623
+
12,47,-20
+
-392,455,-950
+
443,-810,-670
+
+
--- scanner 8 ---
+
53,162,-22
+
967,695,948
+
770,-615,-548
+
-670,-668,425
+
968,599,931
+
956,564,873
+
-402,599,-642
+
-440,-235,-401
+
840,-611,-438
+
684,602,-426
+
609,-449,832
+
691,788,-464
+
-498,984,913
+
895,-586,-503
+
-501,913,878
+
167,129,170
+
695,623,-587
+
493,-550,825
+
-523,556,-616
+
-368,-412,-433
+
-478,-443,-393
+
-7,18,134
+
-390,903,852
+
-353,475,-643
+
609,-631,797
+
-691,-717,496
+
-674,-800,467
+
+
--- scanner 9 ---
+
523,-356,773
+
-764,463,-560
+
-425,-730,874
+
668,-366,749
+
728,-640,-825
+
67,173,60
+
903,419,-683
+
-787,551,-542
+
-403,-811,707
+
889,413,-586
+
749,-622,-839
+
-763,407,-508
+
741,-808,-815
+
-699,745,628
+
-523,-387,-566
+
-489,-747,745
+
-606,801,513
+
-724,-387,-543
+
-647,-369,-544
+
-682,846,572
+
658,516,448
+
518,532,446
+
460,523,469
+
94,-8,-68
+
885,388,-755
+
691,-430,723
+
+
--- scanner 10 ---
+
632,619,803
+
-337,-640,-546
+
746,-937,-943
+
-81,54,-168
+
821,-857,548
+
706,756,751
+
683,-855,672
+
-733,363,-817
+
-615,381,-906
+
-584,435,-808
+
-329,-782,-669
+
586,461,-730
+
659,730,711
+
-493,496,495
+
766,-822,-830
+
-338,-687,-635
+
-589,-913,412
+
721,-864,422
+
-601,-806,278
+
397,451,-676
+
-10,-104,0
+
-604,404,408
+
487,463,-794
+
775,-762,-933
+
-602,583,413
+
-461,-925,315
+
+
--- scanner 11 ---
+
-746,899,-576
+
407,869,433
+
-547,-309,328
+
-416,-384,339
+
-316,-483,-310
+
399,485,-678
+
698,-432,802
+
-46,-77,89
+
-648,857,-455
+
-726,877,401
+
-478,-429,-312
+
-744,850,-511
+
608,-772,-282
+
433,544,-625
+
629,-790,-380
+
-729,896,666
+
525,784,494
+
-451,-326,327
+
46,69,-60
+
359,887,502
+
470,509,-563
+
-434,-515,-324
+
456,-804,-297
+
-788,819,534
+
779,-460,686
+
597,-425,686
+
+
--- scanner 12 ---
+
363,-267,559
+
256,-401,547
+
-772,-682,-877
+
314,-661,-725
+
19,64,-38
+
-676,-711,473
+
-685,590,-796
+
-833,-770,417
+
-719,-516,-940
+
529,557,295
+
387,680,287
+
-625,644,776
+
244,-304,419
+
347,841,-808
+
407,944,-817
+
-702,-725,499
+
-173,172,-77
+
-738,-523,-833
+
-613,761,711
+
-722,549,-776
+
232,954,-788
+
-643,639,-799
+
312,-537,-863
+
305,-411,-763
+
482,646,296
+
-626,751,607
+
+
--- scanner 13 ---
+
292,-495,571
+
651,919,779
+
-175,-32,46
+
-939,696,356
+
-690,411,-464
+
-384,-810,562
+
-785,-685,-485
+
-795,451,-566
+
773,-408,-583
+
-906,399,-435
+
781,-531,-441
+
-455,-767,470
+
772,-497,-536
+
357,-612,559
+
-950,531,445
+
-455,-745,448
+
595,860,622
+
649,453,-298
+
-917,726,512
+
-20,152,68
+
-778,-675,-648
+
-763,-609,-482
+
509,416,-417
+
569,874,648
+
461,-602,572
+
521,550,-310
+
+
--- scanner 14 ---
+
-322,-641,670
+
-349,354,-648
+
-625,714,619
+
812,-715,-617
+
-491,-748,669
+
821,527,-792
+
909,550,885
+
-599,728,593
+
-294,286,-737
+
87,-111,72
+
354,-956,679
+
-668,-679,-347
+
425,-891,793
+
862,-818,-726
+
-387,-758,682
+
887,580,729
+
425,-913,771
+
-639,-800,-435
+
-356,278,-525
+
-46,-32,-48
+
899,577,-702
+
896,-755,-710
+
920,385,796
+
861,469,-784
+
-738,-741,-366
+
-681,773,462
+
+
--- scanner 15 ---
+
-863,636,832
+
887,603,374
+
-66,-152,-18
+
-406,-515,-665
+
-501,-905,785
+
542,-591,-441
+
790,520,-691
+
562,-667,653
+
888,610,607
+
-680,319,-645
+
-611,-836,857
+
813,415,-771
+
732,-702,658
+
668,-644,708
+
-784,760,860
+
-380,-439,-590
+
66,2,27
+
-839,277,-736
+
811,556,-859
+
-752,658,797
+
-576,-505,-555
+
-746,345,-682
+
543,-455,-365
+
851,590,554
+
-399,-914,859
+
436,-477,-381
+
+
--- scanner 16 ---
+
695,-489,-727
+
-393,764,-274
+
513,-404,724
+
733,406,705
+
788,-449,-811
+
804,-386,-777
+
-591,-456,576
+
-715,-313,-340
+
-544,907,364
+
135,43,-46
+
-534,924,338
+
-559,835,455
+
-315,762,-398
+
444,-463,823
+
424,417,-730
+
695,626,745
+
-693,-291,-340
+
-378,843,-372
+
425,-525,753
+
454,414,-693
+
-604,-446,472
+
-601,-248,-269
+
465,460,-686
+
-592,-563,407
+
749,580,604
+
76,148,91
+
+
--- scanner 17 ---
+
455,-760,-649
+
670,-470,334
+
569,454,608
+
-358,-652,-715
+
-522,413,-718
+
578,-408,376
+
-499,503,-639
+
-510,818,236
+
-465,-659,-734
+
530,478,-610
+
534,643,-733
+
-435,-673,316
+
-123,-22,19
+
-481,808,411
+
630,-482,500
+
-421,-818,-768
+
541,457,-771
+
-573,-797,318
+
-490,705,351
+
-535,-547,309
+
-502,454,-681
+
385,-756,-759
+
330,-731,-694
+
20,-66,-142
+
736,518,636
+
522,517,683
+
+
--- scanner 18 ---
+
488,-495,-482
+
753,833,793
+
575,545,-722
+
437,-478,-662
+
-380,740,-476
+
-589,-884,-619
+
-447,-668,405
+
512,-794,706
+
66,67,-124
+
-535,581,492
+
-383,-610,455
+
555,-671,789
+
-392,808,-633
+
-659,-782,-672
+
-477,812,-495
+
741,783,712
+
-641,-817,-476
+
721,728,746
+
-433,523,401
+
513,-605,602
+
613,677,-617
+
188,-120,-51
+
-553,-645,460
+
400,-493,-422
+
-598,533,370
+
546,787,-712
+
+
--- scanner 19 ---
+
680,468,656
+
-895,-366,652
+
-732,-787,-709
+
-801,-610,-698
+
451,-753,587
+
600,-429,-518
+
-808,-712,-655
+
-85,174,-91
+
381,-734,525
+
480,-665,466
+
-787,899,-508
+
-696,913,386
+
-631,962,384
+
-752,920,482
+
499,-445,-344
+
-864,885,-423
+
-821,796,-468
+
523,758,-784
+
56,66,25
+
466,693,-633
+
593,624,698
+
715,682,633
+
501,782,-567
+
-897,-420,814
+
459,-483,-564
+
-883,-452,696
+
+
--- scanner 20 ---
+
397,-456,465
+
822,541,-705
+
-805,-570,-623
+
484,-683,-391
+
-592,793,-393
+
-867,737,670
+
-592,-860,531
+
-506,805,-437
+
-881,820,497
+
-560,807,-275
+
432,554,511
+
-12,12,62
+
780,662,-607
+
467,492,474
+
406,-399,601
+
773,606,-703
+
328,-770,-433
+
-893,-541,-502
+
-503,-915,463
+
330,-529,600
+
408,439,440
+
-715,-853,455
+
-849,835,649
+
542,-805,-456
+
-129,-146,27
+
-874,-471,-564
+
+
--- scanner 21 ---
+
533,528,-756
+
635,945,504
+
924,-707,-431
+
926,-248,469
+
-453,651,678
+
743,907,422
+
18,113,48
+
-426,-601,-285
+
-587,-409,730
+
-602,-306,668
+
934,-310,681
+
450,651,-713
+
-736,841,-422
+
788,-764,-440
+
858,-303,558
+
637,717,-755
+
-701,958,-484
+
685,867,414
+
-219,-659,-318
+
789,-634,-364
+
-609,608,678
+
-494,-457,635
+
-602,695,664
+
-672,954,-527
+
-322,-639,-423
+
+
--- scanner 22 ---
+
665,-972,357
+
157,-75,5
+
-645,524,554
+
-661,-821,715
+
552,-766,-295
+
572,402,640
+
534,-897,368
+
-544,439,-366
+
-641,414,484
+
569,492,-403
+
596,-852,-283
+
-616,479,429
+
-479,-856,715
+
6,-31,124
+
618,534,-400
+
434,-798,-281
+
593,563,629
+
-537,458,-259
+
-703,405,-322
+
-338,-477,-268
+
-580,-849,831
+
758,440,633
+
569,-955,356
+
528,455,-423
+
-490,-509,-253
+
-511,-491,-351
+
+
--- scanner 23 ---
+
388,-809,-352
+
-367,872,532
+
-415,-631,622
+
743,-603,724
+
-753,552,-643
+
562,-642,690
+
139,81,144
+
451,-707,-384
+
-381,-642,874
+
383,456,849
+
-411,-684,-537
+
416,-685,-273
+
-384,-613,831
+
-338,776,398
+
412,553,858
+
399,591,733
+
-264,869,422
+
-733,574,-623
+
-414,-599,-703
+
674,-497,728
+
48,-39,41
+
389,865,-737
+
-669,584,-587
+
463,856,-635
+
-348,-718,-636
+
391,787,-525
+
+
--- scanner 24 ---
+
-784,-392,606
+
-484,366,661
+
736,683,764
+
-663,-858,-769
+
833,-740,823
+
-553,-789,-841
+
821,-458,-849
+
-765,-867,-843
+
700,495,-558
+
87,-2,28
+
-325,324,752
+
790,830,797
+
705,-593,-833
+
836,-846,942
+
-418,392,698
+
830,-555,-820
+
1,-137,118
+
870,-733,933
+
662,640,-670
+
-380,807,-844
+
-301,683,-816
+
-588,-458,571
+
696,601,-489
+
-412,705,-781
+
-758,-468,681
+
661,785,811
+
+
--- scanner 25 ---
+
500,-759,-543
+
637,-476,865
+
844,524,-809
+
691,-401,789
+
755,549,-692
+
-670,-822,952
+
680,-578,858
+
374,779,921
+
-536,581,-571
+
-543,-454,-324
+
326,-743,-442
+
-738,485,812
+
-605,-435,-394
+
-832,-768,954
+
827,534,-783
+
396,700,869
+
-697,522,832
+
-24,26,176
+
-643,582,-740
+
-484,-523,-423
+
546,-705,-402
+
-526,594,-675
+
36,-123,83
+
-648,564,835
+
-714,-736,940
+
311,819,948
+
+
--- scanner 26 ---
+
-609,-865,-696
+
-730,-552,628
+
320,796,-676
+
-480,446,-760
+
-789,-814,-679
+
752,-686,698
+
86,-103,-33
+
-54,-53,105
+
601,-621,755
+
-543,462,-794
+
-688,-396,541
+
312,517,722
+
462,-422,-642
+
426,-451,-511
+
-557,806,840
+
535,-710,720
+
-619,825,770
+
366,785,-669
+
-849,-902,-681
+
532,555,762
+
-498,737,741
+
444,-531,-542
+
-665,-610,506
+
323,826,-713
+
-583,555,-710
+
486,501,621
+
+
--- scanner 27 ---
+
440,-949,710
+
-548,356,729
+
-860,601,-538
+
464,-767,-452
+
653,723,873
+
-846,-908,-728
+
440,436,-892
+
-730,-861,516
+
4,-62,-113
+
541,420,-718
+
407,-702,-603
+
581,741,842
+
484,727,848
+
442,-791,-669
+
-674,-844,415
+
458,-926,798
+
-923,-894,-813
+
-880,-805,-768
+
-93,-141,27
+
-550,496,745
+
400,474,-672
+
-571,298,738
+
-615,-768,460
+
-867,703,-581
+
-791,778,-527
+
406,-925,854
+
+
--- scanner 28 ---
+
647,354,627
+
754,-710,818
+
-32,-37,79
+
-607,574,728
+
706,-823,-325
+
-440,806,-361
+
811,-701,682
+
-630,680,673
+
686,-718,-428
+
-604,-428,344
+
627,391,574
+
-907,-614,-778
+
593,431,-839
+
681,-777,683
+
-481,-385,427
+
452,429,-751
+
557,452,-671
+
9,100,-69
+
-911,-657,-807
+
-554,700,-421
+
648,-856,-532
+
-665,510,678
+
640,355,394
+
-670,-386,531
+
-794,-719,-842
+
-418,699,-345
+
+
--- scanner 29 ---
+
345,-686,278
+
590,445,375
+
-10,-33,-90
+
730,443,391
+
-830,567,-808
+
-329,-599,712
+
-452,-400,-567
+
725,770,-497
+
-454,-606,663
+
788,466,382
+
580,746,-507
+
359,-589,272
+
557,720,-571
+
-688,531,-855
+
-520,-433,-570
+
-571,763,607
+
363,-758,247
+
-794,543,-728
+
-464,-557,820
+
-121,76,13
+
-599,-325,-596
+
-469,671,559
+
-529,590,644
+
520,-828,-781
+
507,-818,-949
+
499,-842,-763
+
+
--- scanner 30 ---
+
898,-783,-440
+
922,437,482
+
-471,-599,844
+
754,-763,593
+
74,-14,20
+
-699,-844,-819
+
905,-782,548
+
7,-163,-135
+
864,402,436
+
-386,-589,679
+
427,680,-886
+
405,573,-902
+
-465,303,-496
+
-661,-982,-715
+
-477,-574,623
+
-728,245,476
+
-719,-949,-922
+
541,574,-826
+
-570,326,-576
+
781,-845,-405
+
-555,248,370
+
-606,305,-408
+
907,-709,651
+
894,-740,-469
+
916,504,488
+
-697,342,327
+
+
--- scanner 31 ---
+
246,-795,-450
+
689,777,-513
+
-737,-654,-829
+
659,821,460
+
300,-430,432
+
-748,371,-546
+
-636,391,-522
+
-451,-517,506
+
555,774,586
+
-738,444,-507
+
-33,-82,-118
+
-476,718,803
+
329,-622,-464
+
-576,-488,551
+
231,-643,-482
+
-498,868,705
+
632,681,465
+
-737,-472,-794
+
-853,-553,-822
+
631,669,-596
+
5,80,24
+
344,-589,466
+
-506,-492,441
+
517,728,-493
+
-469,691,760
+
237,-596,485
+
+
--- scanner 32 ---
+
299,519,833
+
-547,650,-617
+
395,-426,414
+
-954,-698,761
+
643,-437,-429
+
-715,929,492
+
-555,612,-825
+
-856,-676,911
+
-911,-705,734
+
313,846,-260
+
-657,-723,-474
+
-658,986,590
+
267,489,859
+
-714,907,743
+
371,-538,434
+
342,863,-343
+
671,-321,-510
+
-592,-668,-449
+
-702,-598,-445
+
-134,142,-43
+
-587,540,-648
+
239,648,792
+
356,-436,487
+
678,-437,-611
+
-22,23,114
+
271,842,-392
+
+
--- scanner 33 ---
+
353,649,717
+
632,-572,-385
+
627,-425,511
+
569,-375,575
+
-478,613,-778
+
566,-759,-427
+
420,506,769
+
759,692,-309
+
455,702,787
+
742,512,-360
+
592,-430,681
+
-443,636,-564
+
-678,-709,356
+
744,452,-272
+
-665,-529,392
+
-606,857,594
+
-792,-285,-709
+
-685,-476,355
+
39,-2,98
+
-561,738,693
+
-31,148,10
+
-849,-421,-700
+
-565,571,-622
+
-538,915,708
+
443,-676,-384
+
-719,-420,-776
+80
2021/day2.livemd
···
+
<!-- vim:ft=markdown
+
-->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 2
+
+
## Load input
+
+
We do parsing there, as it will help us with the latter tasks. Pattern matching
+
is the simplest approach there, as input is in form of:
+
+
```
+
forward 10
+
up 20
+
down 30
+
```
+
+
We need to `trim/1` input to make sure that the last newline will not interrupt
+
`String.to_integer/1` calls.
+
+
```elixir
+
stream =
+
File.stream!("day2.txt")
+
|> Stream.map(fn input ->
+
case String.trim(input) do
+
"forward " <> n -> {:forward, String.to_integer(n)}
+
"up " <> n -> {:up, String.to_integer(n)}
+
"down " <> n -> {:down, String.to_integer(n)}
+
end
+
end)
+
```
+
+
```output
+
#Stream<[
+
enum: %File.Stream{
+
line_or_bytes: :line,
+
modes: [:raw, :read_ahead, :binary],
+
path: "day2.txt",
+
raw: true
+
},
+
funs: [#Function<47.58486609/1 in Stream.map/2>]
+
]>
+
```
+
+
## Task 1
+
+
```elixir
+
{h, d} =
+
stream
+
|> Enum.reduce({0, 0}, fn
+
{:forward, n}, {h, d} -> {h + n, d}
+
{:up, n}, {h, d} -> {h, d - n}
+
{:down, n}, {h, d} -> {h, d + n}
+
end)
+
+
h * d
+
```
+
+
```output
+
1499229
+
```
+
+
## Task 2
+
+
```elixir
+
{h, d, _} =
+
stream
+
|> Enum.reduce({0, 0, 0}, fn
+
{:forward, n}, {h, d, a} -> {h + n, d + a * n, a}
+
{:up, n}, {h, d, a} -> {h, d, a - n}
+
{:down, n}, {h, d, a} -> {h, d, a + n}
+
end)
+
+
h * d
+
```
+
+
```output
+
1340836560
+
```
+259
2021/day20.livemd
···
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 20
+
+
## Section
+
+
```elixir
+
[algo, board] =
+
File.read!("day20.txt")
+
|> String.split("\n\n")
+
+
board =
+
board
+
|> String.split("\n", trim: true)
+
|> Enum.with_index()
+
|> Enum.flat_map(fn {row, y} ->
+
:binary.bin_to_list(row)
+
|> Enum.with_index()
+
|> Enum.map(fn {c, x} -> {{x, y}, if(c == ?#, do: 1, else: 0)} end)
+
end)
+
|> Map.new()
+
+
defmodule Day20 do
+
defmodule Image do
+
defstruct [:board, :background]
+
+
@behaviour Access
+
+
def new(board, background \\ 0),
+
do: %__MODULE__{board: board, background: background}
+
+
def dims(%__MODULE__{board: board}) do
+
{{min_x, min_y}, {max_x, max_y}} = board |> Map.keys() |> Enum.min_max()
+
+
{min_x..max_x, min_y..max_y}
+
end
+
+
def lighted(%__MODULE__{background: 1}), do: :inf
+
def lighted(%__MODULE__{board: board}), do: board |> Map.values() |> Enum.sum()
+
+
@impl Access
+
def fetch(%__MODULE__{} = img, {_, _} = key) do
+
case Map.fetch(img.board, key) do
+
{:ok, value} -> {:ok, value}
+
:error -> {:ok, img.background}
+
end
+
end
+
+
def fetch(_data, _key), do: :error
+
+
@impl Access
+
def get_and_update(_data, _key, _func), do: :error
+
+
@impl Access
+
def pop(_data, _key), do: :error
+
+
defimpl Inspect do
+
import Inspect.Algebra
+
+
def inspect(%@for{} = img, _opts) do
+
{min_x..max_x, min_y..max_y} = @for.dims(img)
+
+
display =
+
for y <- (min_y - 1)..(max_y + 1) do
+
row =
+
for x <- (min_x - 1)..(max_x + 1) do
+
if img[{x, y}] == 1, do: "█", else: " "
+
end
+
+
concat([concat(row), line()])
+
end
+
+
concat([
+
"#Image<{#{max_x - min_x + 1}x#{max_y - min_y + 1}}",
+
line(),
+
concat(display),
+
">"
+
])
+
end
+
end
+
end
+
+
defmodule Algo do
+
defstruct [:desc]
+
+
@behaviour Access
+
+
def new(desc), do: %__MODULE__{desc: desc}
+
+
@impl Access
+
def fetch(%__MODULE__{desc: desc}, pos) do
+
loc = rem(pos, 512)
+
{:ok, if(binary_part(desc, loc, 1) == "#", do: 1, else: 0)}
+
end
+
+
@impl Access
+
def get_and_update(_data, _key, _func), do: :error
+
+
@impl Access
+
def pop(_data, _key), do: :error
+
end
+
+
def get_bits(img, {x, y}) do
+
digits =
+
for dy <- -1..1,
+
dx <- -1..1,
+
do: img[{x + dx, y + dy}]
+
+
Integer.undigits(digits, 2)
+
end
+
+
def enchance(img, algo) do
+
{min_x..max_x, min_y..max_y} = Image.dims(img)
+
+
board =
+
for y <- (min_y - 1)..(max_y + 1),
+
x <- (min_x - 1)..(max_x + 1),
+
into: %{},
+
do: {{x, y}, algo[get_bits(img, {x, y})]}
+
+
Image.new(board, algo[512 - img.background])
+
end
+
end
+
+
alg = Day20.Algo.new(algo)
+
img = Day20.Image.new(board)
+
```
+
+
```output
+
#Image<{100x100}
+
+
█ █ █ ██ ████████ ██ █ █ ███ █ ██ ██ █ ███ █ ██ █ █ █ ██ ███ █ ██ ██ █ ██ █
+
███ █ █ █ █ ██ ██ █ ████ ██ █ █ ███ █ █ █ █ ███ █ █ ███ ██ ██████ █ █ █████
+
██ █ ███ █ █ ███ ██ ███ █ █ █ █ █ █ ██ ███ ███ ██████ ████ █ █ ██ █ ██ ████ █ ██
+
█ ██ ████████ ██ █ █ █ █ ██ █ █ █ █ ██ ██ █ █ █ ██ █ █ █ ██████ █ █ █
+
███ █ ██ ████ █ █ █ ███ ███ ██ █ █ ███ █ ██ █ ██ ███ █ ██ ██ ██ █ █ ████ █ █
+
████ ███ █ ███ █ █ █ █ █████████ ████ █ █ ██ ██ █ █ █ █ █ █ █ █ ███ ██ ██
+
███ █ █████ ████ ██ ████ █ █████ ██ ██ ████ ███ ███ ██ █ █ █ ██████ ██ █ ██ █
+
█ █ █ ███ █ █ █ █ ████ ████ █ █ █ █ █ █ █ ██ █ █ █ █ █████ ██ █ █ ███
+
██ ██ ███ █ █ █ █ █ ████ █ ██ ███ █ █ █ ██ █ █ ██ ███ ███ █ █████ █ █
+
██ █ █ █ █ ██ █ ██ ███ ███ ██ █ █ █████ █ ██ █ ███ █ █ ██ ███ █ █ ████ ██ ██████
+
█ █ ████ ███ █████ ███ ██ ██ ████ ██ ██ █████████ █ █ ████ ██ █ █ ██ █ ██
+
█ █ █ █ █ █ █ █ █ ███ ██ █ ██ █ █ ██ █ █████ █ ███ ██ █ █ █ ██ ██ ██████ ██
+
██ ████ ██ █ ███████ ██ ██ ██ ████ ████ ██ ████ █ ███ █ ███ ██ █ ████ ███ ██
+
█ █ █ █ █ █ █ █ █ █████ █ █ ███ █ ██ █████ ██ █ █ █ ██ █ █ █ ███ █ █ █ █ █
+
██ █ █ █ ███ ███ ██ ████ ███ █ ██ █ █ ██ ███ ██ █ █ ██ █ ██ █ ██ ██ █ █ █ █ █ ███
+
█ ██ █ █ █ █ ███ ██ ███████ ███ █ █ █████ ███ █ █ ███ ███ ███ ██████ █ █ █ █████ █
+
████ █ ████ █ ████ ██ ████ ██ █ ██████ ███ ███ █ █ █ █ ██ ███████ ██ █ ████ ██ █
+
██ █ ███ ██ ██ ███ █ █ █ █ ██ ███ ██ ██ █ ████ █ █ █ ████ █ ██ █ █ █ ██ █
+
█ █ █ ██ ███ █ ████ ██ ██ █ █ ██ ██ ██ ███ ██ ██ █ ███ ███ █ █ ███ █
+
███ █ █ ██ ████ █ ██ ███ █ ██ █ █ █ █ ███ ██ ███ █ █ █ █ █ █████ █ ████ ██ ████ ██
+
█ █ █ ██ █ █ █ ███ ██████████ ██ █ ████ ██ ██ ███ ██ █ ██ █ █ █ ██ ███ █
+
█ █ ██ █ █ █ █ ██████████ ███ █ █ █ ██ █████ █ ██ █ ████ ███ █ █ ███ ███ ██ █
+
███ █ ██ ██ ████ █ ████ ██ ██████ █ █ █ ██ █████ ████ ██ ████ ██████ █ ██ ██ █
+
██ █████ █ ██ ███ ███ █ █ █ ██████ █ ████ ████ ██ ██ ██ ██ █ █ ████ █████ ██████
+
██ █ █ ███ █ ████ █ ████ ██ █ ████ ██ ████ ██ █ ███ █ ███ █ █ █ ██ █
+
█ ███ ██ ██ █ ██ ██ █ █ ███ ██ █ █ █ ██ █ █ ██ █ █ █ ██ ██ █ █ █ █ █ ██ █
+
█████ █ ███ ███ █ █ ██ ███ ███ ██ ██ █ ███ █ ██ ███ █ ███ ██ ██ █ ██ ███ ████ ███
+
█ ████ █ █ ███ ██ █ ██ ██ █ █ █ ██ █ █ █ █ ██ █ ██ ██████ ██ ████ ██ █ █
+
█ █ █ ██ ██ ██ ███ █ ███ █ ██ █ █████ █ █ ██ ███████ ██ █ █ ██ ████ █████ █ █ ██
+
█ █ █ █ ██ ██ ██ ██ █ ██ ██ ███ █ █ █ ██ █ █ █ ██ ███ █ ███ █ █ ██
+
█ █ ████ █ ██ █ ███ ██ █ ██ █████████ ███ ██ ██ █ █ █ █ ██ ███ ██ █
+
███ ██ █ █ █ ██ ██ ██ ██ █ █ █ ██ █ ██ █ ██ █ ██ ██ █ █ ████ ███ █ ██ ██ █ ███ ██
+
███ █ ██████ █ ███ ██ ███ ██ █ ██████ ███ ███ █ ██ ██ █ ██ ██ ██ █ █ ██ ██ █
+
██ █ █ ██ ██ █ █ ████ ██ █ █ █ ██ █████ ██ ██ █ ███ ███ ███ █
+
██ ███ █ █ █ █ ██ █ ██ ████ ███ ██ █████ ██ █ ██ ██ █ █ █ ██████ █ █ ███
+
██ ██ █ ███ █ ███ █ █ ███ ████ ██ █ █ █ ████ █ ████ ██ ███ █ ██ ██ ████ ███ █ █ ██ ██
+
█ █ █████ ██ █ ██ ███ █ █ █ █ █████████ ██ ██ █ █ ███ █ ██ ████████ █ ██
+
██ ██ ██ ██ ██ ███ █ █ ████ █ █ █ ███ █ █ █ █ ███ █ █ ██ ██ ██ █ █
+
█ ██ █████ ██ █ ███ ██ ██ ██ █ █ █ █ █ █ █████ █ ██ █ ██ █ █ ████ ██
+
██ ████ ██ █ ███ ████ ███ █ ██ ██ █ ██ █ ███ ███ █ █ ██████ █ █████ ██ █ ███ █ █
+
█ █ █ █ ███ █ █ ██ ███ █ ██ ████ █ █ █████ █ ███ ██████ █ ███ ██ ████ █ ██ █ █
+
█ ██ ██ █ ██ █ ██ █ █ █ █ ██ ██ █ ██ █ ██ █ █ ██ ███ ███ ██ █ █ █ ██
+
███ ██ ██ █ █ ██ ████ ███ █ ████ ███ █ ██ █ █ █ ███ █ █ ███ █ ████ ██ █ █ ████
+
█ █ ██ ██ █ ██ █ █ ██ ██ ███ ███ ████ ██ ███ █ ██ ██ ██ ████ █ █ ██ ██ █
+
█ █ ██ █ █ ██ █ ████ ███████ ██ █ █ ██ █ █ ███ ███ █ ██ █ ██ █ ██ ██ █ █ ███ █
+
████ █████ ██ ██ █████ █ █ ██ ██ ███ █ ███ █ █ ██ ███ ███ █████ ██ █
+
█ ███ ███ █ █ █ ██████ ███ ████ █████ ███ ███ ███ ██ █ ██ █ ██ ██ █ ███ █████
+
█ █ ██ █ ████ █████ ███ █ █████ █ █ █ █ █ ██ ██ █ █ █ █ ███ ███ ███ █████ █ ██ █ █ █ █
+
█ █ █ █ ██ █ ████ ███ █ █ ████████ ████ █ ██ █████ █ █ █ ███ █ █ ████ █ █
+
██ ███ ███ █ ██ █ █ █ ████ █ ███ ██ █ █ ██████ ██ ██ █ █ ████ █ ███ █
+
██ ████ ██ █ █ ████ █ ██ ██ ██ ███ █ ██ █ █ ██ █████ █████ █ █ █ █ ██
+
█ ██ █ ███ █ █ ██ ███ ███ ██ █ ██ ███ ████ █ █ █ █ ██ █ █ █ █████ █ █ █ █
+
█ ██ ███ ███ ███ █ █ █ ██ █ ███ ███ █ ██ █ █ ███ ██ █ ██ █ ██ ██ ██ █
+
███ █ █ █ ███ ███ █ █ █████ ████ █ █ ██ █████ █ ███ █ █ ███████ ████ █ ██
+
█ ██ █████ █ ██ ███ ██ █ █ ██ ██ ██ █ █ █ █ ███ █ ██ █ ██ ██ █ █ ██ ██ ███ █ █ ██
+
██ █ ████ ██ █ █████ █ █ ██████ ███ █ █ ██ ██ ██ █ ██ █ █ ██ ██ █ █ █ █ █ █ █ ██ █
+
█ ███████ █ █ ██ █ █ █ █ ████ █ █ █ █ █ ████ █ █ █ █ ██ ██ ██ ██ █ █
+
██ █ ████ █ █ █ ████████ █ █ ███ █ ████ █ █████ ██ ████ █ ███ ██ █ █ █ ██ █████
+
██ █ ██ █ █ █ █ █ █ █████████ █████ █ ███ █ ██ ██ █ ██ ███ ██ █ █ █ █ ████ █ █ ████ █
+
█████ ████ ██ ██ █ █ █ ██████ █ █ █ █ █ █ █ ██ █ █ ███ █ █ ████ ███ ██ █ █ █ █
+
██ █ ███ ██████ █ █ █ ██████ ██ █ █ ██████ ███ ██ █████ ████ █ █ █ ██ ███ █ ██ ██
+
█ ████ ██ █ █ █ █ ███ ██ █ ██ █ █ █████ ██ ██ █ ████ ███ █ █ ██ ██ ████ ███
+
██ ███ █ ███ █ ██ █ ██ ██ ███████ ██ █ █ ████ █ ████ ████ ███ ██ ██ ██ █ █ █ █ █
+
██ █ ██████ █ █ ██ ██████ █████ ███ █ ███ ██ █ ███ █ █ █ ███ █ ████ ████ ██ ██
+
████ █ ██ ██ █ █ █ ██ █ █ ██ █ ██ █ ███████ █ ██ ███ █ █ ███ ████ ███ █ █ █
+
█ ██ █ █ ██ ████ ███████ ██ █ ██ █ █ ██ █ ███ █ █ █ ███ █ █ ████ █ ██ █ █
+
██ █ ██ ██ █ █ █ ███████ ██ █ ███ █ ███ █ ██ █ █ █ █ █ ██ ██ █ ███ ███ ██ ██
+
█ █ ███ █ ██ █████ █ ██ █ ██ ███ █ █ █ ██ █████ █████ ███ █ ████ █ █ ███ █
+
█ ████ █ █ █ █ ██████ ██ ██ ██ █ █ █ █ █ ██ █ ████████████ ███ ████ ███ ███
+
█ █ █ █ ██ ██ █ █ █ ████ ██ ██ █ █ █ ██ ██ █ █ █ █ █ █ ███ █ █████ ██ ███ █ █
+
█ █ ██ ███ █ █ ███ █ █ █ ██ ██ ████████ █ █ █████ █ █ █ ██ █ ██ ████
+
█ █████ █ ██ ███ █ █ █ █ ███ ██ █ ██ ██ █ █████ █ █ ██ █ ███ ██ █ █ ██ █ █ █ █
+
███ █ █ █ █ ██ █ █ █ █ █ █ █ ███ ██ ████ ██████ █ █████ ███ ██ █ █
+
█ █ █ ██ █ █ ████ █ █ █████ █ █ █ █ ██ ██ █ █ █ █████ █ ██ █
+
█ ████ █ █ █ ██ ██ █ █ █ ██ ██ ██ ██ ██ █ █ █ ██ ██ ██ █ ██ █ █ ██ █ █
+
█ ████ ███ █████ █ █ ████ ██ █████ ██ ███ █ ███ ██ ██ ██ █ █ █ ███ █
+
█ █ ████ █ ██ █ █ ██████ ███████ █ ██ ███ ███ █ █ ██ █ ████ ███ █ ███ █ █
+
███ ██ █ ██ █ █ █████ ██████ █ ██████ ██ █ ██ █ ██ ███ █ █ █ █ ███ ██ ████ ██ █
+
█ ███ █ █████ █ █ ███ ██ ██ ██ ███ █ █ █ █ █ ████ █ ████ █ ██ █ █ ██
+
█ ████ ███ █ █ ████ █ █ ██ ███ █ ██ █ █ ██ █ █ ██ █ █ ██ ██ █████ █ █ ███ █ ████
+
█ ██ ██ ██ ██ █ █ ██ ███ ████ ███ ████ █ ██ █ █ ███ ███ ██████ █████ ███ ████ █
+
██ █ ███ █ █ ███ █ ██ ███ █ ██ █████ █ ███ █ █ ██ █ █ █ ████ ██ ██ ███ █ █ █ ██
+
█ ███ ███ ███ ██ █ ███ █ ████ ██ █ █ ███ █ ██ ██████ █ █ ███ █ ██ ██ ███ ██ █ █
+
█ █ █ █ █ █ █ █ █ █ ██ █ █ ███ ███ █ █ █████ █ █ █ █ █ █ █ █ ██ ██ █ ██ █
+
█ ██ █ █ ██ ██████ █ █ █ ██ █ █ ██ █ ███ █ █ █ ██ ██ █ █ ███████
+
██ ██ █ █ █ █ █ ██████ ██ ████ █ █ █ ██ █ █ █ █ ███ █ ███ █ █ █ ██ ███
+
█ ████ █ ██ ██ ███ █ ██ █ ██ ████ █ █ ██ █ █ █ ███ █ ██ ██ ████ ███
+
█ ██ ██ █ █ █ █ ███ ██ █ ████ ████ ███ ██ ██ ██ ███ █ ██████
+
███ ███ ██ █ █ ██ ██ █ ██ █ █ █ █ ███ █ ███ █ ██ ███ █ █████ ███ ███ ████ █ █ ██
+
██ █ █ ████ █ █ ███ ██ █████ █ █ ██ █ █ ██ ██ █ ███ █ █ █ █ █ █ ██ █ ██ ██
+
███ █████ ██ ██ █ ███ █ █ ███ ████ ██ █ █████ ██ █ ██ ████ █ █ █
+
███ █ █ ███ █ ██ █ █████ █ ██ ████████ ██ ████ █ ████████ █ ███ █ ████ █ █
+
█ █ ██ █ ██ █ █ █ ██ ██ █ ██ █ ██ █ █ ██ ██ ██ █ ██ ███ ███ █ ██ ███
+
█ ███ ██ █ █ ███ ███ ██ ██ █ █ █ █ █ ███ █ ██ ██ █ █ ███████ █ ███ ███
+
██ █ █ █ █ ████ ██ █ █████ ██████ █ █ █ █ █ ██ █ █ ███ █ █ █ █ ██
+
█ █ █ █ ████ ██ ██ █ █ █ ███ █ █ █ ██ █ █ ██ █ ██ █ █ █ ██ █ ███ █ ███ ██
+
██ █ █ ██ ██ █ █ █ █ ███ █ ██ █ ██ █ █ █ █ ██ ██ ███ ██ ███ ██ ██████ ███
+
██ █ █ █ █ █ ███ ███ ████ ██ ██ ███ █ █ ████ █ ███ █ ██ ██ █ █ ███ ███ █ █ █ ███ █
+
██ ████ ██ █ █ █ █ █ ██ ██████ ██ █ █ █ █ █ █ █ █ ██ █ █ ████████ █
+
████ ██ █ █ ████ █ █ ██ █ █ █ █ ██ █ █ █ ████ █ █████ ███ ██ █ ████ ██ ███ █ █ █ █████
+
+
>
+
```
+
+
## Task 1
+
+
```elixir
+
img
+
|> Day20.enchance(alg)
+
|> Day20.enchance(alg)
+
|> Day20.Image.lighted()
+
```
+
+
```output
+
5179
+
```
+
+
## Task 2
+
+
```elixir
+
1..50
+
|> Enum.reduce(img, fn _, acc -> Day20.enchance(acc, alg) end)
+
|> Day20.Image.lighted()
+
```
+
+
```output
+
16112
+
```
+102
2021/day20.txt
···
+
####...###.###.##.##.##..###..##.#.##.#...####..##...#..#..#....#..#..##.##..#.#.####.######.#..#.##..##....#.####.##...#.#..#.####.#.#.#..###.##..#.#.#.#...#.....###.#.#...#..#....#######....#..#...###.##.........#.#.##.#........##...#..##.......####.#.#.#.#.#.####..#..........#.##......##......###.#..##.#.#.....###.#..#...###.##........#..#.##.#.###.#..#####..##..#..#.#.#...###..##..#.###.##...#.##.#.....#.#..........#..##.#########.#.#..##.#.##..######.....####...###..###.#..##########.#.#.....###.##.##.
+
+
#.#...#..##..########...##....#.#.###.#.##.##...#..###.#.##.#.#..#..##..###....#..##.##....#...##.#.
+
.###.#..#.#.#..##.##.#.####..##.#...#.###...#.#....#.#.###..#.#..###...##..######..#..#..#####......
+
##.#.###.#.#..###...##..###.#.#..#....#...#..#.....##..###.###.######.####.#.#...##.#.##.####..#.##.
+
...#..##...########.##..#..#...#...#...##.#..#.#..#.##..##.#..#...#.##........#.#.#.######..#..#.#..
+
.....###....#.##....####..#.#.#.###.###.##.#.#.###..#..##.#...##.###..#.##..##.##..#.#....####..#.#.
+
..####..###.#..###.#.....#..#..#....#########.####.#..#.##.##..#....#.....#.#.#..#.#..#..###.##...##
+
###.#..#####...####.##...####...#.#####.##...##.####.###...###...##...#..#.#.######.##....#....##..#
+
...#...#.#.###..#.#..#.#.####..####.#..#...#...#.#...#...#.....##..#.....#.#.#....#####.##..#.#..###
+
##...##..###..#..#...#..#..#.####...#.##.###.#.#....#..##....#.....#.##.###.###.#.....#####.#...#...
+
.##.#..#..#..#.##.#.##.###.###....##.#.#...#####.#..##..#....###..#.#...##.###.#..#.####..##..######
+
#.#..####.###.#####.###.##....##..####.##.##.#########.........#.#.....####.##.....#.#...##.#....##.
+
.#..#.#.#..#.#.#.#.#..###....##.#.##.#....#.##.#....#####.#..###...##......#..#.#.##..##..######..##
+
..##.####.##.....#.#######..##.##...##.####.####.##...####..#.###....#..###..##..#.####....###..##..
+
#.#....#...#.#.#..#.#..#...#####..#.#..###.#.##...#####.....##.#....#.#.##.#..#.#..###...#.#.#..#..#
+
##.#.#..#.###.###.##.####....###.#.##.#.#.##...###.##.#.#...##.#.##..#.##.##.#.#....#.....#.#.###...
+
.#.##.#....#.#.#.###.##..#######.###..#...#...#####.###.#.#.###..###...###.######.#.#....#...#####.#
+
####..#..####.#......####..##...####...##.#.######.###.###.#.#.#.#....##.#######....##.#..####..##.#
+
..##.#..###...##....##.###.#.#.#....#..##..###..##..##..#.####..#....#.#.####..#..##.#..#....#..##.#
+
.#..#.#..##.###....#...####...##.##..#.#..##.##.##.###....##...##.....#.###......###..#.#..###....#.
+
###.#...#.##...####.#.##.###..#.....##.#.#...#.#..###.##..###.#..#.#.#.#.#####.#.####.##..####..##..
+
.....#.#..#.##...#..#.....#.###.##########.##.....#..####.##.##.###.##..#.##..#....#.#..##...###.#..
+
#..#.##.#.#.#..#....##########.###..#.#...#.##...#####..#..##..#..####.......###..#..#.###..###.##.#
+
###.#..##..##..####...#.####..##.######....#..#...#..##...#####.####.##.####...######..#..##...##..#
+
..##.#####...#.##..###...###.#......#.#.######.#...####.####.##.##....##..##.#.#..####.#####.######.
+
..##..#.#..###..#.....####..#.####.##.#.####.##.....####..##..#...###.#...###...#.#.#........##...#.
+
.#.###.##.##.#.##.##..#.#.###...##..#..#..#.##.#.#..##.#.#.#.##....##....#.#......#....#..#....##.#.
+
#####.#.###...###.#..#.##.###...###.##.##........#.###.#...##.###.#...###.##.##..#.##.###..####.###.
+
#....####.#..#.###....##.#.##..##.....#..#...#...##.#..#.#...#..##.#..##..######.##..####.##...#.#..
+
..#.#..#..##.##...##.###...#...###..#.##..#.#####..#.#.##.#######.##.#.#..##..####.....#####..#.#.##
+
#.#.....#.#.##.##.##.##......#...##.##.###..#...#.#........##....#.#.....#.##.###....#..###..#..#.##
+
..#.#.####..#.##...#.###.##....#.##.#########.###...##...##.#.#....#...#...##.....###.##.........#..
+
###.##.#.#...#...##...##...##.##.#..#.#....##.#.##..#..##.#.##.##..#.#.####.###.#.##.##....#.###.##.
+
###..#.######.#.###.##.###..##.#..######..###.....###......#.##..##..#.....##..##.##..#.#....##.##.#
+
..##.#....#.........##.##.#.#..####..##.#......#....#...##.#####..##........##....#.###...###.###..#
+
##...###.#.#..#.#..##.#.##.####....###....##.#####.##....#.##...##..#.....#....#...######..#.#...###
+
.##.##.#..###.#.###.#.#.###...####.##.#.#.#.####.#...####.##..###.#...##..##.####..###.#.#..##..##..
+
#..#...#####.##...#...##..###.#.#....#.#...#########..##.....##.#.#...###......#.##.########..#.##..
+
##..##.##.......##..##........###.#....#.####.#..#.#.###....#.#.#.#.###.#.#..##..##...##.#.....#....
+
....#..##...#####...##..#.###....##.##..##.#....#....#..#.#...#.#####...#..##.#.##...#.#...####...##
+
..##..####.##....#.###.####...###.#.##.##...#..##..#.###.###.#.#.######.#..#####......##..#.###.#.#.
+
#..#.#....#...###.#.#....##.###..#....##..####.#..#.#####.#.###.######...#..###.##..####.#...##.#..#
+
..#.##.##.#.##........#..##.....#.#.#.#.##.##..#..##...#.##...#...#.##.###..###.....##..#....#.#..##
+
###.##...##.#.#...##...####.###.#...####..###...#.##.#..#.#.###......#.#...###..#.####.##.#.#.####..
+
#.#.##.##...#..##..#....#.##..##......###..###...####..##...###.#.##.##..##...####.#.....#.##.##...#
+
.....#...#.##.#..#.##.#.####.#######......##.#..#...##..#...#.###.###.#.##.#.##..#.##.##.#..#.###..#
+
####...#####..##....##.#####...#...#...##.....##..###..#...###..#...#...##.###..###.#####...##.#....
+
#..###...###....#.#.#.######.###..####..#####...###..###..###....##.#.##..#.##..##..#.###.#####.....
+
#.#.##.#.####..#####.###.#..#####.#..#.#.#..#.##....##.#.#.#.#.###.###..###...#####.#.##.#.#.#..#...
+
.#.#...#..#.##.#..####..###.#..#.########.####......#...##..#####..#...#.#..###..#.#....####....#..#
+
##.###.###..#..##.#..#...#..####..#.###..##....#.#...######.##....##...#....#.........####.#.###.#..
+
.##..####.##.#.#..####...#.##..##.##..###...#.....##...#......#....##...#####..#####.#.#.#...#..##..
+
.#...##.#.###.#.#.##....###..###.##.#.##.....###.####.......#.#.#.#....##.#..#..#..#####..#....#.#.#
+
..#.##.###.###.................###.#...#...#.##.#.###..###..#..##..#.#..###..##.#.##.#.##.##.##.#...
+
###.#...#..#...###.......###.#.#..#####.####.#..#...##...#####..#........###.#..#.#######..####.#.##
+
...#.##.#####.#...##.###...##.#..#..##.##.##..#.#.#.#.###...#.##..#.##.##.#.#.##...##.###....#..#.##
+
##.#.####.##.#..#####.#.#...######.###.#.#.##.##...##.#.##.#..#...##.##.#..#...#..#..#..#..#.##.#...
+
#.#######.#..#.##..#..#.#..#..####....#.#..#..#...#.....####...#..#.......#..#...##..##.##.##..#.#..
+
..##.#.####.#.#.#......########..#..#.....###.#.####.#..#####.##..####.#.###....##.#.#..#.##..#####.
+
.##.#.##.#.#..#.#.#.#...#########...#####..#...###.#.##..##.#..##...###.##.#.#.#.#...####.#.#.####.#
+
.#####.####..##.##....#.#.#...######.#.#..#.#.#....#.#....##.#..#.###..#..#.####...###..##.#.#.#.#..
+
.##..#..###.######.#.#.#..######.##..#..#.######....###.##..#####.....####.#.#.#...##.###.#...##.##.
+
.#.####..##.#..#.#..#.###.##.#....##..#.#..#####.##.##...#..####..###..#........#.##..##.####...###.
+
..##..###.#.###.#...##.#.##.##.#######..##.#....#.####.#...####...####.###.##.##...##.#..#.#....#..#
+
.##..#.######..#.#.##.....######.#####......###.#....###.##.#.###.#..#.#.###.#.####...####.##.....##
+
.####....#.##.##.#.#....#.##.#..#...##.....#..##......#..#######..#.##.###.#..#.###.####..###.#.#..#
+
..#.##.#.#..##..####....#######.##...#.##.....#.#.##....#.###.#.#..#.###.#.....#.####.#.....##.#...#
+
##...#.##..##.#.........#..#..#######.##.#..###.#.###..#.##.#..#...#..#..#.##.##.#..###.###...##.##.
+
...#.#..###..#.##.#####.#.##...#.##..###.#...#...#.##....#####..#####....###..#.####.#...#.###.....#
+
..#.####..#..#.#..#.######...##.##...##...#.#.#.....#..#...##..#.############.###.####....###..###..
+
#.#...#.#.##..##..#.#..#...####.##.##.#.#.#.##..##.#.#.....#....#...#...#.###.#.#####..##.###...#..#
+
.#....#.##..###.#..#.###.#..#.#..##..##.......########.#...#...#####.#...#..#..##.....#.##.....####.
+
#.#####.#.##.###.#.#....#.#.###...##.#.....##..##..#.#####..#.#.##.#..###..##...#.#.##.#.#.....#.#..
+
..###...#.#.......#.#......##.#..#.#.#.#.#...#.###.##...####....######......#...#####..###.##...#..#
+
#..#...#..##..#...#...####.#...#....#####.#...#...#.#.....##...##..#...#....#..#####...#.....##...#.
+
#.####.#...#...#..##...##....#...#.#.##.##.##...##..##.#..#..#.##.##.##.#.##......#.#...##.....#...#
+
.#..####..###........#####...#....#.####..##..#####.##.###..#..###...##..##...##.....#..#.#.###.#...
+
.#....#.####....#....##..#.#.######.#######.#.##.###.###...#.#....##..#..####.###.#....###...#.#....
+
...###..##.#.##..#.#.#####.######.#..######.##...#.##.#..##.###.#.......#..#...#.###...##..####.##.#
+
#....###....#..#####.#..#...###..##.##...##.###...#...#....#..#...#..####.#.####...#..##....#...#.##
+
#.####.###...#..#.####...#..#.##.###.#.##.#....#..##.#.#...##.#..#.##.##..#####..#..#...###...#.####
+
#.##.##..##.##......#.#.##...###.####.###.####.#...##...#.#...###..###.######.#####....###.####.#...
+
##..#.###....#.#..###.#..##..###.#..##..#####.#.###..#.#...##.#.#.#.####....##...##....###.#.#.#..##
+
...#.###.###..###.##...#.###.#.####.##..#.#..###...#..##.######.#.#..###..#.##...##.###....##.#...#.
+
#..#.#..#.#..#.#.#.#.#..##..#....#..###.###.#...#.#####.#..#..#.#....#.#.#.#....##.##..#...##......#
+
...#...##....#....#.##.######.#...#.....#.##..#....#..##.#.........###..#..#..#.##.##...#.#..#######
+
##.##..#..#.#..#.#.######.##...####...#...#..#..##.#......#.#....#.###..#.###...#...#...#.##...###..
+
#.####.#.##....##..###....#.##.#.##....####.#.#.##.#....#..#..###...#.....##.##....####..###........
+
..#..##...##.#...#..#.#..###....##...#...####.....####....###..##..##..##.###..#.....######.........
+
.###.###.##.#...#.##..##.#.##.#.#..#.#..###.#....###.#..##.###....#...#####.###..###.####..#.#...##.
+
..##.#.#.####.#..#..###.##.#####.#.#....##..#.#.##..##..#...###.#...#...#...#...#..#..##.#...##...##
+
......###..#####...##..##.#.....###.#...#..###..####..##..#..#####..##..#..##..####.#..#.........#..
+
###............#.#.......###..#..##..#.#####.#.##.########.##..####.#.########..#.###.....#.####.#.#
+
.#.....#....##..#.##..#...#.#.##.##..#.##...#.##.#..#......##.....##..##.#..##.###...###....#.##.###
+
..#...###....##....#.#...###.###..##.##...#.#.#.#..#....###.#.##.....##.#..#.#######.#.###...###....
+
##.#.#.#.#...####.##..#.#####..######..#.#...#.#.........#....##.....#....#.###....#.#.#..#...##....
+
.......#.#.#..#....####.##.##.#.......#.#.###..#..#..#..##.#.#.##.#.##.#.#.#..##.#..###..#.###...##.
+
..##.#.#..##.##...#..#..#..#..###..#.##..#.##..#..#....#....#.##.##.###.##.###..##.......######.###.
+
##.#.#.#.#.#..###...###..####...##..##.###.#..#..####.#...###..#.##.##.#.#.###..###.#.#.#...###..#..
+
..##...####......##..#..#..#...#...#..##...######.##......#.#.#....#.#.#.#..#..##.#...#.########...#
+
####.##.#.#.####..#.#.##.#..#...#.#.##.#....#..#.####.#.#####.###..##.#.####...##.###.#.#....#.#####
+95
2021/day21.livemd
···
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 21
+
+
## Section
+
+
```elixir
+
input = File.read!("day21.txt")
+
+
[[_, p1], [_, p2]] = Regex.scan(~r/: (\d)/, input)
+
+
p1 = String.to_integer(p1)
+
p2 = String.to_integer(p2)
+
+
{p1, p2}
+
```
+
+
```output
+
{3, 5}
+
```
+
+
```elixir
+
round =
+
Stream.unfold(0, &{&1, &1 + 1})
+
|> Stream.scan({{0, p1}, {0, p2}}, fn n, {{s, p}, other} ->
+
p = rem(p - 1 + 6 + n * 9, 10) + 1
+
+
{other, {s + p, p}}
+
end)
+
|> Enum.take_while(fn {{s, _}, {_, _}} -> s < 1000 end)
+
+
{rounds, {{loser, _}, _}} = {length(round), List.last(round)}
+
+
rounds * 3 * loser
+
```
+
+
```output
+
720750
+
```
+
+
```elixir
+
defmodule Day21.Task2 do
+
def play(p1, p2) do
+
tid = :ets.new(__MODULE__, [])
+
{a, b} = cached_round({p1 - 1, 0}, {p2 - 1, 0}, tid)
+
:ets.delete(tid)
+
max(a, b)
+
end
+
+
defp cached_round(a, b, tid) do
+
case :ets.lookup(tid, {a, b}) do
+
[{_, v}] ->
+
v
+
+
[] ->
+
value = round(a, b, tid)
+
+
:ets.insert(tid, {{a, b}, value})
+
+
value
+
end
+
end
+
+
defp round({_, s}, _, _) when s >= 21, do: {1, 0}
+
defp round(_, {_, s}, _) when s >= 21, do: {0, 1}
+
+
defp round({pos, score}, p2, tid) do
+
for a <- 1..3, b <- 1..3, c <- 1..3, reduce: {0, 0} do
+
{wins1, wins2} ->
+
next = rem(pos + a + b + c, 10)
+
+
{nscore2, nscore1} =
+
cached_round(
+
p2,
+
{next, score + next + 1},
+
tid
+
)
+
+
{wins1 + nscore1, wins2 + nscore2}
+
end
+
end
+
end
+
```
+
+
```output
+
{:module, Day21.Task2, <<70, 79, 82, 49, 0, 0, 12, ...>>, {:round, 3}}
+
```
+
+
```elixir
+
Day21.Task2.play(p1, p2)
+
```
+
+
```output
+
275067741811212
+
```
+2
2021/day21.txt
···
+
Player 1 starting position: 3
+
Player 2 starting position: 5
+165
2021/day22.livemd
···
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 22
+
+
## Input
+
+
```elixir
+
input =
+
File.stream!("day22.txt")
+
|> Stream.map(&String.trim/1)
+
|> Stream.map(&String.split(&1, [" "]))
+
|> Enum.map(fn [action, rest] ->
+
{_, bindings} =
+
rest
+
|> String.replace(",", ";")
+
|> Code.eval_string()
+
+
{String.to_atom(action), Map.new(bindings)}
+
end)
+
```
+
+
```output
+
[
+
on: %{x: -40..7, y: -3..49, z: -48..6},
+
on: %{x: -38..10, y: -11..37, z: -30..19},
+
on: %{x: -43..1, y: -16..30, z: -38..13},
+
on: %{x: -10..44, y: -8..46, z: -41..4},
+
on: %{x: -27..19, y: -2..45, z: -33..12},
+
on: %{x: -41..4, y: -18..32, z: -34..19},
+
on: %{x: -43..9, y: -20..27, z: -34..20},
+
on: %{x: -47..-2, y: -5..49, z: -20..32},
+
on: %{x: -20..33, y: -40..6, z: -16..33},
+
on: %{x: -25..24, y: -47..-2, z: -46..6},
+
off: %{x: -28..-9, y: -6..4, z: 22..37},
+
on: %{x: -34..14, y: -16..32, z: -43..3},
+
off: %{x: -36..-18, y: -44..-33, z: 5..16},
+
on: %{x: -23..22, y: -34..11, z: -38..12},
+
off: %{x: -24..-15, y: 26..39, z: -18..-9},
+
on: %{x: -23..22, y: -31..20, z: -38..13},
+
off: %{x: -16..-6, y: 7..19, z: -44..-30},
+
on: %{x: -8..45, y: -18..28, z: -27..18},
+
off: %{x: -24..-8, y: -3..7, z: 33..45},
+
on: %{x: -28..18, y: -15..39, z: -18..35},
+
on: %{x: 52706..68579, y: -51721..-24984, z: -29134..-4745},
+
on: %{x: 19158..43390, y: 48482..62915, z: 36278..51760},
+
on: %{x: 33529..54535, y: 41410..44729, z: 35536..62066},
+
on: %{x: 39279..54831, y: -54196..-35294, z: -46321..-19146},
+
on: %{x: -49951..-33034, y: -75783..-65241, z: -32974..-9141},
+
on: %{x: 16267..33862, y: 32962..38520, z: 55102..80003},
+
on: %{x: 28231..33305, y: -13203..11551, z: -82121..-71765},
+
on: %{x: -3880..15012, y: -97354..-71276, z: -32509..-10704},
+
on: %{x: -59644..-43923, y: -56932..-39976, z: -46680..-24924},
+
on: %{x: -22171..6559, y: 59909..65127, z: 51012..71854},
+
on: %{x: -35278..-11377, y: -90913..-54535, z: 15441..29860},
+
on: %{x: 42440..47504, y: -77130..-54916, z: -5117..22780},
+
on: %{x: -23382..-925, y: -96268..-67199, z: -1408..16864},
+
on: %{x: 46073..66555, y: 2178..6843, z: -72379..-46993},
+
on: %{x: -7367..16256, y: 27822..35444, z: -81222..-57262},
+
on: %{x: 70121..85076, y: -2405..20765, z: -25162..-6383},
+
on: %{x: -38188..-8731, y: 303..24311, z: -85237..-74901},
+
on: %{x: 9308..35679, y: 72560..89334, z: -12862..6802},
+
on: %{x: 19088..20550, y: -54261..-29941, z: -66813..-56094},
+
on: %{x: 58563..67361, y: 32116..50251, z: -40547..-22471},
+
on: %{x: 63946..72885, y: -45525..-32975, z: 6297..33150},
+
on: %{x: 35523..45582, y: -46123..-39187, z: -62601..-55854},
+
on: %{x: -45263..-16076, y: 66141..71305, z: 24152..51511},
+
on: %{x: -56833..-39277, y: -61785..-39127, z: 20400..30866},
+
on: %{x: -64099..-47168, y: -14802..-10218, z: 59578..78286},
+
on: %{x: 54485..79540, y: -9884..13564, z: -33614..-29502},
+
on: %{x: -56136..-41543, y: 40175..50868, z: 18766..46233},
+
on: %{x: -29888..-22443, y: 56778..79471, ...},
+
on: %{x: 57940..83198, ...},
+
on: %{...},
+
...
+
]
+
```
+
+
## Implementation
+
+
```elixir
+
defmodule Day22 do
+
def volume(%{x: x, y: y, z: z}),
+
do: Range.size(x) * Range.size(y) * Range.size(z)
+
+
def volume(list), do: list |> Enum.map(&volume/1) |> Enum.sum()
+
+
def apply({action, new}, cuboids) do
+
cuboids = Enum.flat_map(cuboids, fn old -> sub(old, new) end)
+
+
case action do
+
:on -> [new | cuboids]
+
:off -> cuboids
+
end
+
end
+
+
defp sub(%{x: ax, y: ay, z: az} = a, %{x: bx, y: by, z: bz} = b) do
+
if overlap?(a, b) do
+
rx = split(ax, bx)
+
ry = split(ay, by)
+
rz = split(az, bz)
+
+
for x <- rx,
+
y <- ry,
+
z <- rz,
+
cube = cube(x, y, z),
+
overlap?(cube, a),
+
not overlap?(cube, b),
+
do: cube
+
else
+
[a]
+
end
+
end
+
+
defp overlap?(%{x: ax, y: ay, z: az}, %{x: bx, y: by, z: bz}) do
+
not (Range.disjoint?(ax, bx) or
+
Range.disjoint?(ay, by) or
+
Range.disjoint?(az, bz))
+
end
+
+
defp cube(x, y, z), do: %{x: x, y: y, z: z}
+
+
# `b` is "whithin" `a`
+
defp split(a1..a2, b1..b2) do
+
[
+
a1..(b1 - 1)//1,
+
max(a1, b1)..min(a2, b2)//1,
+
(min(a2, b2) + 1)..a2//1
+
]
+
|> Enum.reject(&(Range.size(&1) == 0))
+
end
+
end
+
```
+
+
```output
+
{:module, Day22, <<70, 79, 82, 49, 0, 0, 18, ...>>, {:split, 2}}
+
```
+
+
## Task 1
+
+
```elixir
+
range = -50..50
+
+
input
+
|> Enum.reject(fn {_, v} ->
+
Enum.any?(Map.values(v), &Range.disjoint?(&1, range))
+
end)
+
|> Enum.reduce([], &Day22.apply/2)
+
|> Day22.volume()
+
```
+
+
```output
+
556501
+
```
+
+
## Task 2
+
+
```elixir
+
input
+
|> Enum.reduce([], &Day22.apply/2)
+
|> Day22.volume()
+
```
+
+
```output
+
1217140271559773
+
```
+420
2021/day22.txt
···
+
on x=-40..7,y=-3..49,z=-48..6
+
on x=-38..10,y=-11..37,z=-30..19
+
on x=-43..1,y=-16..30,z=-38..13
+
on x=-10..44,y=-8..46,z=-41..4
+
on x=-27..19,y=-2..45,z=-33..12
+
on x=-41..4,y=-18..32,z=-34..19
+
on x=-43..9,y=-20..27,z=-34..20
+
on x=-47..-2,y=-5..49,z=-20..32
+
on x=-20..33,y=-40..6,z=-16..33
+
on x=-25..24,y=-47..-2,z=-46..6
+
off x=-28..-9,y=-6..4,z=22..37
+
on x=-34..14,y=-16..32,z=-43..3
+
off x=-36..-18,y=-44..-33,z=5..16
+
on x=-23..22,y=-34..11,z=-38..12
+
off x=-24..-15,y=26..39,z=-18..-9
+
on x=-23..22,y=-31..20,z=-38..13
+
off x=-16..-6,y=7..19,z=-44..-30
+
on x=-8..45,y=-18..28,z=-27..18
+
off x=-24..-8,y=-3..7,z=33..45
+
on x=-28..18,y=-15..39,z=-18..35
+
on x=52706..68579,y=-51721..-24984,z=-29134..-4745
+
on x=19158..43390,y=48482..62915,z=36278..51760
+
on x=33529..54535,y=41410..44729,z=35536..62066
+
on x=39279..54831,y=-54196..-35294,z=-46321..-19146
+
on x=-49951..-33034,y=-75783..-65241,z=-32974..-9141
+
on x=16267..33862,y=32962..38520,z=55102..80003
+
on x=28231..33305,y=-13203..11551,z=-82121..-71765
+
on x=-3880..15012,y=-97354..-71276,z=-32509..-10704
+
on x=-59644..-43923,y=-56932..-39976,z=-46680..-24924
+
on x=-22171..6559,y=59909..65127,z=51012..71854
+
on x=-35278..-11377,y=-90913..-54535,z=15441..29860
+
on x=42440..47504,y=-77130..-54916,z=-5117..22780
+
on x=-23382..-925,y=-96268..-67199,z=-1408..16864
+
on x=46073..66555,y=2178..6843,z=-72379..-46993
+
on x=-7367..16256,y=27822..35444,z=-81222..-57262
+
on x=70121..85076,y=-2405..20765,z=-25162..-6383
+
on x=-38188..-8731,y=303..24311,z=-85237..-74901
+
on x=9308..35679,y=72560..89334,z=-12862..6802
+
on x=19088..20550,y=-54261..-29941,z=-66813..-56094
+
on x=58563..67361,y=32116..50251,z=-40547..-22471
+
on x=63946..72885,y=-45525..-32975,z=6297..33150
+
on x=35523..45582,y=-46123..-39187,z=-62601..-55854
+
on x=-45263..-16076,y=66141..71305,z=24152..51511
+
on x=-56833..-39277,y=-61785..-39127,z=20400..30866
+
on x=-64099..-47168,y=-14802..-10218,z=59578..78286
+
on x=54485..79540,y=-9884..13564,z=-33614..-29502
+
on x=-56136..-41543,y=40175..50868,z=18766..46233
+
on x=-29888..-22443,y=56778..79471,z=19514..30387
+
on x=57940..83198,y=4819..24637,z=-36050..-14367
+
on x=-35953..-18054,y=-92305..-62464,z=-24944..433
+
on x=66547..83499,y=14135..24578,z=33083..41247
+
on x=23558..38387,y=64415..73072,z=-28114..-14640
+
on x=-13398..25438,y=-78327..-54021,z=32535..47622
+
on x=59279..70463,y=-48832..-12639,z=18768..30270
+
on x=-34289..-32327,y=35546..59245,z=55554..73170
+
on x=15715..29890,y=-84334..-64420,z=12788..32323
+
on x=-38593..-17951,y=-24585..-12831,z=-84437..-70981
+
on x=-81422..-51852,y=-44476..-32475,z=-32716..-22730
+
on x=-5856..25405,y=22130..39071,z=-84393..-56966
+
on x=5807..22366,y=-82846..-62290,z=17828..22587
+
on x=40912..63282,y=7257..37789,z=-67351..-34269
+
on x=-60312..-52700,y=17308..35727,z=32687..57593
+
on x=10748..21594,y=33001..48676,z=-71306..-63061
+
on x=-67665..-47017,y=-76167..-51735,z=-13297..-8021
+
on x=3312..26580,y=-35665..1379,z=-82617..-69610
+
on x=35278..52989,y=25977..48545,z=55789..71242
+
on x=17649..50914,y=-77065..-64303,z=-32515..-3058
+
on x=55174..70296,y=-63489..-51834,z=-20117..3614
+
on x=21633..36099,y=-56734..-43497,z=42283..51140
+
on x=32220..54369,y=48382..79084,z=-38669..-15641
+
on x=-41133..-21130,y=-43943..-12508,z=-72464..-67577
+
on x=1841..14519,y=34565..69226,z=58731..72943
+
on x=-81410..-71020,y=-41070..-11211,z=-25653..-2929
+
on x=54878..79738,y=37397..60247,z=-29325..-413
+
on x=-60358..-43018,y=-65054..-60356,z=991..20784
+
on x=-73582..-57508,y=31733..47988,z=-185..25415
+
on x=-8304..-1150,y=-81827..-65189,z=31671..57958
+
on x=-76108..-70108,y=20214..27537,z=-16291..3825
+
on x=15838..47053,y=-82389..-54043,z=3683..28928
+
on x=33142..48892,y=-69396..-53597,z=10868..36599
+
on x=-38048..-10804,y=-52011..-36488,z=51368..69373
+
on x=-4568..12859,y=-45556..-29570,z=-81370..-56776
+
on x=-16514..1528,y=-72602..-60172,z=-49767..-15535
+
on x=53082..91975,y=-5166..3133,z=22143..45433
+
on x=-88733..-57149,y=-41214..-19757,z=-22443..12286
+
on x=46893..68079,y=-50078..-29688,z=-39574..-23241
+
on x=-75085..-43624,y=16715..41482,z=-56327..-32898
+
on x=-76474..-45397,y=-64897..-52688,z=-20583..9143
+
on x=-19957..-2573,y=-59234..-31642,z=-79358..-61082
+
on x=26667..54887,y=-48864..-21382,z=47058..75678
+
on x=-44122..-16611,y=38155..71045,z=31473..49769
+
on x=-33391..-25134,y=-28005..-19241,z=51281..71668
+
on x=-87044..-63854,y=-23392..-7146,z=-2434..12126
+
on x=-591..19282,y=49600..86073,z=-55053..-37283
+
on x=-49830..-25077,y=45107..64739,z=-42830..-39577
+
on x=-11624..9796,y=-69135..-58118,z=-60400..-46121
+
on x=-45799..-24612,y=-62524..-47519,z=-37426..-28681
+
on x=34798..65120,y=26496..42571,z=41925..56566
+
on x=66112..68536,y=36258..50828,z=-1591..13570
+
on x=-15520..17879,y=72198..76196,z=23426..37175
+
on x=-39470..-24249,y=-82394..-63435,z=-20694..-7322
+
on x=-51300..-19607,y=23582..45094,z=49327..75939
+
on x=-40352..-26133,y=44295..65777,z=-60202..-38106
+
on x=3094..9439,y=-7619..7072,z=-94190..-71205
+
on x=70662..76847,y=32659..50544,z=-16957..-5542
+
on x=76282..96199,y=-26320..7056,z=-18269..10065
+
on x=-76248..-56030,y=23305..44186,z=-27243..-2017
+
on x=37045..57820,y=59279..72594,z=-5542..20408
+
on x=-44346..-20543,y=-87528..-58656,z=-35428..-2530
+
on x=37275..59953,y=-13753..2122,z=-74562..-53204
+
on x=52620..86557,y=23965..51715,z=-9509..-3827
+
on x=35795..63942,y=-46269..-22225,z=-54424..-31197
+
on x=-59544..-33767,y=9103..43984,z=-75618..-48873
+
on x=48874..58442,y=-77723..-42490,z=-14491..-11057
+
on x=37993..45421,y=60275..85636,z=-30638..4194
+
on x=54414..87440,y=7165..14487,z=21373..49667
+
on x=-31071..-8516,y=-63048..-54694,z=48010..53504
+
on x=37842..60715,y=-72053..-51698,z=-19271..-12587
+
on x=-44461..-12953,y=-33140..-19148,z=65167..75808
+
on x=-25510..2687,y=-55779..-24569,z=-69951..-46736
+
on x=-58173..-28520,y=-54375..-34513,z=-67610..-42556
+
on x=49497..80937,y=22263..43733,z=-42858..-17317
+
on x=-77801..-62492,y=-18176..-2842,z=16740..31884
+
on x=-40193..-19152,y=-32522..2707,z=-79663..-66600
+
on x=-50373..-23703,y=-46038..-12247,z=52074..71463
+
on x=52388..77469,y=-31867..-443,z=-50390..-36826
+
on x=-88034..-68737,y=-23143..-10464,z=-36065..-16663
+
on x=-65232..-53363,y=-17477..5073,z=38324..58181
+
on x=30925..53428,y=175..8144,z=57953..85443
+
on x=-49373..-38200,y=-311..6146,z=-77273..-48532
+
on x=32384..60171,y=53267..59287,z=12544..43012
+
on x=-48309..-24591,y=69828..73698,z=-21642..-5616
+
on x=-28570..-845,y=-24614..-5964,z=75229..91783
+
on x=-84432..-51564,y=-17335..-10501,z=-41225..-31395
+
on x=26592..43310,y=59225..62145,z=-45690..-22050
+
on x=4610..29014,y=65924..77350,z=-42917..-26623
+
on x=7145..20907,y=59641..72450,z=33512..51351
+
on x=-7362..2555,y=66424..85969,z=-34868..-15252
+
on x=-67112..-48950,y=-34742..-29850,z=33549..51770
+
on x=5116..24556,y=-77258..-53349,z=-59199..-49610
+
on x=-5223..12832,y=-85767..-62154,z=-63137..-25288
+
on x=-57402..-38394,y=23575..43849,z=49017..68715
+
on x=-5769..-3315,y=39128..68183,z=-71021..-52847
+
on x=6932..24244,y=30420..51629,z=55953..65526
+
on x=-29541..7458,y=-90145..-57044,z=-35054..-11576
+
on x=-10648..7954,y=-52949..-37015,z=51897..84477
+
on x=71634..87410,y=-20915..-15029,z=21564..38229
+
on x=-45805..-19490,y=-76458..-46791,z=13612..38412
+
on x=46952..72024,y=12007..31441,z=-64360..-43961
+
on x=-83434..-50243,y=-40251..-12284,z=10710..45032
+
on x=-84933..-68979,y=10644..21421,z=18662..43382
+
on x=41424..64670,y=49202..67746,z=-3488..24596
+
on x=-58317..-38261,y=25020..54489,z=-62333..-35139
+
on x=31402..52264,y=-39865..-3557,z=-61229..-45665
+
on x=11038..34450,y=-70660..-57200,z=23378..47844
+
on x=-61703..-48338,y=28118..53935,z=40276..44980
+
on x=-53403..-37172,y=-42771..-24798,z=44461..67302
+
on x=-6688..14480,y=75749..99074,z=-5417..6505
+
on x=5384..35432,y=-77335..-56400,z=-59871..-33791
+
on x=1603..24013,y=59386..75157,z=17493..37220
+
on x=16902..40265,y=20481..51075,z=-81132..-52892
+
on x=-31160..-5046,y=-92494..-74285,z=8537..12802
+
on x=-18183..-13833,y=13153..49953,z=66118..75643
+
on x=55672..76342,y=2135..27763,z=-45212..-19364
+
on x=35438..68301,y=43753..57908,z=-41226..-18528
+
on x=23646..35699,y=-76449..-53997,z=-21377..-14127
+
on x=-31654..-19008,y=18663..34709,z=-81288..-51590
+
on x=-76966..-59040,y=-46340..-22258,z=-5666..22990
+
on x=-31214..-20656,y=12464..42872,z=-86327..-52582
+
on x=21093..34180,y=-67130..-31862,z=44205..71945
+
on x=-68172..-49487,y=-62236..-47858,z=-31864..-4610
+
on x=13353..24199,y=66632..85682,z=-12135..20096
+
on x=-74820..-59297,y=-51864..-14460,z=-18528..3692
+
on x=-13545..3537,y=63598..83395,z=-31867..528
+
on x=-62438..-44176,y=-30526..3969,z=46663..68416
+
on x=22083..43728,y=2257..18901,z=54139..77885
+
on x=63102..90207,y=-36610..-21973,z=17017..37294
+
on x=-25513..-2920,y=-55321..-26346,z=-82595..-58662
+
on x=-59282..-47912,y=-22135..4940,z=-76370..-45984
+
on x=-46516..-37421,y=-40875..-30419,z=50078..67090
+
on x=247..17678,y=59666..73669,z=41161..66030
+
on x=41843..59744,y=-66781..-53325,z=-8026..-866
+
on x=56442..67337,y=31447..38104,z=15633..26441
+
on x=22246..52258,y=-33697..-12636,z=45175..80705
+
on x=25597..36312,y=1997..19204,z=-79738..-54986
+
on x=-15480..5974,y=-36965..-8946,z=72200..96085
+
on x=-44938..-16803,y=14179..37894,z=63576..70737
+
on x=-60563..-26278,y=35288..61821,z=28791..43958
+
on x=-2781..27047,y=-78181..-60658,z=7115..28869
+
on x=10325..34851,y=-48783..-28260,z=-85849..-67966
+
on x=-9545..5720,y=-66451..-53654,z=44770..66479
+
on x=-58489..-28712,y=44411..67195,z=-58310..-33840
+
on x=24722..34486,y=-67833..-40454,z=-67381..-40990
+
on x=58610..73788,y=-12225..7126,z=23646..51111
+
on x=-37164..-13729,y=62914..77209,z=11097..21143
+
on x=50156..70243,y=-47706..-13090,z=-39835..-13351
+
on x=76207..92507,y=-24144..7547,z=-2126..5790
+
on x=7817..31657,y=-55682..-32888,z=-81159..-52172
+
on x=71906..91201,y=12680..26262,z=3440..23272
+
on x=-38023..-4461,y=-83735..-46050,z=-56158..-38260
+
on x=-29161..-15540,y=-46665..-40319,z=57913..75651
+
on x=-21117..-9729,y=-29641..-21318,z=70665..79125
+
on x=-87374..-70709,y=-21190..-6753,z=-8554..26648
+
on x=18046..42722,y=48725..78913,z=-43262..-35039
+
on x=29634..46384,y=48479..70190,z=-54430..-25966
+
on x=49482..67130,y=-27612..-5693,z=32204..54616
+
on x=-18852..-12914,y=68426..76907,z=-30812..-26331
+
on x=31377..37346,y=22930..58293,z=-67913..-49831
+
on x=-39598..-27748,y=6896..20187,z=-73733..-67722
+
on x=27751..40846,y=44762..73826,z=25432..54560
+
on x=67176..86690,y=-29998..-10307,z=-42471..-11162
+
on x=-60642..-28188,y=-43985..-29075,z=-70335..-53311
+
on x=-23536..-1020,y=61753..77289,z=-65238..-29581
+
on x=-75390..-64417,y=5503..30410,z=-42131..-14557
+
on x=38542..53411,y=-59214..-34215,z=40608..53343
+
on x=-9650..8906,y=-28406..3212,z=-82649..-62885
+
on x=-2849..20704,y=-5170..17802,z=-79401..-74877
+
on x=-56789..-34867,y=12504..18099,z=-63987..-57513
+
on x=-42510..-29442,y=60034..69734,z=30430..48273
+
on x=40496..64946,y=5792..10312,z=45679..68128
+
off x=36887..57526,y=47538..63530,z=-42985..-28341
+
off x=33479..58411,y=-68548..-46527,z=13251..39103
+
on x=63072..81417,y=15646..49394,z=21504..45148
+
off x=-76216..-61912,y=-30534..-17551,z=-50280..-26222
+
off x=25878..59914,y=-64350..-36188,z=27874..39360
+
on x=-51496..-46945,y=-5396..29398,z=-78407..-50985
+
off x=-68762..-50445,y=33207..52061,z=-42617..-15847
+
off x=-45658..-24730,y=-13226..12659,z=57392..77206
+
on x=-8068..23761,y=-48399..-28155,z=50498..71412
+
on x=16850..27765,y=-77260..-62223,z=-47859..-28554
+
on x=-24227..-1152,y=60223..84591,z=-28685..-1888
+
on x=-83203..-60907,y=-38213..-1290,z=-19771..-3635
+
off x=22050..29566,y=-55088..-28774,z=-82502..-48350
+
off x=55602..73932,y=30508..60779,z=-18418..563
+
on x=18396..43696,y=48295..65403,z=-50879..-28862
+
off x=58964..95810,y=5076..9444,z=-15462..-7722
+
off x=65419..97082,y=-12404..4511,z=-19581..3679
+
off x=58822..78853,y=-31174..-6818,z=-32926..-19059
+
off x=2312..14918,y=-14468..-8421,z=-82159..-63347
+
off x=-8615..6715,y=-34749..-9928,z=-85890..-73180
+
on x=10021..28727,y=60507..75964,z=-46068..-16944
+
on x=47209..85189,y=-33718..-120,z=-50448..-29027
+
off x=-69679..-64804,y=-62936..-27943,z=-6028..3121
+
on x=11568..38288,y=-77218..-72840,z=-1658..28856
+
off x=68949..83664,y=-11073..17816,z=29484..47100
+
on x=-42138..-25168,y=22944..40683,z=45644..72158
+
off x=-54212..-23198,y=54848..84031,z=-34752..-8583
+
off x=-61743..-43915,y=-62636..-51044,z=-40084..-19481
+
off x=-58593..-36205,y=-53837..-28785,z=34877..51154
+
on x=-29140..-7627,y=-81905..-73121,z=714..9303
+
off x=-70736..-46090,y=-53884..-41570,z=-23826..-13883
+
on x=64926..88584,y=-32881..-6387,z=18988..43795
+
on x=33758..45337,y=-41289..-13923,z=66720..86882
+
off x=67177..85594,y=-1270..27149,z=-12298..10562
+
on x=-30728..-9677,y=-80101..-71392,z=-7737..6045
+
on x=-34058..-11169,y=-84130..-59611,z=-2411..25556
+
on x=-82888..-45532,y=-53498..-43399,z=-15466..12569
+
on x=53096..73732,y=-31292..-271,z=46937..54564
+
off x=58806..72491,y=-35114..-15573,z=-32393..-15887
+
on x=-32570..-20445,y=-70056..-55586,z=15130..43528
+
off x=8231..26748,y=-52110..-30753,z=-83079..-61762
+
on x=-7168..18004,y=-85219..-76351,z=-55..15553
+
on x=-48759..-17822,y=56514..81093,z=-17816..-268
+
off x=71494..89379,y=-20577..5421,z=-16229..3599
+
on x=-74127..-61857,y=-37318..-16386,z=23418..48020
+
off x=46250..64727,y=39997..55663,z=-659..22759
+
on x=-3747..18906,y=-88542..-51288,z=-50866..-25393
+
on x=11967..39179,y=-42409..-27075,z=51760..78913
+
off x=32634..54583,y=53351..78683,z=37069..52980
+
on x=-45801..-34391,y=6739..35543,z=-80719..-61475
+
off x=-59939..-43493,y=-2816..19380,z=43062..76353
+
on x=-54552..-45916,y=30463..59717,z=-60676..-40687
+
off x=947..37295,y=17259..35699,z=-77711..-57213
+
on x=-34155..-16112,y=58205..77747,z=10469..35078
+
off x=-41364..-24954,y=-55475..-20679,z=53974..74195
+
on x=-5866..6658,y=-10037..4333,z=69763..93051
+
off x=40058..68698,y=51027..74309,z=-3345..5414
+
on x=-41513..-26098,y=-47848..-29818,z=44033..62222
+
off x=-68876..-57248,y=30233..44005,z=21522..38471
+
on x=-10503..7050,y=-33479..-26016,z=-81965..-69000
+
on x=-63996..-35550,y=23827..38930,z=50227..78098
+
on x=-34663..-17363,y=57015..82338,z=-32869..-17105
+
on x=30784..51645,y=32138..66808,z=31941..61168
+
off x=-3755..2895,y=-64141..-57971,z=36971..58497
+
on x=-20087..3384,y=-63838..-35555,z=57392..69703
+
on x=-86557..-54970,y=14861..40412,z=27350..36531
+
on x=15258..32146,y=26537..42919,z=65823..68594
+
off x=13862..42242,y=-84456..-71150,z=-13132..5905
+
off x=-42982..-21849,y=-73917..-48154,z=21993..50847
+
on x=-29379..-7101,y=29242..38662,z=-79142..-60459
+
off x=11546..49500,y=61301..86969,z=-22865..4577
+
on x=-48399..-37677,y=60118..82209,z=-25376..-6657
+
on x=-57062..-36839,y=-59454..-56603,z=13677..38428
+
off x=-34067..-21168,y=-81243..-56765,z=-17444..3822
+
off x=44352..64136,y=50950..67304,z=1643..23339
+
off x=64615..79759,y=19545..29449,z=-24935..-16190
+
off x=25709..39422,y=-76035..-66047,z=-30123..3414
+
on x=-66361..-38785,y=-60420..-53479,z=13651..34601
+
on x=26547..53719,y=25778..42415,z=-71893..-46470
+
off x=35485..64687,y=32129..59334,z=31017..53502
+
off x=-27532..-16323,y=42528..53056,z=44767..66976
+
off x=-85657..-60092,y=-4500..16282,z=25434..42820
+
on x=10591..32952,y=-55737..-51910,z=45939..63149
+
off x=37813..46415,y=-23900..-17178,z=-86629..-47985
+
on x=-73010..-52678,y=21009..53737,z=11818..30585
+
on x=54601..63218,y=-64449..-41296,z=-8460..15915
+
on x=-16576..-10827,y=4232..34251,z=-81741..-62897
+
on x=67542..81394,y=-5704..24443,z=-36781..-3582
+
on x=-10656..21150,y=-13060..12841,z=-92317..-74508
+
on x=-64593..-54055,y=38045..53878,z=-46825..-28151
+
off x=36627..44665,y=-34351..-5917,z=-85072..-68088
+
off x=-23261..-5824,y=-22196..13929,z=57375..80182
+
off x=-32414..-14305,y=-83945..-60848,z=-17901..-6229
+
off x=-69199..-45106,y=-35361..-11117,z=47106..48416
+
on x=-17361..309,y=-87112..-75083,z=-17309..-846
+
on x=49576..70268,y=-52965..-28866,z=-33749..-13320
+
off x=-84872..-60225,y=21104..41143,z=-33952..253
+
off x=25065..53172,y=-74764..-50642,z=-27008..-12427
+
on x=5466..28561,y=58871..87353,z=3407..31099
+
off x=58159..69905,y=1719..21038,z=-56660..-32952
+
on x=49812..75324,y=42397..58595,z=10501..19992
+
off x=-28176..-5545,y=-4561..10768,z=66184..83235
+
on x=-36512..-16357,y=6529..33157,z=61540..79962
+
on x=-76835..-51187,y=23689..47550,z=26996..57187
+
on x=15920..39818,y=-73996..-51623,z=-40686..-18624
+
on x=74449..92921,y=-30516..-17926,z=6351..21131
+
off x=-36036..-18588,y=66163..82239,z=12845..17683
+
on x=-58293..-40285,y=41167..63632,z=5699..26703
+
off x=55508..80984,y=411..28348,z=45931..48884
+
on x=36567..70716,y=-64313..-46937,z=19533..31078
+
on x=57973..76789,y=640..32503,z=-46928..-15585
+
on x=40700..59637,y=58372..73306,z=-34813..-17979
+
on x=-35809..-16448,y=14279..36807,z=59850..75883
+
off x=-11980..15927,y=71172..89369,z=27605..44939
+
off x=-28383..-12868,y=-49010..-14693,z=67766..71069
+
on x=-63520..-57313,y=-65070..-41322,z=7548..28820
+
off x=-30097..-9794,y=50203..76545,z=-47190..-22675
+
on x=-10027..13876,y=42660..67586,z=-62549..-45351
+
off x=-75743..-41761,y=-18063..-8438,z=43896..51143
+
on x=-53973..-21852,y=19812..35895,z=-65245..-53623
+
on x=9327..30980,y=60724..81052,z=4679..22655
+
on x=-9382..14696,y=-12635..-7880,z=-92088..-71928
+
on x=-49568..-21303,y=45400..66270,z=-37218..-23585
+
on x=26374..50716,y=29522..45024,z=-72113..-50858
+
off x=-7123..9906,y=-30606..-21570,z=-89692..-60367
+
off x=24645..34685,y=-7385..-535,z=-75457..-69280
+
off x=46600..75937,y=42638..62019,z=-15214..-800
+
off x=-73156..-64899,y=-18542..6622,z=-51976..-33625
+
on x=-46953..-31989,y=-43453..-17942,z=48050..68549
+
off x=44491..64439,y=-52270..-47527,z=25565..42399
+
on x=54480..85695,y=-56683..-30655,z=-8303..15795
+
on x=29997..57709,y=62586..84888,z=-22633..2635
+
on x=-56730..-33262,y=-61124..-36167,z=-44900..-31218
+
on x=-36099..-17509,y=59225..80566,z=-49431..-28644
+
on x=45514..74203,y=-2009..10424,z=-65113..-45173
+
off x=-31309..-22150,y=-84143..-63111,z=26691..48979
+
off x=-68448..-52444,y=-49282..-47076,z=-6567..21766
+
on x=9190..23305,y=-40030..-24391,z=56198..85303
+
off x=5498..22227,y=-43923..-15355,z=-85770..-69241
+
off x=-61505..-41086,y=34956..58168,z=-43349..-24183
+
on x=-458..11929,y=14735..44319,z=60006..73064
+
off x=54250..68185,y=-71222..-34674,z=-28518..-15694
+
off x=-28528..42,y=-45762..-25317,z=64430..72231
+
off x=17184..32440,y=-43934..-25096,z=-75789..-65047
+
on x=-54107..-45535,y=-647..29416,z=56621..66738
+
on x=-63306..-50383,y=-54815..-51798,z=3488..23514
+
off x=-33064..-17821,y=-68795..-40276,z=48722..58281
+
off x=28813..45569,y=10091..43242,z=48567..79748
+
on x=-34407..-13658,y=-82959..-67725,z=-14721..-7549
+
off x=11006..38914,y=-64578..-54646,z=31394..48188
+
on x=-89516..-56035,y=-33338..-20011,z=23842..40221
+
on x=12382..42662,y=51972..71326,z=-51009..-29545
+
on x=-23497..-510,y=-14057..6559,z=-82664..-61835
+
off x=42738..44332,y=-45357..-25100,z=44137..62767
+
off x=-19799..9546,y=-63709..-45750,z=48687..64170
+
off x=-50529..-30472,y=-47930..-19905,z=-75205..-45624
+
off x=-23531..14033,y=68487..89564,z=8925..28259
+
on x=1663..20113,y=56791..75346,z=12276..44119
+
off x=45731..75170,y=-23286..393,z=-64525..-28621
+
on x=-78486..-56778,y=-31099..-18591,z=-48346..-25135
+
on x=-43514..-34754,y=67709..72495,z=-16374..5180
+
off x=32961..61842,y=-62894..-41340,z=-33931..-15049
+
on x=-52937..-36075,y=64942..83439,z=-3622..27175
+
off x=41640..61376,y=-70913..-50192,z=-23373..-12724
+
on x=16109..24715,y=-19443..8667,z=75001..90517
+
off x=14880..41615,y=37677..55218,z=-64590..-40070
+
off x=-93344..-73236,y=-27796..-24908,z=-10127..16501
+
off x=59960..65418,y=-4002..12224,z=-67984..-42193
+
on x=42351..56746,y=-20084..-13129,z=-65765..-51230
+
off x=-59234..-29355,y=-71438..-58469,z=-11162..7404
+
on x=51040..67401,y=-60224..-40198,z=-546..19625
+
on x=-77978..-59874,y=36001..58307,z=14976..23796
+
off x=56211..75341,y=8311..17708,z=-53749..-20735
+
on x=-36432..-7183,y=19575..30346,z=-86318..-58459
+
off x=-287..4588,y=-90791..-66459,z=-21768..4012
+
off x=-79379..-62831,y=-31440..-593,z=-17403..8089
+
off x=-35905..-18333,y=29389..56106,z=42947..70271
+
off x=25117..47923,y=3093..37238,z=-77359..-65332
+
on x=56769..88321,y=-37074..-5686,z=-21787..-6401
+
on x=-28981..-10417,y=28580..52377,z=-77998..-54458
+
off x=-24957..-267,y=35439..53345,z=51302..86849
+
off x=-47011..-30673,y=-6746..-378,z=65710..79497
+
off x=-73026..-58387,y=-27117..-1079,z=-58305..-36042
+
off x=-20512..4246,y=45491..71174,z=48277..50414
+
on x=23379..43354,y=63961..93513,z=3964..25213
+
off x=597..17616,y=-83653..-72150,z=-11879..21798
+
off x=-58597..-46587,y=12126..39528,z=-75993..-36792
+
on x=-2903..11768,y=72176..88526,z=23687..33143
+
on x=12525..24278,y=-2148..6961,z=59625..82181
+
on x=-84588..-72500,y=-29471..-14022,z=-16989..13434
+
off x=-58154..-34165,y=-74940..-54914,z=12160..19819
+
off x=-6724..14627,y=22646..53365,z=-88495..-61533
+
on x=-87262..-70236,y=-23648..3813,z=11206..27547
+
on x=53546..71522,y=-28908..-8027,z=46725..60604
+
on x=-81664..-64558,y=-26054..-6136,z=-43138..-11228
+
off x=74496..91204,y=1367..9913,z=-2108..16186
+
on x=-69821..-39879,y=-4418..23997,z=-65231..-50478
+
off x=6104..33203,y=65171..78461,z=26193..44937
+
off x=-4928..16268,y=50554..71798,z=-66020..-34009
+
off x=22174..43968,y=-69871..-46557,z=-37898..-23874
+90
2021/day3.livemd
···
+
<!-- vim:ft=markdown
+
-->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 3
+
+
## Input
+
+
```elixir
+
stream =
+
File.stream!("day3.txt")
+
|> Enum.map(&String.trim/1)
+
|> Enum.map(&String.to_charlist/1)
+
+
defmodule Day3 do
+
def count(list) do
+
Enum.reduce(list, List.duplicate(0, 12), fn input, acc ->
+
for {value, counter} <- Enum.zip(input, acc) do
+
case value do
+
?1 -> counter + 1
+
?0 -> counter
+
end
+
end
+
end)
+
end
+
end
+
```
+
+
```output
+
{:module, Day3, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:count, 1}}
+
```
+
+
## Task 1
+
+
```elixir
+
half = div(length(stream), 2)
+
+
{a, b} =
+
stream
+
|> Day3.count()
+
|> Enum.reduce({0, 0}, fn elem, {a, b} ->
+
if elem > half do
+
{a * 2 + 1, b * 2}
+
else
+
{a * 2, b * 2 + 1}
+
end
+
end)
+
+
a * b
+
```
+
+
```output
+
3847100
+
```
+
+
## Task 2
+
+
```elixir
+
defmodule Day3.Task2 do
+
def reduce(list, cb), do: reduce(list, 0, cb)
+
+
defp reduce([elem], _, _), do: elem
+
+
defp reduce(list, at, cb) do
+
counts = Day3.count(list)
+
+
half = div(length(list), 2)
+
count = Enum.at(counts, at)
+
+
bit =
+
cond do
+
count == half and cb.(count + 1, half) -> ?1
+
count != half and cb.(count, half) -> ?1
+
true -> ?0
+
end
+
+
reduce(Enum.filter(list, &(Enum.at(&1, at) == bit)), at + 1, cb)
+
end
+
end
+
+
co2 = List.to_integer(Day3.Task2.reduce(stream, &</2), 2)
+
o2 = List.to_integer(Day3.Task2.reduce(stream, &>/2), 2)
+
+
co2 * o2
+
```
+
+
```output
+
4105235
+
```
+126
2021/day4.livemd
···
+
<!-- vim:ft=markdown
+
-->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 4
+
+
## Input
+
+
This time it is a little bit more convoluted, as there are 2 parts of the input.
+
Fortunately we can easily disect the parts via pattern matching.
+
+
Technically the conversion to the numbers is not needed, but it does no harm
+
and provides additional layer of safety against some whitespace characters left there
+
and here.
+
+
The `Day4.win/2` function is manually unrolled, as it is easier to write than some
+
random jumping in the list.
+
+
<!-- livebook:{"disable_formatting":true} -->
+
+
```elixir
+
[numbers | bingos] =
+
File.read!("day4.txt")
+
|> String.split("\n\n", trim: true)
+
+
numbers =
+
numbers
+
|> String.trim()
+
|> String.split(",")
+
|> Enum.map(&String.to_integer/1)
+
+
bingos =
+
bingos
+
|> Enum.map(fn bingo ->
+
bingo
+
|> String.split(~r/\s+/, trim: true)
+
|> Enum.map(&String.to_integer/1)
+
end)
+
+
defmodule Day4 do
+
def win(
+
[
+
a1, a2, a3, a4, a5,
+
b1, b2, b3, b4, b5,
+
c1, c2, c3, c4, c5,
+
d1, d2, d3, d4, d5,
+
e1, e2, e3, e4, e5
+
],
+
nums
+
) do
+
# Rows
+
all_in([a1, a2, a3, a4, a5], nums) or
+
all_in([b1, b3, b3, b4, b5], nums) or
+
all_in([c1, c2, c3, c4, c5], nums) or
+
all_in([d1, d2, d3, d4, d5], nums) or
+
all_in([e1, e2, e3, e4, e5], nums) or
+
# Columns
+
all_in([a1, b1, c1, d1, e1], nums) or
+
all_in([a2, b2, c2, d2, e2], nums) or
+
all_in([a3, b3, c3, d3, e3], nums) or
+
all_in([a4, b4, c4, d4, e4], nums) or
+
all_in([a5, b5, c5, d5, e5], nums)
+
end
+
+
def not_matched(bingo, nums) do
+
Enum.reject(bingo, &(&1 in nums))
+
end
+
+
defp all_in(list, nums) do
+
Enum.all?(list, &(&1 in nums))
+
end
+
end
+
```
+
+
```output
+
{:module, Day4, <<70, 79, 82, 49, 0, 0, 15, ...>>, {:all_in, 2}}
+
```
+
+
## Task 1
+
+
We simply traverse the `numbers` list aggregating the numbers (order doesn't really matter,
+
here we aggregate them in reverse order to speedup the code). When we have enough numbers
+
that any of the `bingos` is winning one, then we halt the reduction and return computed
+
result.
+
+
```elixir
+
numbers
+
|> Enum.reduce_while([], fn elem, acc ->
+
matches = [elem | acc]
+
+
case Enum.find(bingos, &Day4.win(&1, matches)) do
+
nil -> {:cont, matches}
+
bingo -> {:halt, Enum.sum(Day4.not_matched(bingo, matches)) * elem}
+
end
+
end)
+
```
+
+
```output
+
34506
+
```
+
+
## Task 2
+
+
```elixir
+
numbers
+
|> Enum.reduce_while({bingos, []}, fn elem, {bingos, acc} ->
+
matches = [elem | acc]
+
+
case bingos do
+
[bingo] ->
+
if Day4.win(bingo, matches) do
+
{:halt, Enum.sum(Day4.not_matched(bingo, matches)) * elem}
+
else
+
{:cont, {bingos, matches}}
+
end
+
+
_ ->
+
{:cont, {Enum.reject(bingos, &Day4.win(&1, matches)), matches}}
+
end
+
end)
+
```
+
+
```output
+
7686
+
```
+109
2021/day5.livemd
···
+
<!-- vim:ft=markdown
+
-->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 5
+
+
```elixir
+
defmodule Day5 do
+
defmodule Point do
+
defstruct [:x, :y]
+
+
def parse(input) do
+
[x, y] = String.split(input, ",")
+
+
%__MODULE__{x: String.to_integer(x), y: String.to_integer(y)}
+
end
+
end
+
+
defmodule Line do
+
defstruct [:start, :finish]
+
+
def new(a, b) do
+
{start, finish} =
+
cond do
+
a.x < b.x -> {a, b}
+
a.y < b.y -> {a, b}
+
true -> {b, a}
+
end
+
+
%__MODULE__{start: start, finish: finish}
+
end
+
+
def horizontal?(a), do: a.start.y == a.finish.y
+
def vertical?(a), do: a.start.x == a.finish.x
+
+
def points(a) do
+
case {sign(a.finish.x - a.start.x), sign(a.finish.y - a.start.y)} do
+
{0, dy} -> for y <- a.start.y..a.finish.y//dy, do: {a.start.x, y}
+
{dx, 0} -> for x <- a.start.x..a.finish.x//dx, do: {x, a.start.y}
+
{dx, dy} -> Enum.zip(a.start.x..a.finish.x//dx, a.start.y..a.finish.y//dy)
+
end
+
end
+
+
def orientation(a) do
+
cond do
+
horizontal?(a) -> :horizontal
+
vertical?(a) -> :vertical
+
true -> :diagonal
+
end
+
end
+
+
defp sign(0), do: 0
+
defp sign(x) when x < 0, do: -1
+
defp sign(x) when x > 0, do: 1
+
end
+
end
+
+
lines =
+
File.stream!("day5.txt")
+
|> Stream.map(&String.trim/1)
+
|> Stream.map(fn input ->
+
[a, b] = String.split(input, " -> ")
+
+
pa = Day5.Point.parse(a)
+
pb = Day5.Point.parse(b)
+
+
Day5.Line.new(pa, pb)
+
end)
+
```
+
+
```output
+
#Stream<[
+
enum: %File.Stream{
+
line_or_bytes: :line,
+
modes: [:raw, :read_ahead, :binary],
+
path: "day5.txt",
+
raw: true
+
},
+
funs: [#Function<47.58486609/1 in Stream.map/2>, #Function<47.58486609/1 in Stream.map/2>]
+
]>
+
```
+
+
## Task 1
+
+
```elixir
+
lines
+
|> Stream.filter(&(Day5.Line.orientation(&1) != :diagonal))
+
|> Stream.flat_map(&Day5.Line.points/1)
+
|> Enum.frequencies()
+
|> Enum.count(fn {_k, v} -> v > 1 end)
+
```
+
+
```output
+
5197
+
```
+
+
## Task 2
+
+
```elixir
+
lines
+
|> Stream.flat_map(&Day5.Line.points/1)
+
|> Enum.frequencies()
+
|> Enum.count(fn {_k, v} -> v > 1 end)
+
```
+
+
```output
+
18605
+
```
+57
2021/day6.livemd
···
+
<!-- vim:ft=markdown -->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 6
+
+
## Section
+
+
```elixir
+
initial = for i <- 0..8, into: %{}, do: {i, 0}
+
+
counts =
+
File.read!("day6.txt")
+
|> String.trim()
+
|> String.split(",")
+
|> Enum.map(&String.to_integer/1)
+
|> Enum.frequencies()
+
|> Map.merge(initial, fn _, a, _ -> a end)
+
+
defmodule Day6 do
+
def next(%{0 => next} = population) do
+
1..8
+
|> Map.new(&{&1 - 1, population[&1]})
+
|> Map.merge(%{6 => next, 8 => next}, fn _, v1, v2 -> v1 + v2 end)
+
end
+
end
+
```
+
+
```output
+
{:module, Day6, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:next, 1}}
+
```
+
+
## Task 1
+
+
```elixir
+
1..80
+
|> Enum.reduce(counts, fn _, acc -> Day6.next(acc) end)
+
|> Map.values()
+
|> Enum.sum()
+
```
+
+
```output
+
343441
+
```
+
+
## Task 2
+
+
```elixir
+
1..256
+
|> Enum.reduce(counts, fn _, acc -> Day6.next(acc) end)
+
|> Map.values()
+
|> Enum.sum()
+
```
+
+
```output
+
1569108373832
+
```
+56
2021/day7.livemd
···
+
<!-- vim:ft=markdown
+
-->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 7
+
+
```elixir
+
input =
+
File.read!("day7.txt")
+
|> String.trim()
+
|> String.split(",")
+
|> Enum.map(&String.to_integer/1)
+
```
+
+
```output
+
[1101, 1, 29, 67, 1102, 0, 1, 65, 1008, 65, 35, 66, 1005, 66, 28, 1, 67, 65, 20, 4, 0, 1001, 65, 1,
+
65, 1106, 0, 8, 99, 35, 67, 101, 99, 105, 32, 110, 39, 101, 115, 116, 32, 112, 97, 115, 32, 117,
+
110, 101, 32, 105, ...]
+
```
+
+
## Task 1
+
+
```elixir
+
median = Enum.at(Enum.sort(input), div(length(input), 2))
+
+
input
+
|> Enum.map(&abs(&1 - median))
+
|> Enum.sum()
+
```
+
+
```output
+
336721
+
```
+
+
## Task 2
+
+
```elixir
+
arith_sum = fn n -> div(n * n + n, 2) end
+
+
max = Enum.max(input)
+
+
mean = Enum.sum(input) / length(input)
+
+
[floor(mean), ceil(mean)]
+
|> Enum.map(fn n ->
+
input
+
|> Enum.map(&arith_sum.(abs(&1 - n)))
+
|> Enum.sum()
+
end)
+
|> Enum.min()
+
```
+
+
```output
+
91638945
+
```
+141
2021/day8.livemd
···
+
<!-- vim:ft=markdown
+
-->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 8
+
+
```elixir
+
input =
+
File.stream!("day8.txt")
+
|> Stream.map(fn line ->
+
line
+
|> String.split(" | ")
+
|> Enum.map(fn part ->
+
part
+
|> String.trim()
+
|> String.split(" ")
+
|> Enum.map(fn disp ->
+
# Sort characters in each entry to simplify later work
+
disp
+
|> String.to_charlist()
+
|> Enum.sort()
+
|> List.to_string()
+
end)
+
end)
+
|> List.to_tuple()
+
end)
+
```
+
+
```output
+
#Stream<[
+
enum: %File.Stream{
+
line_or_bytes: :line,
+
modes: [:raw, :read_ahead, :binary],
+
path: "day8.txt",
+
raw: true
+
},
+
funs: [#Function<47.58486609/1 in Stream.map/2>]
+
]>
+
```
+
+
## Task 1
+
+
We simply need to count all occurences of the values that have 2, 3, 4, or 7 highlighted
+
segments.
+
+
```elixir
+
input
+
|> Enum.map(fn {_, output} ->
+
Enum.count(output, &(byte_size(&1) in [2, 3, 4, 7]))
+
end)
+
|> Enum.sum()
+
```
+
+
```output
+
390
+
```
+
+
## Task 2
+
+
```elixir
+
defmodule Day8.Task2 do
+
defp a --- b, do: MapSet.difference(a, b)
+
+
defp a +++ b, do: MapSet.union(a, b)
+
+
defp a <~> b, do: MapSet.intersection(a, b)
+
+
# 1. 7. 4. 2|3|5. 2|3|5. 2|3|5. 6|9|0. 6|9|0. 6|9|0. 8.
+
def deduce([cf, acf, bcdf, acdeg, acdfg, abdfg, abdefg, abcdfg, abcefg, abcdefg]) do
+
eg = abcdefg --- (acf +++ bcdf)
+
bd = bcdf --- cf
+
adg = acdeg <~> acdfg <~> abdfg
+
abfg = abdefg <~> abcdfg <~> abcefg
+
a = acf --- cf
+
b = abfg <~> bd
+
f = abfg <~> cf
+
g = adg <~> eg
+
d = adg <~> bd
+
c = cf --- f
+
e = eg --- g
+
+
[a, b, c, d, e, f, g] =
+
[a, b, c, d, e, f, g]
+
|> Enum.map(&extract/1)
+
+
[
+
# 0
+
[a, b, c, e, f, g],
+
# 1
+
[c, f],
+
# 2
+
[a, c, d, e, g],
+
# 3
+
[a, c, d, f, g],
+
# 4
+
[b, c, d, f],
+
# 5
+
[a, b, d, f, g],
+
# 6
+
[a, b, d, e, f, g],
+
# 7
+
[a, c, f],
+
# 8
+
[a, b, c, d, e, f, g],
+
# 9
+
[a, b, c, d, f, g]
+
]
+
|> Enum.map(&List.to_string(Enum.sort(&1)))
+
|> Enum.with_index()
+
|> Map.new()
+
end
+
+
defp extract(a) do
+
# Just additional sanity check
+
[v] = MapSet.to_list(a)
+
+
v
+
end
+
+
def decode(matches, output) do
+
output
+
|> Enum.map(&matches[&1])
+
|> Integer.undigits()
+
end
+
end
+
+
input
+
|> Enum.map(fn {input, output} ->
+
input
+
|> Enum.sort_by(&byte_size/1)
+
|> Enum.map(&MapSet.new(String.to_charlist(&1)))
+
|> Day8.Task2.deduce()
+
|> Day8.Task2.decode(output)
+
end)
+
|> Enum.sum()
+
```
+
+
```output
+
1011785
+
```
+114
2021/day9.livemd
···
+
<!-- vim:ft=markdown
+
-->
+
+
<!-- livebook:{"persist_outputs":true} -->
+
+
+
# Day 9
+
+
## Setup
+
+
```elixir
+
Mix.install([
+
{:nx, github: "elixir-nx/nx", sparse: "nx"},
+
{:kino, github: "livebook-dev/kino"}
+
])
+
```
+
+
```output
+
:ok
+
```
+
+
## Input
+
+
```elixir
+
input =
+
File.read!("day9.txt")
+
|> String.split("\n", trim: true)
+
|> Enum.map(&String.to_charlist(String.trim(&1)))
+
|> Nx.tensor(names: [:y, :x])
+
|> Nx.subtract(?0)
+
|> Nx.add(1)
+
+
{width, height} = shape = Nx.shape(input)
+
```
+
+
```output
+
{100, 100}
+
```
+
+
## Task 1
+
+
```elixir
+
minima = fn padded, size, axis ->
+
shifted = Nx.slice_axis(padded, 0, size, axis)
+
x1 = Nx.less(input, shifted)
+
+
shifted = Nx.slice_axis(padded, 2, size, axis)
+
x2 = Nx.less(input, shifted)
+
+
Nx.logical_and(x1, x2)
+
end
+
+
padded = Nx.pad(input, 99, [{0, 0, 0}, {1, 1, 0}])
+
+
x = minima.(padded, width, :x)
+
+
padded = Nx.pad(input, 99, [{1, 1, 0}, {0, 0, 0}])
+
+
y = minima.(padded, height, :y)
+
+
minimas = Nx.logical_and(x, y)
+
+
input
+
|> Nx.multiply(minimas)
+
|> Nx.sum()
+
|> Nx.to_number()
+
```
+
+
```output
+
452
+
```
+
+
## Task 2
+
+
```elixir
+
input
+
|> Nx.equal(10)
+
|> Nx.logical_not()
+
|> Nx.select(Nx.iota(shape), 9999)
+
|> Nx.to_flat_list()
+
|> Enum.reject(&(&1 == 9999))
+
|> Enum.map(fn point -> {div(point, width), rem(point, width)} end)
+
|> Enum.reduce([], fn {y, x} = point, basins ->
+
basin_left = Enum.find_index(basins, &({y, x - 1} in &1))
+
basin_up = Enum.find_index(basins, &({y - 1, x} in &1))
+
+
case {basin_left, basin_up} do
+
{nil, nil} ->
+
[MapSet.new([point]) | basins]
+
+
{idx, nil} ->
+
List.update_at(basins, idx, &MapSet.put(&1, point))
+
+
{nil, idx} ->
+
List.update_at(basins, idx, &MapSet.put(&1, point))
+
+
{idx, idx} ->
+
List.update_at(basins, idx, &MapSet.put(&1, point))
+
+
{idx1, idx2} ->
+
{old, basins} = List.pop_at(basins, max(idx1, idx2))
+
+
List.update_at(basins, min(idx1, idx2), &(&1 |> MapSet.union(old) |> MapSet.put(point)))
+
end
+
end)
+
|> Enum.map(&MapSet.size/1)
+
|> Enum.sort(:desc)
+
|> Enum.take(3)
+
|> Enum.reduce(&*/2)
+
```
+
+
```output
+
1263735
+
```
-1985
2021/solutions.livemd
···
-
<!--
-
vim:ft=markdown --!>
-
livebook:{"persist_outputs":true}
-
-->
-
-
<!-- livebook:{"persist_outputs":true} -->
-
-
# Advent of Code 2021
-
-
## Setup
-
-
```elixir
-
Mix.install([
-
{:nx, github: "elixir-nx/nx", sparse: "nx"},
-
{:kino, github: "livebook-dev/kino"}
-
])
-
```
-
-
```output
-
:ok
-
```
-
-
## Day 1
-
-
### Load input
-
-
```elixir
-
stream =
-
File.stream!("day1.txt")
-
|> Stream.map(&String.to_integer(String.trim(&1)))
-
```
-
-
```output
-
#Stream<[
-
enum: %File.Stream{
-
line_or_bytes: :line,
-
modes: [:raw, :read_ahead, :binary],
-
path: "day1.txt",
-
raw: true
-
},
-
funs: [#Function<47.58486609/1 in Stream.map/2>]
-
]>
-
```
-
-
### Task 1
-
-
<!-- livebook:{"break_markdown":true} -->
-
-
Compute count of consecutive increases
-
-
```elixir
-
stream
-
|> Stream.chunk_every(2, 1, :discard)
-
|> Enum.count(fn [a, b] -> a < b end)
-
```
-
-
```output
-
1688
-
```
-
-
### Task 2
-
-
<!-- livebook:{"break_markdown":true} -->
-
-
Compute count of consecutive increases of sums of trigrams.
-
-
However we can notice, that if we have list like:
-
-
$$
-
[a, b, c, d]
-
$$
-
-
Then when we want to compare consecutive trigrams then we compare:
-
-
$$
-
a + b + c < b + c + d \\
-
a < d
-
$$
-
-
So we can traverse each 4 elements and then just compare first and last one
-
instead of summing and then traversing it again.
-
-
```elixir
-
stream
-
|> Stream.chunk_every(4, 1, :discard)
-
|> Enum.count(fn [a, _, _, b] -> a < b end)
-
```
-
-
```output
-
1728
-
```
-
-
## Day 2
-
-
### Load input
-
-
We do parsing there, as it will help us with the latter tasks. Pattern matching
-
is the simplest approach there, as input is in form of:
-
-
```
-
forward 10
-
up 20
-
down 30
-
```
-
-
We need to `trim/1` input to make sure that the last newline will not interrupt
-
`String.to_integer/1` calls.
-
-
```elixir
-
stream =
-
File.stream!("day2.txt")
-
|> Stream.map(fn input ->
-
case String.trim(input) do
-
"forward " <> n -> {:forward, String.to_integer(n)}
-
"up " <> n -> {:up, String.to_integer(n)}
-
"down " <> n -> {:down, String.to_integer(n)}
-
end
-
end)
-
```
-
-
```output
-
#Stream<[
-
enum: %File.Stream{
-
line_or_bytes: :line,
-
modes: [:raw, :read_ahead, :binary],
-
path: "day2.txt",
-
raw: true
-
},
-
funs: [#Function<47.58486609/1 in Stream.map/2>]
-
]>
-
```
-
-
### Task 1
-
-
```elixir
-
{h, d} =
-
stream
-
|> Enum.reduce({0, 0}, fn
-
{:forward, n}, {h, d} -> {h + n, d}
-
{:up, n}, {h, d} -> {h, d - n}
-
{:down, n}, {h, d} -> {h, d + n}
-
end)
-
-
h * d
-
```
-
-
```output
-
1499229
-
```
-
-
### Task 2
-
-
```elixir
-
{h, d, _} =
-
stream
-
|> Enum.reduce({0, 0, 0}, fn
-
{:forward, n}, {h, d, a} -> {h + n, d + a * n, a}
-
{:up, n}, {h, d, a} -> {h, d, a - n}
-
{:down, n}, {h, d, a} -> {h, d, a + n}
-
end)
-
-
h * d
-
```
-
-
```output
-
1340836560
-
```
-
-
## Day 3
-
-
### Input
-
-
```elixir
-
stream =
-
File.stream!("day3.txt")
-
|> Enum.map(&String.trim/1)
-
|> Enum.map(&String.to_charlist/1)
-
-
defmodule Day3 do
-
def count(list) do
-
Enum.reduce(list, List.duplicate(0, 12), fn input, acc ->
-
for {value, counter} <- Enum.zip(input, acc) do
-
case value do
-
?1 -> counter + 1
-
?0 -> counter
-
end
-
end
-
end)
-
end
-
end
-
```
-
-
```output
-
{:module, Day3, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:count, 1}}
-
```
-
-
### Task 1
-
-
```elixir
-
half = div(length(stream), 2)
-
-
{a, b} =
-
stream
-
|> Day3.count()
-
|> Enum.reduce({0, 0}, fn elem, {a, b} ->
-
if elem > half do
-
{a * 2 + 1, b * 2}
-
else
-
{a * 2, b * 2 + 1}
-
end
-
end)
-
-
a * b
-
```
-
-
```output
-
3847100
-
```
-
-
### Task 2
-
-
```elixir
-
defmodule Day3.Task2 do
-
def reduce(list, cb), do: reduce(list, 0, cb)
-
-
defp reduce([elem], _, _), do: elem
-
-
defp reduce(list, at, cb) do
-
counts = Day3.count(list)
-
-
half = div(length(list), 2)
-
count = Enum.at(counts, at)
-
-
bit =
-
cond do
-
count == half and cb.(count + 1, half) -> ?1
-
count != half and cb.(count, half) -> ?1
-
true -> ?0
-
end
-
-
reduce(Enum.filter(list, &(Enum.at(&1, at) == bit)), at + 1, cb)
-
end
-
end
-
-
co2 = List.to_integer(Day3.Task2.reduce(stream, &</2), 2)
-
o2 = List.to_integer(Day3.Task2.reduce(stream, &>/2), 2)
-
-
co2 * o2
-
```
-
-
```output
-
4105235
-
```
-
-
## Day 4
-
-
### Input
-
-
This time it is a little bit more convoluted, as there are 2 parts of the input.
-
Fortunately we can easily disect the parts via pattern matching.
-
-
Technically the conversion to the numbers is not needed, but it does no harm
-
and provides additional layer of safety against some whitespace characters left there
-
and here.
-
-
The `Day4.win/2` function is manually unrolled, as it is easier to write than some
-
random jumping in the list.
-
-
<!-- livebook:{"disable_formatting":true} -->
-
-
```elixir
-
[numbers | bingos] =
-
File.read!("day4.txt")
-
|> String.split("\n\n", trim: true)
-
-
numbers =
-
numbers
-
|> String.trim()
-
|> String.split(",")
-
|> Enum.map(&String.to_integer/1)
-
-
bingos =
-
bingos
-
|> Enum.map(fn bingo ->
-
bingo
-
|> String.split(~r/\s+/, trim: true)
-
|> Enum.map(&String.to_integer/1)
-
end)
-
-
defmodule Day4 do
-
def win(
-
[
-
a1, a2, a3, a4, a5,
-
b1, b2, b3, b4, b5,
-
c1, c2, c3, c4, c5,
-
d1, d2, d3, d4, d5,
-
e1, e2, e3, e4, e5
-
],
-
nums
-
) do
-
# Rows
-
all_in([a1, a2, a3, a4, a5], nums) or
-
all_in([b1, b3, b3, b4, b5], nums) or
-
all_in([c1, c2, c3, c4, c5], nums) or
-
all_in([d1, d2, d3, d4, d5], nums) or
-
all_in([e1, e2, e3, e4, e5], nums) or
-
# Columns
-
all_in([a1, b1, c1, d1, e1], nums) or
-
all_in([a2, b2, c2, d2, e2], nums) or
-
all_in([a3, b3, c3, d3, e3], nums) or
-
all_in([a4, b4, c4, d4, e4], nums) or
-
all_in([a5, b5, c5, d5, e5], nums)
-
end
-
-
def not_matched(bingo, nums) do
-
Enum.reject(bingo, &(&1 in nums))
-
end
-
-
defp all_in(list, nums) do
-
Enum.all?(list, &(&1 in nums))
-
end
-
end
-
```
-
-
```output
-
{:module, Day4, <<70, 79, 82, 49, 0, 0, 15, ...>>, {:all_in, 2}}
-
```
-
-
### Task 1
-
-
We simply traverse the `numbers` list aggregating the numbers (order doesn't really matter,
-
here we aggregate them in reverse order to speedup the code). When we have enough numbers
-
that any of the `bingos` is winning one, then we halt the reduction and return computed
-
result.
-
-
```elixir
-
numbers
-
|> Enum.reduce_while([], fn elem, acc ->
-
matches = [elem | acc]
-
-
case Enum.find(bingos, &Day4.win(&1, matches)) do
-
nil -> {:cont, matches}
-
bingo -> {:halt, Enum.sum(Day4.not_matched(bingo, matches)) * elem}
-
end
-
end)
-
```
-
-
```output
-
34506
-
```
-
-
### Task 2
-
-
```elixir
-
numbers
-
|> Enum.reduce_while({bingos, []}, fn elem, {bingos, acc} ->
-
matches = [elem | acc]
-
-
case bingos do
-
[bingo] ->
-
if Day4.win(bingo, matches) do
-
{:halt, Enum.sum(Day4.not_matched(bingo, matches)) * elem}
-
else
-
{:cont, {bingos, matches}}
-
end
-
-
_ ->
-
{:cont, {Enum.reject(bingos, &Day4.win(&1, matches)), matches}}
-
end
-
end)
-
```
-
-
```output
-
7686
-
```
-
-
## Day 5
-
-
```elixir
-
defmodule Day5 do
-
defmodule Point do
-
defstruct [:x, :y]
-
-
def parse(input) do
-
[x, y] = String.split(input, ",")
-
-
%__MODULE__{x: String.to_integer(x), y: String.to_integer(y)}
-
end
-
end
-
-
defmodule Line do
-
defstruct [:start, :finish]
-
-
def new(a, b) do
-
{start, finish} =
-
cond do
-
a.x < b.x -> {a, b}
-
a.y < b.y -> {a, b}
-
true -> {b, a}
-
end
-
-
%__MODULE__{start: start, finish: finish}
-
end
-
-
def horizontal?(a), do: a.start.y == a.finish.y
-
def vertical?(a), do: a.start.x == a.finish.x
-
-
def points(a) do
-
case {sign(a.finish.x - a.start.x), sign(a.finish.y - a.start.y)} do
-
{0, dy} -> for y <- a.start.y..a.finish.y//dy, do: {a.start.x, y}
-
{dx, 0} -> for x <- a.start.x..a.finish.x//dx, do: {x, a.start.y}
-
{dx, dy} -> Enum.zip(a.start.x..a.finish.x//dx, a.start.y..a.finish.y//dy)
-
end
-
end
-
-
def orientation(a) do
-
cond do
-
horizontal?(a) -> :horizontal
-
vertical?(a) -> :vertical
-
true -> :diagonal
-
end
-
end
-
-
defp sign(0), do: 0
-
defp sign(x) when x < 0, do: -1
-
defp sign(x) when x > 0, do: 1
-
end
-
end
-
-
lines =
-
File.stream!("day5.txt")
-
|> Stream.map(&String.trim/1)
-
|> Stream.map(fn input ->
-
[a, b] = String.split(input, " -> ")
-
-
pa = Day5.Point.parse(a)
-
pb = Day5.Point.parse(b)
-
-
Day5.Line.new(pa, pb)
-
end)
-
```
-
-
```output
-
#Stream<[
-
enum: %File.Stream{
-
line_or_bytes: :line,
-
modes: [:raw, :read_ahead, :binary],
-
path: "day5.txt",
-
raw: true
-
},
-
funs: [#Function<47.58486609/1 in Stream.map/2>, #Function<47.58486609/1 in Stream.map/2>]
-
]>
-
```
-
-
### Task 1
-
-
```elixir
-
lines
-
|> Stream.filter(&(Day5.Line.orientation(&1) != :diagonal))
-
|> Stream.flat_map(&Day5.Line.points/1)
-
|> Enum.frequencies()
-
|> Enum.count(fn {_k, v} -> v > 1 end)
-
```
-
-
```output
-
5197
-
```
-
-
### Task 2
-
-
```elixir
-
lines
-
|> Stream.flat_map(&Day5.Line.points/1)
-
|> Enum.frequencies()
-
|> Enum.count(fn {_k, v} -> v > 1 end)
-
```
-
-
```output
-
18605
-
```
-
-
## Day 6
-
-
```elixir
-
initial = for i <- 0..8, into: %{}, do: {i, 0}
-
-
counts =
-
File.read!("day6.txt")
-
|> String.trim()
-
|> String.split(",")
-
|> Enum.map(&String.to_integer/1)
-
|> Enum.frequencies()
-
|> Map.merge(initial, fn _, a, _ -> a end)
-
-
defmodule Day6 do
-
def next(%{0 => next} = population) do
-
1..8
-
|> Map.new(&{&1 - 1, population[&1]})
-
|> Map.merge(%{6 => next, 8 => next}, fn _, v1, v2 -> v1 + v2 end)
-
end
-
end
-
```
-
-
```output
-
{:module, Day6, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:next, 1}}
-
```
-
-
### Task 1
-
-
```elixir
-
1..80
-
|> Enum.reduce(counts, fn _, acc -> Day6.next(acc) end)
-
|> Map.values()
-
|> Enum.sum()
-
```
-
-
```output
-
343441
-
```
-
-
### Task 2
-
-
```elixir
-
1..256
-
|> Enum.reduce(counts, fn _, acc -> Day6.next(acc) end)
-
|> Map.values()
-
|> Enum.sum()
-
```
-
-
```output
-
1569108373832
-
```
-
-
## Day 7
-
-
```elixir
-
input =
-
File.read!("day7.txt")
-
|> String.trim()
-
|> String.split(",")
-
|> Enum.map(&String.to_integer/1)
-
```
-
-
```output
-
[1101, 1, 29, 67, 1102, 0, 1, 65, 1008, 65, 35, 66, 1005, 66, 28, 1, 67, 65, 20, 4, 0, 1001, 65, 1,
-
65, 1106, 0, 8, 99, 35, 67, 101, 99, 105, 32, 110, 39, 101, 115, 116, 32, 112, 97, 115, 32, 117,
-
110, 101, 32, 105, ...]
-
```
-
-
### Task 1
-
-
```elixir
-
median = Enum.at(Enum.sort(input), div(length(input), 2))
-
-
input
-
|> Enum.map(&abs(&1 - median))
-
|> Enum.sum()
-
```
-
-
```output
-
336721
-
```
-
-
### Task 2
-
-
```elixir
-
arith_sum = fn n -> div(n * n + n, 2) end
-
-
max = Enum.max(input)
-
-
mean = Enum.sum(input) / length(input)
-
-
[floor(mean), ceil(mean)]
-
|> Enum.map(fn n ->
-
input
-
|> Enum.map(&arith_sum.(abs(&1 - n)))
-
|> Enum.sum()
-
end)
-
|> Enum.min()
-
```
-
-
```output
-
91638945
-
```
-
-
## Day 8
-
-
```elixir
-
input =
-
File.stream!("day8.txt")
-
|> Stream.map(fn line ->
-
line
-
|> String.split(" | ")
-
|> Enum.map(fn part ->
-
part
-
|> String.trim()
-
|> String.split(" ")
-
|> Enum.map(fn disp ->
-
# Sort characters in each entry to simplify later work
-
disp
-
|> String.to_charlist()
-
|> Enum.sort()
-
|> List.to_string()
-
end)
-
end)
-
|> List.to_tuple()
-
end)
-
```
-
-
```output
-
#Stream<[
-
enum: %File.Stream{
-
line_or_bytes: :line,
-
modes: [:raw, :read_ahead, :binary],
-
path: "day8.txt",
-
raw: true
-
},
-
funs: [#Function<47.58486609/1 in Stream.map/2>]
-
]>
-
```
-
-
### Task 1
-
-
We simply need to count all occurences of the values that have 2, 3, 4, or 7 highlighted
-
segments.
-
-
```elixir
-
input
-
|> Enum.map(fn {_, output} ->
-
Enum.count(output, &(byte_size(&1) in [2, 3, 4, 7]))
-
end)
-
|> Enum.sum()
-
```
-
-
```output
-
390
-
```
-
-
### Task 2
-
-
```elixir
-
defmodule Day8.Task2 do
-
defp a --- b, do: MapSet.difference(a, b)
-
-
defp a +++ b, do: MapSet.union(a, b)
-
-
defp a <~> b, do: MapSet.intersection(a, b)
-
-
# 1. 7. 4. 2|3|5. 2|3|5. 2|3|5. 6|9|0. 6|9|0. 6|9|0. 8.
-
def deduce([cf, acf, bcdf, acdeg, acdfg, abdfg, abdefg, abcdfg, abcefg, abcdefg]) do
-
eg = abcdefg --- (acf +++ bcdf)
-
bd = bcdf --- cf
-
adg = acdeg <~> acdfg <~> abdfg
-
abfg = abdefg <~> abcdfg <~> abcefg
-
a = acf --- cf
-
b = abfg <~> bd
-
f = abfg <~> cf
-
g = adg <~> eg
-
d = adg <~> bd
-
c = cf --- f
-
e = eg --- g
-
-
[a, b, c, d, e, f, g] =
-
[a, b, c, d, e, f, g]
-
|> Enum.map(&extract/1)
-
-
[
-
# 0
-
[a, b, c, e, f, g],
-
# 1
-
[c, f],
-
# 2
-
[a, c, d, e, g],
-
# 3
-
[a, c, d, f, g],
-
# 4
-
[b, c, d, f],
-
# 5
-
[a, b, d, f, g],
-
# 6
-
[a, b, d, e, f, g],
-
# 7
-
[a, c, f],
-
# 8
-
[a, b, c, d, e, f, g],
-
# 9
-
[a, b, c, d, f, g]
-
]
-
|> Enum.map(&List.to_string(Enum.sort(&1)))
-
|> Enum.with_index()
-
|> Map.new()
-
end
-
-
defp extract(a) do
-
# Just additional sanity check
-
[v] = MapSet.to_list(a)
-
-
v
-
end
-
-
def decode(matches, output) do
-
output
-
|> Enum.map(&matches[&1])
-
|> Integer.undigits()
-
end
-
end
-
-
input
-
|> Enum.map(fn {input, output} ->
-
input
-
|> Enum.sort_by(&byte_size/1)
-
|> Enum.map(&MapSet.new(String.to_charlist(&1)))
-
|> Day8.Task2.deduce()
-
|> Day8.Task2.decode(output)
-
end)
-
|> Enum.sum()
-
```
-
-
```output
-
1011785
-
```
-
-
## Day 9
-
-
```elixir
-
input =
-
File.read!("day9.txt")
-
|> String.split("\n", trim: true)
-
|> Enum.map(&String.to_charlist(String.trim(&1)))
-
|> Nx.tensor(names: [:y, :x])
-
|> Nx.subtract(?0)
-
|> Nx.add(1)
-
-
{width, height} = shape = Nx.shape(input)
-
```
-
-
```output
-
{100, 100}
-
```
-
-
### Task 1
-
-
```elixir
-
minima = fn padded, size, axis ->
-
shifted = Nx.slice_axis(padded, 0, size, axis)
-
x1 = Nx.less(input, shifted)
-
-
shifted = Nx.slice_axis(padded, 2, size, axis)
-
x2 = Nx.less(input, shifted)
-
-
Nx.logical_and(x1, x2)
-
end
-
-
padded = Nx.pad(input, 99, [{0, 0, 0}, {1, 1, 0}])
-
-
x = minima.(padded, width, :x)
-
-
padded = Nx.pad(input, 99, [{1, 1, 0}, {0, 0, 0}])
-
-
y = minima.(padded, height, :y)
-
-
minimas = Nx.logical_and(x, y)
-
-
input
-
|> Nx.multiply(minimas)
-
|> Nx.sum()
-
|> Nx.to_number()
-
```
-
-
```output
-
452
-
```
-
-
### Task 2
-
-
```elixir
-
input
-
|> Nx.equal(10)
-
|> Nx.logical_not()
-
|> Nx.select(Nx.iota(shape), 9999)
-
|> Nx.to_flat_list()
-
|> Enum.reject(&(&1 == 9999))
-
|> Enum.map(fn point -> {div(point, width), rem(point, width)} end)
-
|> Enum.reduce([], fn {y, x} = point, basins ->
-
basin_left = Enum.find_index(basins, &({y, x - 1} in &1))
-
basin_up = Enum.find_index(basins, &({y - 1, x} in &1))
-
-
case {basin_left, basin_up} do
-
{nil, nil} ->
-
[MapSet.new([point]) | basins]
-
-
{idx, nil} ->
-
List.update_at(basins, idx, &MapSet.put(&1, point))
-
-
{nil, idx} ->
-
List.update_at(basins, idx, &MapSet.put(&1, point))
-
-
{idx, idx} ->
-
List.update_at(basins, idx, &MapSet.put(&1, point))
-
-
{idx1, idx2} ->
-
{old, basins} = List.pop_at(basins, max(idx1, idx2))
-
-
List.update_at(basins, min(idx1, idx2), &(&1 |> MapSet.union(old) |> MapSet.put(point)))
-
end
-
end)
-
|> Enum.map(&MapSet.size/1)
-
|> Enum.sort(:desc)
-
|> Enum.take(3)
-
|> Enum.reduce(&*/2)
-
```
-
-
```output
-
1263735
-
```
-
-
## Day 10
-
-
```elixir
-
input =
-
File.stream!("day10.txt")
-
|> Stream.map(&String.trim/1)
-
-
defmodule Day10 do
-
@parens %{?( => ?), ?[ => ?], ?< => ?>, ?{ => ?}}
-
-
def parse(input), do: parse(input, [])
-
-
defp parse(<<c>> <> rest, stack) when c in '([{<', do: parse(rest, [@parens[c] | stack])
-
defp parse(<<c>> <> rest, [c | stack]), do: parse(rest, stack)
-
defp parse(<<>>, []), do: :ok
-
defp parse(<<>>, rest), do: {:incomplete, rest}
-
defp parse(<<c>> <> _, _), do: {:unexpected, [c]}
-
end
-
```
-
-
```output
-
{:module, Day10, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:parse, 2}}
-
```
-
-
### Task 1
-
-
```elixir
-
points = %{
-
?) => 3,
-
?] => 57,
-
?} => 1197,
-
?> => 25137
-
}
-
-
input
-
|> Enum.map(&Day10.parse/1)
-
|> Enum.map(fn
-
{:unexpected, [c]} -> points[c]
-
_ -> 0
-
end)
-
|> Enum.sum()
-
```
-
-
```output
-
288291
-
```
-
-
### Task 2
-
-
```elixir
-
points = %{
-
?) => 1,
-
?] => 2,
-
?} => 3,
-
?> => 4
-
}
-
-
median = fn list ->
-
sorted = Enum.sort(list)
-
middle = div(length(list), 2)
-
-
Enum.at(sorted, middle)
-
end
-
-
input
-
|> Enum.map(&Day10.parse/1)
-
|> Enum.flat_map(fn
-
{:incomplete, rest} ->
-
[
-
Enum.reduce(rest, 0, fn c, acc ->
-
acc * 5 + points[c]
-
end)
-
]
-
-
_ ->
-
[]
-
end)
-
|> median.()
-
```
-
-
```output
-
820045242
-
```
-
-
## Day 11
-
-
```elixir
-
input =
-
File.read!("day11.txt")
-
|> String.split("\n")
-
|> Enum.map(&String.trim/1)
-
|> Enum.map(fn line ->
-
for <<c <- line>>, do: c - ?0
-
end)
-
|> Enum.with_index()
-
|> Enum.flat_map(fn {row, y} ->
-
for {v, x} <- Enum.with_index(row), do: {{x, y}, v}
-
end)
-
|> Map.new()
-
-
defmodule Day11 do
-
def step(map) do
-
updated = Map.new(map, fn {k, v} -> {k, v + 1} end)
-
-
lightup(updated, 0)
-
end
-
-
@diffs for dx <- -1..1, dy <- -1..1, dx != 0 or dy != 0, do: {dx, dy}
-
-
def lightup(map, n) do
-
map
-
|> Enum.reduce({map, 0}, fn
-
{_, v}, acc when v < 10 ->
-
acc
-
-
{{x, y} = k, _}, {map, count} ->
-
new_map =
-
@diffs
-
|> Enum.reduce(map, fn {dx, dy}, acc ->
-
point = {x + dx, y + dy}
-
-
case Map.fetch(acc, point) do
-
{:ok, value} when value != 0 -> %{acc | point => value + 1}
-
_ -> acc
-
end
-
end)
-
|> Map.put(k, 0)
-
-
{new_map, count + 1}
-
end)
-
|> case do
-
{map, 0} -> {map, n}
-
{map, m} -> lightup(map, n + m)
-
end
-
end
-
end
-
```
-
-
```output
-
{:module, Day11, <<70, 79, 82, 49, 0, 0, 11, ...>>, {:lightup, 2}}
-
```
-
-
### Task 1
-
-
```elixir
-
draw = fn map ->
-
for x <- 0..9 do
-
IO.puts(for y <- 0..9, do: ?0 + map[{x, y}])
-
end
-
-
IO.puts("")
-
end
-
-
1..100
-
|> Enum.reduce({input, 0}, fn _, {map, n} ->
-
{new_map, m} = Day11.step(map)
-
{new_map, n + m}
-
end)
-
|> elem(1)
-
```
-
-
```output
-
1688
-
```
-
-
### Task 2
-
-
```elixir
-
Stream.unfold(1, &{&1, &1 + 1})
-
|> Enum.reduce_while(input, fn idx, map ->
-
case Day11.step(map) do
-
{_, 100} -> {:halt, idx}
-
{next, _} -> {:cont, next}
-
end
-
end)
-
```
-
-
```output
-
403
-
```
-
-
## Day 12
-
-
```elixir
-
input =
-
File.read!("day12.txt")
-
|> String.split("\n")
-
|> Enum.map(&String.split(&1, "-"))
-
-
graph =
-
Enum.reduce(input, %{}, fn [a, b], acc ->
-
acc
-
|> Map.update(a, [b], &[b | &1])
-
|> Map.update(b, [a], &[a | &1])
-
end)
-
-
defmodule Day12 do
-
def dfs(graph, start, finish), do: dfs(graph, start, finish, [start])
-
-
defp dfs(_graph, vertex, vertex, _visited), do: 1
-
-
defp dfs(graph, vertex, finish, visited) do
-
(graph[vertex] -- visited)
-
|> Enum.reduce(0, fn vertex, acc ->
-
visited = if small?(vertex), do: [vertex | visited], else: visited
-
-
acc + dfs(graph, vertex, finish, visited)
-
end)
-
end
-
-
def dfs2(graph, start, finish), do: dfs2(graph, start, finish, %{start => :inf})
-
-
defp dfs2(_graph, vertex, vertex, _visited), do: 1
-
-
defp dfs2(graph, vertex, finish, visited) do
-
(graph[vertex] -- keys(visited))
-
|> Enum.reduce(0, fn vertex, acc ->
-
visited = if small?(vertex), do: Map.update(visited, vertex, 1, &(&1 + 1)), else: visited
-
-
acc + dfs2(graph, vertex, finish, visited)
-
end)
-
end
-
-
defp keys(map) do
-
if Enum.any?(map, fn {_, v} -> v == 2 end) do
-
# there is already some vertex visited twice
-
Map.keys(map)
-
else
-
for {k, v} <- map, v > 1, do: k
-
end
-
end
-
-
defp small?(<<c>> <> _), do: c in ?a..?z
-
end
-
```
-
-
```output
-
{:module, Day12, <<70, 79, 82, 49, 0, 0, 15, ...>>, {:small?, 1}}
-
```
-
-
### Task 1
-
-
```elixir
-
Day12.dfs(graph, "start", "end")
-
```
-
-
```output
-
4167
-
```
-
-
### Task 2
-
-
```elixir
-
Day12.dfs2(graph, "start", "end")
-
```
-
-
```output
-
98441
-
```
-
-
## Day 13
-
-
```elixir
-
[input, folds] =
-
File.read!("day13.txt")
-
|> String.trim()
-
|> String.split("\n\n")
-
-
input =
-
input
-
|> String.split("\n")
-
|> Enum.map(fn line ->
-
[x, y] = String.split(line, ",")
-
-
{String.to_integer(x), String.to_integer(y)}
-
end)
-
|> MapSet.new()
-
-
folds =
-
folds
-
|> String.split("\n")
-
|> Enum.map(fn
-
"fold along " <> <<c>> <> "=" <> rest ->
-
{String.to_atom(<<c>>), String.to_integer(rest)}
-
end)
-
-
defmodule Day13 do
-
def fold({orientation, pos}, set) do
-
Enum.reduce(set, MapSet.new(), fn point, acc ->
-
new_point = folded_coords(orientation, pos, point)
-
-
MapSet.put(acc, new_point)
-
end)
-
end
-
-
defp folded_coords(:x, col, {x, y}) when x > col, do: {abs(2 * col - x), y}
-
defp folded_coords(:y, row, {x, y}) when y > row, do: {x, abs(2 * row - y)}
-
defp folded_coords(_, _, point), do: point
-
-
def draw(set) do
-
set
-
|> Enum.group_by(&elem(&1, 1))
-
|> Enum.sort()
-
|> Enum.map(fn {_, points} ->
-
points
-
|> Enum.map(&elem(&1, 0))
-
|> Enum.sort()
-
|> Enum.chunk_every(2, 1)
-
|> Enum.map(fn
-
[a, b] -> b - a
-
_ -> 0
-
end)
-
|> Enum.map(&String.pad_trailing("█", &1, " "))
-
end)
-
|> Enum.join("\n")
-
end
-
end
-
```
-
-
```output
-
{:module, Day13, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:draw, 1}}
-
```
-
-
### Task 1
-
-
```elixir
-
Day13.fold(hd(folds), input) |> MapSet.size()
-
```
-
-
```output
-
802
-
```
-
-
### Task 2
-
-
```elixir
-
Enum.reduce(folds, input, &Day13.fold/2)
-
|> Day13.draw()
-
|> IO.puts()
-
```
-
-
```output
-
███ █ █ █ █ ████ ████ ██ █ █ ███
-
█ █ █ █ █ █ █ █ █ █ █ █ █ █
-
█ █ ██ ████ ███ █ █ █ █ ███
-
███ █ █ █ █ █ █ █ ██ █ █ █ █
-
█ █ █ █ █ █ █ █ █ █ █ █ █ █
-
█ █ █ █ █ █ █ ████ ███ ██ ███
-
```
-
-
```output
-
:ok
-
```
-
-
## Day 14
-
-
```elixir
-
[polymer_raw, subs] =
-
File.read!("day14.txt")
-
|> String.split("\n\n")
-
-
<<first, _::binary>> = polymer_raw
-
-
polymer =
-
{first,
-
polymer_raw
-
|> String.to_charlist()
-
|> Enum.chunk_every(2, 1, :discard)
-
|> Enum.frequencies()}
-
-
subs =
-
subs
-
|> String.trim()
-
|> String.split(["\n", " -> "])
-
|> Enum.chunk_every(2)
-
|> Map.new(fn [pair, <<new>>] -> {String.to_charlist(pair), new} end)
-
-
defmodule Day14 do
-
def expand({hd, polymer}, subs) do
-
new =
-
polymer
-
|> Enum.reduce(%{}, fn {[a, b] = pair, count}, acc ->
-
s = Map.fetch!(subs, pair)
-
-
acc
-
|> Map.update([a, s], count, &(&1 + count))
-
|> Map.update([s, b], count, &(&1 + count))
-
end)
-
-
{hd, new}
-
end
-
-
def expand_naive(polymer, subs) do
-
polymer
-
|> to_charlist()
-
|> Enum.chunk_every(2, 1, :discard)
-
|> Enum.flat_map(fn [a, b] = pair ->
-
[a, subs[pair], b]
-
end)
-
|> List.to_string()
-
end
-
-
def frequencies({hd, polymer}) do
-
polymer
-
|> Enum.reduce(%{hd => 1}, fn {[_, b], count}, acc ->
-
Map.update(acc, b, count, &(&1 + count))
-
end)
-
end
-
end
-
```
-
-
```output
-
{:module, Day14, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:frequencies, 1}}
-
```
-
-
### Task 1
-
-
```elixir
-
{{_, min}, {_, max}} =
-
1..10
-
|> Enum.reduce(polymer, fn _, acc ->
-
Day14.expand(acc, subs)
-
end)
-
|> Day14.frequencies()
-
|> Enum.min_max_by(&elem(&1, 1))
-
-
# 2768
-
max - min
-
```
-
-
```output
-
2768
-
```
-
-
### Task 2
-
-
```elixir
-
{{_, min}, {_, max}} =
-
1..40
-
|> Enum.reduce(polymer, fn _, acc ->
-
Day14.expand(acc, subs)
-
end)
-
|> Day14.frequencies()
-
|> Enum.min_max_by(&elem(&1, 1))
-
-
max - min
-
```
-
-
```output
-
2914365137499
-
```
-
-
## Day 15
-
-
```elixir
-
input =
-
File.read!("day15.txt")
-
|> String.trim()
-
|> String.split("\n")
-
|> Enum.map(&String.to_charlist/1)
-
|> Enum.with_index()
-
|> Enum.flat_map(fn {row, y} ->
-
row
-
|> Enum.with_index()
-
|> Enum.map(fn {v, x} -> {{x, y}, v - ?0} end)
-
end)
-
|> Map.new()
-
-
{width, height} = Enum.max(Map.keys(input))
-
```
-
-
```output
-
{99, 99}
-
```
-
-
### Task 1
-
-
```elixir
-
shortest_paths =
-
for y <- height..0//-1,
-
x <- width..0//-1,
-
reduce: %{} do
-
acc ->
-
right = acc[{x + 1, y}]
-
bottom = acc[{x, y + 1}]
-
-
value =
-
case {right, bottom} do
-
{nil, nil} -> input[{x, y}]
-
_ -> input[{x, y}] + min(right, bottom)
-
end
-
-
Map.put(acc, {x, y}, value)
-
end
-
-
shortest_paths[{0, 0}] - input[{0, 0}]
-
```
-
-
```output
-
429
-
```
-
-
### Task 2
-
-
```elixir
-
defmodule Day15.Task2 do
-
def expand_grid(board) do
-
{width, height} = Enum.max(Map.keys(board))
-
-
board
-
|> Enum.flat_map(fn {{x, y}, v} ->
-
for rx <- 0..4, ry <- 0..4 do
-
{{x + (width + 1) * rx, y + (height + 1) * ry}, rem(v - 1 + rx + ry, 9) + 1}
-
end
-
end)
-
|> Map.new()
-
end
-
-
def find_path(board, start, finish) do
-
dists = :gb_sets.singleton({0, start})
-
-
find_path(board, finish, dists, MapSet.new())
-
end
-
-
@surround for dx <- -1..1, dy <- -1..1, abs(dx) != abs(dy), do: {dx, dy}
-
-
def find_path(board, finish, dists, visited) do
-
{{dist, {x, y} = curr}, dists} = :gb_sets.take_smallest(dists)
-
-
if curr == finish do
-
dist
-
else
-
visited = MapSet.put(visited, curr)
-
-
dists =
-
for {dx, dy} <- @surround,
-
next = {x + dx, y + dy},
-
next not in visited,
-
is_map_key(board, next),
-
alt = dist + board[next],
-
reduce: dists do
-
acc ->
-
:gb_sets.add_element({alt, next}, acc)
-
end
-
-
find_path(board, finish, dists, visited)
-
end
-
end
-
end
-
```
-
-
```output
-
{:module, Day15.Task2, <<70, 79, 82, 49, 0, 0, 16, ...>>, {:find_path, 4}}
-
```
-
-
```elixir
-
input
-
|> Day15.Task2.expand_grid()
-
|> Day15.Task2.find_path({0, 0}, {499, 499})
-
```
-
-
```output
-
2844
-
```
-
-
## Day 16
-
-
```elixir
-
defmodule Day16 do
-
defmodule Packet do
-
defstruct [:version, :type, :value]
-
end
-
-
def decode(<<version::3, 4::3, rest::bitstring>>) do
-
{value, rest} = literal(rest, 0)
-
-
{%Packet{type: 4, version: version, value: value}, rest}
-
end
-
-
def decode(<<version::3, type::3, 0::1, length::15, rest::bitstring>>) do
-
<<subpackets::bitstring-size(length), rest::bitstring>> = rest
-
-
{%Packet{type: type, version: version, value: decode_all(subpackets)}, rest}
-
end
-
-
def decode(<<version::3, type::3, 1::1, length::11, rest::bitstring>>) do
-
{value, rest} = Enum.map_reduce(1..length, rest, fn _, acc -> decode(acc) end)
-
-
{%Packet{type: type, version: version, value: value}, rest}
-
end
-
-
def decode_all(input) do
-
case decode(input) do
-
{packet, <<>>} -> [packet]
-
{packet, rest} -> [packet | decode_all(rest)]
-
end
-
end
-
-
defp literal(<<1::1, bits::4, rest::bitstring>>, acc) do
-
literal(rest, acc * 0x10 + bits)
-
end
-
-
defp literal(<<0::1, bits::4, rest::bitstring>>, acc) do
-
{acc * 0x10 + bits, rest}
-
end
-
end
-
-
input =
-
File.read!("day16.txt")
-
|> String.trim()
-
|> Base.decode16!()
-
|> Day16.decode()
-
|> elem(0)
-
```
-
-
```output
-
%Day16.Packet{
-
type: 0,
-
value: [
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{type: 4, value: 20, version: 6},
-
%Day16.Packet{
-
type: 6,
-
value: [
-
%Day16.Packet{type: 4, value: 14747, version: 1},
-
%Day16.Packet{type: 4, value: 14747, version: 6}
-
],
-
version: 2
-
}
-
],
-
version: 1
-
},
-
%Day16.Packet{
-
type: 3,
-
value: [
-
%Day16.Packet{type: 4, value: 15, version: 5},
-
%Day16.Packet{type: 4, value: 10, version: 6}
-
],
-
version: 7
-
},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{
-
type: 7,
-
value: [
-
%Day16.Packet{type: 4, value: 2184, version: 1},
-
%Day16.Packet{type: 4, value: 130250, version: 6}
-
],
-
version: 6
-
},
-
%Day16.Packet{type: 4, value: 5442981, version: 4}
-
],
-
version: 6
-
},
-
%Day16.Packet{type: 4, value: 8281083, version: 0},
-
%Day16.Packet{
-
type: 2,
-
value: [
-
%Day16.Packet{type: 4, value: 102, version: 5},
-
%Day16.Packet{type: 4, value: 647125, version: 7}
-
],
-
version: 1
-
},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{type: 4, value: 178, version: 1},
-
%Day16.Packet{type: 4, value: 176, version: 6}
-
],
-
version: 0
-
},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{
-
type: 6,
-
value: [
-
%Day16.Packet{
-
type: 0,
-
value: [
-
%Day16.Packet{type: 4, value: 13, version: 1},
-
%Day16.Packet{type: 4, value: 8, version: 4},
-
%Day16.Packet{type: 4, value: 4, version: 3}
-
],
-
version: 2
-
},
-
%Day16.Packet{
-
type: 0,
-
value: [
-
%Day16.Packet{type: 4, value: 7, version: 7},
-
%Day16.Packet{type: 4, value: 11, version: 3},
-
%Day16.Packet{type: 4, value: 14, version: 2}
-
],
-
version: 4
-
}
-
],
-
version: 7
-
},
-
%Day16.Packet{type: 4, value: 2724, version: 0}
-
],
-
version: 1
-
},
-
%Day16.Packet{type: 4, value: 9, version: 4},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{
-
type: 5,
-
value: [
-
%Day16.Packet{type: 4, value: 7240238, version: 2},
-
%Day16.Packet{type: 4, value: 233, version: 7}
-
],
-
version: 1
-
},
-
%Day16.Packet{type: 4, value: 37, version: 6}
-
],
-
version: 4
-
},
-
%Day16.Packet{type: 2, value: [%Day16.Packet{type: 4, value: 2, version: 5}], version: 5},
-
%Day16.Packet{type: 4, value: 53749, version: 4},
-
%Day16.Packet{type: 4, value: 11, version: 3},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{type: 4, value: 382979, version: 4},
-
%Day16.Packet{
-
type: 5,
-
value: [
-
%Day16.Packet{
-
type: 0,
-
value: [
-
%Day16.Packet{type: 4, value: 15, version: 1},
-
%Day16.Packet{type: 4, value: 10, version: 0},
-
%Day16.Packet{type: 4, value: 2, version: 6}
-
],
-
version: 5
-
},
-
%Day16.Packet{
-
type: 0,
-
value: [
-
%Day16.Packet{type: 4, value: 4, version: 7},
-
%Day16.Packet{type: 4, value: 7, version: 4},
-
%Day16.Packet{type: 4, value: 2, version: 5}
-
],
-
version: 1
-
}
-
],
-
version: 6
-
}
-
],
-
version: 2
-
},
-
%Day16.Packet{type: 4, value: 21251, version: 1},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{type: 4, value: 163, version: 6},
-
%Day16.Packet{
-
type: 5,
-
value: [
-
%Day16.Packet{type: 4, value: 59, version: 3},
-
%Day16.Packet{type: 4, value: 836848134220, version: 1}
-
],
-
version: 6
-
}
-
],
-
version: 2
-
},
-
%Day16.Packet{
-
type: 2,
-
value: [
-
%Day16.Packet{
-
type: 0,
-
value: [
-
%Day16.Packet{
-
type: 0,
-
value: [
-
%Day16.Packet{
-
type: 2,
-
value: [
-
%Day16.Packet{
-
type: 2,
-
value: [
-
%Day16.Packet{
-
type: 0,
-
value: [
-
%Day16.Packet{
-
type: 3,
-
value: [
-
%Day16.Packet{
-
type: 2,
-
value: [
-
%Day16.Packet{
-
type: 2,
-
value: [
-
%Day16.Packet{
-
type: 3,
-
value: [%Day16.Packet{type: 0, value: [...], ...}],
-
version: 0
-
}
-
],
-
version: 1
-
}
-
],
-
version: 1
-
}
-
],
-
version: 7
-
}
-
],
-
version: 0
-
}
-
],
-
version: 6
-
}
-
],
-
version: 2
-
}
-
],
-
version: 2
-
}
-
],
-
version: 6
-
}
-
],
-
version: 7
-
},
-
%Day16.Packet{type: 1, value: [%Day16.Packet{type: 4, value: 44, version: 4}], version: 7},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{type: 4, value: 255, version: 2},
-
%Day16.Packet{type: 4, value: 91, version: 5},
-
%Day16.Packet{type: 4, value: 176, version: 5},
-
%Day16.Packet{type: 4, value: 23, version: 1}
-
],
-
version: 7
-
},
-
%Day16.Packet{
-
type: 3,
-
value: [
-
%Day16.Packet{type: 4, value: 11520, version: 4},
-
%Day16.Packet{type: 4, value: 6069, version: 0},
-
%Day16.Packet{type: 4, value: 1089149511401, version: 4},
-
%Day16.Packet{type: 4, value: 158, version: 2},
-
%Day16.Packet{type: 4, value: 620605, version: 0}
-
],
-
version: 2
-
},
-
%Day16.Packet{
-
type: 0,
-
value: [
-
%Day16.Packet{type: 4, value: 62788, version: 7},
-
%Day16.Packet{type: 4, value: 9410622, version: 2},
-
%Day16.Packet{type: 4, value: 15912821, version: 4}
-
],
-
version: 4
-
},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{type: 4, value: 22416, version: 5},
-
%Day16.Packet{
-
type: 5,
-
value: [
-
%Day16.Packet{type: 4, value: 246, version: 1},
-
%Day16.Packet{type: 4, value: 246, version: 4}
-
],
-
version: 2
-
}
-
],
-
version: 0
-
},
-
%Day16.Packet{type: 3, value: [%Day16.Packet{type: 4, value: 13008601, version: 5}], version: 0},
-
%Day16.Packet{
-
type: 0,
-
value: [
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{type: 4, value: 3, version: 4},
-
%Day16.Packet{type: 4, value: 14, version: 1},
-
%Day16.Packet{type: 4, value: 5, version: 0}
-
],
-
version: 5
-
},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{type: 4, value: 2, version: 1},
-
%Day16.Packet{type: 4, value: 14, version: 1},
-
%Day16.Packet{type: 4, value: 10, version: 1}
-
],
-
version: 6
-
},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{type: 4, value: 8, version: 3},
-
%Day16.Packet{type: 4, value: 6, version: 6},
-
%Day16.Packet{type: 4, value: 11, version: 0}
-
],
-
version: 1
-
}
-
],
-
version: 5
-
},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{type: 4, value: 32940592237, version: 2},
-
%Day16.Packet{
-
type: 5,
-
value: [
-
%Day16.Packet{type: 4, value: 100, version: 1},
-
%Day16.Packet{type: 4, value: 1393232728, version: 2}
-
],
-
version: 2
-
}
-
],
-
version: 0
-
},
-
%Day16.Packet{type: 4, value: 89, version: 3},
-
%Day16.Packet{
-
type: 2,
-
value: [
-
%Day16.Packet{type: 4, value: 204, version: 6},
-
%Day16.Packet{type: 4, value: 260321821, version: 2},
-
%Day16.Packet{type: 4, value: 225241983, version: 6}
-
],
-
version: 0
-
},
-
%Day16.Packet{
-
type: 0,
-
value: [
-
%Day16.Packet{type: 4, value: 960899, version: 3},
-
%Day16.Packet{type: 4, value: 58997, version: 5},
-
%Day16.Packet{type: 4, value: 54940, version: 6},
-
%Day16.Packet{type: 4, value: 10974, version: 2},
-
%Day16.Packet{type: 4, value: 882043, version: 2}
-
],
-
version: 0
-
},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{
-
type: 6,
-
value: [
-
%Day16.Packet{type: 4, value: 35633017255, version: 4},
-
%Day16.Packet{type: 4, value: 35633017255, version: 2}
-
],
-
version: 3
-
},
-
%Day16.Packet{type: 4, value: 1359, version: 6}
-
],
-
version: 6
-
},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{type: 4, value: 92, version: 4},
-
%Day16.Packet{type: 4, value: 38, version: 3},
-
%Day16.Packet{type: 4, value: 160, version: 5},
-
%Day16.Packet{type: 4, value: 111, version: 1},
-
%Day16.Packet{type: 4, value: 64, version: 4}
-
],
-
version: 4
-
},
-
%Day16.Packet{
-
type: 0,
-
value: [
-
%Day16.Packet{type: 4, value: 2541, version: 3},
-
%Day16.Packet{type: 4, value: 263947, version: 6},
-
%Day16.Packet{type: 4, value: 7686705, version: 5},
-
%Day16.Packet{type: 4, value: 31, version: 4}
-
],
-
version: 2
-
},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{
-
type: 6,
-
value: [
-
%Day16.Packet{type: 4, value: 3193865, version: 1},
-
%Day16.Packet{type: 4, value: 20223, version: 7}
-
],
-
version: 2
-
},
-
%Day16.Packet{type: 4, value: 9328522, version: 5}
-
],
-
version: 0
-
},
-
%Day16.Packet{
-
type: 2,
-
value: [
-
%Day16.Packet{type: 4, value: 5, version: 4},
-
%Day16.Packet{type: 4, value: 7, version: 3},
-
%Day16.Packet{type: 4, value: 179420284, version: 4},
-
%Day16.Packet{type: 4, value: 19890, version: 1},
-
%Day16.Packet{type: 4, value: 2655, version: 0}
-
],
-
version: 7
-
},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{type: 4, value: 862089, version: 1},
-
%Day16.Packet{
-
type: 6,
-
value: [
-
%Day16.Packet{type: 4, value: 248, version: 3},
-
%Day16.Packet{type: 4, value: 3286, version: 5}
-
],
-
version: 3
-
}
-
],
-
version: 3
-
},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{type: 4, value: 93, version: 6},
-
%Day16.Packet{
-
type: 5,
-
value: [
-
%Day16.Packet{type: 4, value: 4269, version: 6},
-
%Day16.Packet{type: 4, value: 240, version: 3}
-
],
-
version: 4
-
}
-
],
-
version: 5
-
},
-
%Day16.Packet{
-
type: 3,
-
value: [
-
%Day16.Packet{type: 4, value: 2938, version: 6},
-
%Day16.Packet{type: 4, value: 3, version: 6},
-
%Day16.Packet{type: 4, value: 211, version: 7}
-
],
-
version: 3
-
},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{
-
type: 7,
-
value: [
-
%Day16.Packet{type: 4, value: 159, version: 0},
-
%Day16.Packet{type: 4, value: 159, version: 5}
-
],
-
version: 0
-
},
-
%Day16.Packet{type: 4, value: 28, version: 1}
-
],
-
version: 4
-
},
-
%Day16.Packet{type: 4, value: 84, version: 4},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{type: 4, value: 235, version: 4},
-
%Day16.Packet{
-
type: 6,
-
value: [
-
%Day16.Packet{type: 0, value: [%Day16.Packet{...}, ...], version: 4},
-
%Day16.Packet{type: 0, value: [...], ...}
-
],
-
version: 3
-
}
-
],
-
version: 6
-
},
-
%Day16.Packet{type: 4, value: 1425, version: 4},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{
-
type: 7,
-
value: [%Day16.Packet{type: 0, value: [...], ...}, %Day16.Packet{type: 0, ...}],
-
version: 5
-
},
-
%Day16.Packet{type: 4, value: 13, version: 2}
-
],
-
version: 2
-
},
-
%Day16.Packet{type: 0, value: [%Day16.Packet{type: 4, value: 3121, version: 6}], version: 5},
-
%Day16.Packet{
-
type: 1,
-
value: [
-
%Day16.Packet{type: 4, value: 51, version: 2},
-
%Day16.Packet{type: 4, value: 61, ...},
-
%Day16.Packet{type: 4, ...}
-
],
-
version: 4
-
},
-
%Day16.Packet{
-
type: 1,
-
value: [%Day16.Packet{type: 4, value: 1393, ...}, %Day16.Packet{type: 5, ...}],
-
version: 3
-
},
-
%Day16.Packet{type: 1, value: [%Day16.Packet{type: 7, ...}, %Day16.Packet{...}], version: 3},
-
%Day16.Packet{type: 1, value: [%Day16.Packet{...}, ...], version: 7},
-
%Day16.Packet{type: 3, value: [...], ...},
-
%Day16.Packet{type: 2, ...},
-
%Day16.Packet{...},
-
...
-
],
-
version: 3
-
}
-
```
-
-
### Task 1
-
-
```elixir
-
defmodule Day16.Task1 do
-
alias Day16.Packet
-
-
def sum(%Packet{type: 4, version: version}), do: version
-
-
def sum(%Packet{version: version, value: value}) do
-
Enum.reduce(value, version, &(sum(&1) + &2))
-
end
-
end
-
-
Day16.Task1.sum(input)
-
```
-
-
```output
-
949
-
```
-
-
### Task 2
-
-
```elixir
-
defmodule Day16.Task2 do
-
alias Day16.Packet
-
-
def evaluate(%Packet{type: 0} = packet), do: reduce(packet, 0, &+/2)
-
def evaluate(%Packet{type: 1} = packet), do: reduce(packet, 1, &*/2)
-
def evaluate(%Packet{type: 2} = packet), do: reduce(packet, :inf, &min/2)
-
def evaluate(%Packet{type: 3} = packet), do: reduce(packet, 0, &max/2)
-
-
def evaluate(%Packet{type: 4, value: value}), do: value
-
-
def evaluate(%Packet{type: 5} = packet), do: compare(packet, &>/2)
-
def evaluate(%Packet{type: 6} = packet), do: compare(packet, &</2)
-
def evaluate(%Packet{type: 7} = packet), do: compare(packet, &==/2)
-
-
defp reduce(%Packet{value: value}, initial, op) do
-
Enum.reduce(value, initial, &op.(evaluate(&1), &2))
-
end
-
-
defp compare(%Packet{value: [a, b]}, op) do
-
if op.(evaluate(a), evaluate(b)), do: 1, else: 0
-
end
-
end
-
-
Day16.Task2.evaluate(input)
-
```
-
-
```output
-
1114600142730
-
```