this repo has no description

ft: split solutions to separate notebooks

+69
2021/day1.livemd
··· 1 + <!-- vim:ft=markdown --> 2 + 3 + <!-- livebook:{"persist_outputs":true} --> 4 + 5 + # Day 1 6 + 7 + ## Load input 8 + 9 + ```elixir 10 + stream = 11 + File.stream!("day1.txt") 12 + |> Stream.map(&String.to_integer(String.trim(&1))) 13 + ``` 14 + 15 + ```output 16 + #Stream<[ 17 + enum: %File.Stream{ 18 + line_or_bytes: :line, 19 + modes: [:raw, :read_ahead, :binary], 20 + path: "day1.txt", 21 + raw: true 22 + }, 23 + funs: [#Function<47.58486609/1 in Stream.map/2>] 24 + ]> 25 + ``` 26 + 27 + ## Task 1 28 + 29 + Compute count of consecutive increases 30 + 31 + ```elixir 32 + stream 33 + |> Stream.chunk_every(2, 1, :discard) 34 + |> Enum.count(fn [a, b] -> a < b end) 35 + ``` 36 + 37 + ```output 38 + 1688 39 + ``` 40 + 41 + ## Task 2 42 + 43 + Compute count of consecutive increases of sums of trigrams. 44 + 45 + However we can notice, that if we have list like: 46 + 47 + $$ 48 + [a, b, c, d] 49 + $$ 50 + 51 + Then when we want to compare consecutive trigrams then we compare: 52 + 53 + $$ 54 + a + b + c < b + c + d \\ 55 + a < d 56 + $$ 57 + 58 + So we can traverse each 4 elements and then just compare first and last one 59 + instead of summing and then traversing it again. 60 + 61 + ```elixir 62 + stream 63 + |> Stream.chunk_every(4, 1, :discard) 64 + |> Enum.count(fn [a, _, _, b] -> a < b end) 65 + ``` 66 + 67 + ```output 68 + 1728 69 + ```
+88
2021/day10.livemd
··· 1 + <!-- vim:ft=markdown 2 + --> 3 + 4 + <!-- livebook:{"persist_outputs":true} --> 5 + 6 + # Day 10 7 + 8 + ```elixir 9 + input = 10 + File.stream!("day10.txt") 11 + |> Stream.map(&String.trim/1) 12 + 13 + defmodule Day10 do 14 + @parens %{?( => ?), ?[ => ?], ?< => ?>, ?{ => ?}} 15 + 16 + def parse(input), do: parse(input, []) 17 + 18 + defp parse(<<c>> <> rest, stack) when c in '([{<', do: parse(rest, [@parens[c] | stack]) 19 + defp parse(<<c>> <> rest, [c | stack]), do: parse(rest, stack) 20 + defp parse(<<>>, []), do: :ok 21 + defp parse(<<>>, rest), do: {:incomplete, rest} 22 + defp parse(<<c>> <> _, _), do: {:unexpected, [c]} 23 + end 24 + ``` 25 + 26 + ```output 27 + {:module, Day10, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:parse, 2}} 28 + ``` 29 + 30 + ## Task 1 31 + 32 + ```elixir 33 + points = %{ 34 + ?) => 3, 35 + ?] => 57, 36 + ?} => 1197, 37 + ?> => 25137 38 + } 39 + 40 + input 41 + |> Enum.map(&Day10.parse/1) 42 + |> Enum.map(fn 43 + {:unexpected, [c]} -> points[c] 44 + _ -> 0 45 + end) 46 + |> Enum.sum() 47 + ``` 48 + 49 + ```output 50 + 288291 51 + ``` 52 + 53 + ## Task 2 54 + 55 + ```elixir 56 + points = %{ 57 + ?) => 1, 58 + ?] => 2, 59 + ?} => 3, 60 + ?> => 4 61 + } 62 + 63 + median = fn list -> 64 + sorted = Enum.sort(list) 65 + middle = div(length(list), 2) 66 + 67 + Enum.at(sorted, middle) 68 + end 69 + 70 + input 71 + |> Enum.map(&Day10.parse/1) 72 + |> Enum.flat_map(fn 73 + {:incomplete, rest} -> 74 + [ 75 + Enum.reduce(rest, 0, fn c, acc -> 76 + acc * 5 + points[c] 77 + end) 78 + ] 79 + 80 + _ -> 81 + [] 82 + end) 83 + |> median.() 84 + ``` 85 + 86 + ```output 87 + 820045242 88 + ```
+101
2021/day11.livemd
··· 1 + <!-- vim:ft=markdown 2 + --> 3 + 4 + <!-- livebook:{"persist_outputs":true} --> 5 + 6 + # Day 11 7 + 8 + ```elixir 9 + input = 10 + File.read!("day11.txt") 11 + |> String.split("\n") 12 + |> Enum.map(&String.trim/1) 13 + |> Enum.map(fn line -> 14 + for <<c <- line>>, do: c - ?0 15 + end) 16 + |> Enum.with_index() 17 + |> Enum.flat_map(fn {row, y} -> 18 + for {v, x} <- Enum.with_index(row), do: {{x, y}, v} 19 + end) 20 + |> Map.new() 21 + 22 + defmodule Day11 do 23 + def step(map) do 24 + updated = Map.new(map, fn {k, v} -> {k, v + 1} end) 25 + 26 + lightup(updated, 0) 27 + end 28 + 29 + @diffs for dx <- -1..1, dy <- -1..1, dx != 0 or dy != 0, do: {dx, dy} 30 + 31 + def lightup(map, n) do 32 + map 33 + |> Enum.reduce({map, 0}, fn 34 + {_, v}, acc when v < 10 -> 35 + acc 36 + 37 + {{x, y} = k, _}, {map, count} -> 38 + new_map = 39 + @diffs 40 + |> Enum.reduce(map, fn {dx, dy}, acc -> 41 + point = {x + dx, y + dy} 42 + 43 + case Map.fetch(acc, point) do 44 + {:ok, value} when value != 0 -> %{acc | point => value + 1} 45 + _ -> acc 46 + end 47 + end) 48 + |> Map.put(k, 0) 49 + 50 + {new_map, count + 1} 51 + end) 52 + |> case do 53 + {map, 0} -> {map, n} 54 + {map, m} -> lightup(map, n + m) 55 + end 56 + end 57 + end 58 + ``` 59 + 60 + ```output 61 + {:module, Day11, <<70, 79, 82, 49, 0, 0, 11, ...>>, {:lightup, 2}} 62 + ``` 63 + 64 + ## Task 1 65 + 66 + ```elixir 67 + draw = fn map -> 68 + for x <- 0..9 do 69 + IO.puts(for y <- 0..9, do: ?0 + map[{x, y}]) 70 + end 71 + 72 + IO.puts("") 73 + end 74 + 75 + 1..100 76 + |> Enum.reduce({input, 0}, fn _, {map, n} -> 77 + {new_map, m} = Day11.step(map) 78 + {new_map, n + m} 79 + end) 80 + |> elem(1) 81 + ``` 82 + 83 + ```output 84 + 1688 85 + ``` 86 + 87 + ## Task 2 88 + 89 + ```elixir 90 + Stream.unfold(1, &{&1, &1 + 1}) 91 + |> Enum.reduce_while(input, fn idx, map -> 92 + case Day11.step(map) do 93 + {_, 100} -> {:halt, idx} 94 + {next, _} -> {:cont, next} 95 + end 96 + end) 97 + ``` 98 + 99 + ```output 100 + 403 101 + ```
+83
2021/day12.livemd
··· 1 + <!-- vim:ft=markdown 2 + --> 3 + 4 + <!-- livebook:{"persist_outputs":true} --> 5 + 6 + # Day 12 7 + 8 + ```elixir 9 + input = 10 + File.read!("day12.txt") 11 + |> String.split("\n") 12 + |> Enum.map(&String.split(&1, "-")) 13 + 14 + graph = 15 + Enum.reduce(input, %{}, fn [a, b], acc -> 16 + acc 17 + |> Map.update(a, [b], &[b | &1]) 18 + |> Map.update(b, [a], &[a | &1]) 19 + end) 20 + 21 + defmodule Day12 do 22 + def dfs(graph, start, finish), do: dfs(graph, start, finish, [start]) 23 + 24 + defp dfs(_graph, vertex, vertex, _visited), do: 1 25 + 26 + defp dfs(graph, vertex, finish, visited) do 27 + (graph[vertex] -- visited) 28 + |> Enum.reduce(0, fn vertex, acc -> 29 + visited = if small?(vertex), do: [vertex | visited], else: visited 30 + 31 + acc + dfs(graph, vertex, finish, visited) 32 + end) 33 + end 34 + 35 + def dfs2(graph, start, finish), do: dfs2(graph, start, finish, %{start => :inf}) 36 + 37 + defp dfs2(_graph, vertex, vertex, _visited), do: 1 38 + 39 + defp dfs2(graph, vertex, finish, visited) do 40 + (graph[vertex] -- keys(visited)) 41 + |> Enum.reduce(0, fn vertex, acc -> 42 + visited = if small?(vertex), do: Map.update(visited, vertex, 1, &(&1 + 1)), else: visited 43 + 44 + acc + dfs2(graph, vertex, finish, visited) 45 + end) 46 + end 47 + 48 + defp keys(map) do 49 + if Enum.any?(map, fn {_, v} -> v == 2 end) do 50 + # there is already some vertex visited twice 51 + Map.keys(map) 52 + else 53 + for {k, v} <- map, v > 1, do: k 54 + end 55 + end 56 + 57 + defp small?(<<c>> <> _), do: c in ?a..?z 58 + end 59 + ``` 60 + 61 + ```output 62 + {:module, Day12, <<70, 79, 82, 49, 0, 0, 15, ...>>, {:small?, 1}} 63 + ``` 64 + 65 + ## Task 1 66 + 67 + ```elixir 68 + Day12.dfs(graph, "start", "end") 69 + ``` 70 + 71 + ```output 72 + 4167 73 + ``` 74 + 75 + ## Task 2 76 + 77 + ```elixir 78 + Day12.dfs2(graph, "start", "end") 79 + ``` 80 + 81 + ```output 82 + 98441 83 + ```
+99
2021/day13.livemd
··· 1 + <!-- vim:ft=markdown 2 + --> 3 + 4 + <!-- livebook:{"persist_outputs":true} --> 5 + 6 + # Day 13 7 + 8 + ```elixir 9 + [input, folds] = 10 + File.read!("day13.txt") 11 + |> String.trim() 12 + |> String.split("\n\n") 13 + 14 + input = 15 + input 16 + |> String.split("\n") 17 + |> Enum.map(fn line -> 18 + [x, y] = String.split(line, ",") 19 + 20 + {String.to_integer(x), String.to_integer(y)} 21 + end) 22 + |> MapSet.new() 23 + 24 + folds = 25 + folds 26 + |> String.split("\n") 27 + |> Enum.map(fn 28 + "fold along " <> <<c>> <> "=" <> rest -> 29 + {String.to_atom(<<c>>), String.to_integer(rest)} 30 + end) 31 + 32 + defmodule Day13 do 33 + def fold({orientation, pos}, set) do 34 + Enum.reduce(set, MapSet.new(), fn point, acc -> 35 + new_point = folded_coords(orientation, pos, point) 36 + 37 + MapSet.put(acc, new_point) 38 + end) 39 + end 40 + 41 + defp folded_coords(:x, col, {x, y}) when x > col, do: {abs(2 * col - x), y} 42 + defp folded_coords(:y, row, {x, y}) when y > row, do: {x, abs(2 * row - y)} 43 + defp folded_coords(_, _, point), do: point 44 + 45 + def draw(set) do 46 + set 47 + |> Enum.group_by(&elem(&1, 1)) 48 + |> Enum.sort() 49 + |> Enum.map(fn {_, points} -> 50 + points 51 + |> Enum.map(&elem(&1, 0)) 52 + |> Enum.sort() 53 + |> Enum.chunk_every(2, 1) 54 + |> Enum.map(fn 55 + [a, b] -> b - a 56 + _ -> 0 57 + end) 58 + |> Enum.map(&String.pad_trailing("█", &1, " ")) 59 + end) 60 + |> Enum.join("\n") 61 + end 62 + end 63 + ``` 64 + 65 + ```output 66 + {:module, Day13, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:draw, 1}} 67 + ``` 68 + 69 + ## Task 1 70 + 71 + ```elixir 72 + Day13.fold(hd(folds), input) |> MapSet.size() 73 + ``` 74 + 75 + ```output 76 + 802 77 + ``` 78 + 79 + ## Task 2 80 + 81 + ```elixir 82 + Enum.reduce(folds, input, &Day13.fold/2) 83 + |> Day13.draw() 84 + |> IO.puts() 85 + ``` 86 + 87 + ```output 88 + ███ █ █ █ █ ████ ████ ██ █ █ ███ 89 + █ █ █ █ █ █ █ █ █ █ █ █ █ █ 90 + █ █ ██ ████ ███ █ █ █ █ ███ 91 + ███ █ █ █ █ █ █ █ ██ █ █ █ █ 92 + █ █ █ █ █ █ █ █ █ █ █ █ █ █ 93 + █ █ █ █ █ █ █ ████ ███ ██ ███ 94 + ``` 95 + 96 + ```output 97 + :ok 98 + ``` 99 +
+102
2021/day14.livemd
··· 1 + <!-- vim:ft=markdown 2 + --> 3 + 4 + <!-- livebook:{"persist_outputs":true} --> 5 + 6 + # Day 14 7 + 8 + ```elixir 9 + [polymer_raw, subs] = 10 + File.read!("day14.txt") 11 + |> String.split("\n\n") 12 + 13 + <<first, _::binary>> = polymer_raw 14 + 15 + polymer = 16 + {first, 17 + polymer_raw 18 + |> String.to_charlist() 19 + |> Enum.chunk_every(2, 1, :discard) 20 + |> Enum.frequencies()} 21 + 22 + subs = 23 + subs 24 + |> String.trim() 25 + |> String.split(["\n", " -> "]) 26 + |> Enum.chunk_every(2) 27 + |> Map.new(fn [pair, <<new>>] -> {String.to_charlist(pair), new} end) 28 + 29 + defmodule Day14 do 30 + def expand({hd, polymer}, subs) do 31 + new = 32 + polymer 33 + |> Enum.reduce(%{}, fn {[a, b] = pair, count}, acc -> 34 + s = Map.fetch!(subs, pair) 35 + 36 + acc 37 + |> Map.update([a, s], count, &(&1 + count)) 38 + |> Map.update([s, b], count, &(&1 + count)) 39 + end) 40 + 41 + {hd, new} 42 + end 43 + 44 + def expand_naive(polymer, subs) do 45 + polymer 46 + |> to_charlist() 47 + |> Enum.chunk_every(2, 1, :discard) 48 + |> Enum.flat_map(fn [a, b] = pair -> 49 + [a, subs[pair], b] 50 + end) 51 + |> List.to_string() 52 + end 53 + 54 + def frequencies({hd, polymer}) do 55 + polymer 56 + |> Enum.reduce(%{hd => 1}, fn {[_, b], count}, acc -> 57 + Map.update(acc, b, count, &(&1 + count)) 58 + end) 59 + end 60 + end 61 + ``` 62 + 63 + ```output 64 + {:module, Day14, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:frequencies, 1}} 65 + ``` 66 + 67 + ## Task 1 68 + 69 + ```elixir 70 + {{_, min}, {_, max}} = 71 + 1..10 72 + |> Enum.reduce(polymer, fn _, acc -> 73 + Day14.expand(acc, subs) 74 + end) 75 + |> Day14.frequencies() 76 + |> Enum.min_max_by(&elem(&1, 1)) 77 + 78 + # 2768 79 + max - min 80 + ``` 81 + 82 + ```output 83 + 2768 84 + ``` 85 + 86 + ## Task 2 87 + 88 + ```elixir 89 + {{_, min}, {_, max}} = 90 + 1..40 91 + |> Enum.reduce(polymer, fn _, acc -> 92 + Day14.expand(acc, subs) 93 + end) 94 + |> Day14.frequencies() 95 + |> Enum.min_max_by(&elem(&1, 1)) 96 + 97 + max - min 98 + ``` 99 + 100 + ```output 101 + 2914365137499 102 + ```
+117
2021/day15.livemd
··· 1 + <!-- vim:ft=markdown 2 + --> 3 + 4 + <!-- livebook:{"persist_outputs":true} --> 5 + 6 + # Day 15 7 + 8 + ```elixir 9 + input = 10 + File.read!("day15.txt") 11 + |> String.trim() 12 + |> String.split("\n") 13 + |> Enum.map(&String.to_charlist/1) 14 + |> Enum.with_index() 15 + |> Enum.flat_map(fn {row, y} -> 16 + row 17 + |> Enum.with_index() 18 + |> Enum.map(fn {v, x} -> {{x, y}, v - ?0} end) 19 + end) 20 + |> Map.new() 21 + 22 + {width, height} = Enum.max(Map.keys(input)) 23 + ``` 24 + 25 + ```output 26 + {99, 99} 27 + ``` 28 + 29 + ## Task 1 30 + 31 + ```elixir 32 + shortest_paths = 33 + for y <- height..0//-1, 34 + x <- width..0//-1, 35 + reduce: %{} do 36 + acc -> 37 + right = acc[{x + 1, y}] 38 + bottom = acc[{x, y + 1}] 39 + 40 + value = 41 + case {right, bottom} do 42 + {nil, nil} -> input[{x, y}] 43 + _ -> input[{x, y}] + min(right, bottom) 44 + end 45 + 46 + Map.put(acc, {x, y}, value) 47 + end 48 + 49 + shortest_paths[{0, 0}] - input[{0, 0}] 50 + ``` 51 + 52 + ```output 53 + 429 54 + ``` 55 + 56 + ## Task 2 57 + 58 + ```elixir 59 + defmodule Day15.Task2 do 60 + def expand_grid(board) do 61 + {width, height} = Enum.max(Map.keys(board)) 62 + 63 + board 64 + |> Enum.flat_map(fn {{x, y}, v} -> 65 + for rx <- 0..4, ry <- 0..4 do 66 + {{x + (width + 1) * rx, y + (height + 1) * ry}, rem(v - 1 + rx + ry, 9) + 1} 67 + end 68 + end) 69 + |> Map.new() 70 + end 71 + 72 + def find_path(board, start, finish) do 73 + dists = :gb_sets.singleton({0, start}) 74 + 75 + find_path(board, finish, dists, MapSet.new()) 76 + end 77 + 78 + @surround for dx <- -1..1, dy <- -1..1, abs(dx) != abs(dy), do: {dx, dy} 79 + 80 + def find_path(board, finish, dists, visited) do 81 + {{dist, {x, y} = curr}, dists} = :gb_sets.take_smallest(dists) 82 + 83 + if curr == finish do 84 + dist 85 + else 86 + visited = MapSet.put(visited, curr) 87 + 88 + dists = 89 + for {dx, dy} <- @surround, 90 + next = {x + dx, y + dy}, 91 + next not in visited, 92 + is_map_key(board, next), 93 + alt = dist + board[next], 94 + reduce: dists do 95 + acc -> 96 + :gb_sets.add_element({alt, next}, acc) 97 + end 98 + 99 + find_path(board, finish, dists, visited) 100 + end 101 + end 102 + end 103 + ``` 104 + 105 + ```output 106 + {:module, Day15.Task2, <<70, 79, 82, 49, 0, 0, 16, ...>>, {:find_path, 4}} 107 + ``` 108 + 109 + ```elixir 110 + input 111 + |> Day15.Task2.expand_grid() 112 + |> Day15.Task2.find_path({0, 0}, {499, 499}) 113 + ``` 114 + 115 + ```output 116 + 2844 117 + ```
+610
2021/day16.livemd
··· 1 + <!-- vim:ft=markdown --> 2 + 3 + <!-- livebook:{"persist_outputs":true} --> 4 + 5 + # Day 16 6 + 7 + ## Section 8 + 9 + ```elixir 10 + defmodule Day16 do 11 + defmodule Packet do 12 + defstruct [:version, :type, :value] 13 + end 14 + 15 + def decode(<<version::3, 4::3, rest::bitstring>>) do 16 + {value, rest} = literal(rest, 0) 17 + 18 + {%Packet{type: 4, version: version, value: value}, rest} 19 + end 20 + 21 + def decode(<<version::3, type::3, 0::1, length::15, rest::bitstring>>) do 22 + <<subpackets::bitstring-size(length), rest::bitstring>> = rest 23 + 24 + {%Packet{type: type, version: version, value: decode_all(subpackets)}, rest} 25 + end 26 + 27 + def decode(<<version::3, type::3, 1::1, length::11, rest::bitstring>>) do 28 + {value, rest} = Enum.map_reduce(1..length, rest, fn _, acc -> decode(acc) end) 29 + 30 + {%Packet{type: type, version: version, value: value}, rest} 31 + end 32 + 33 + def decode_all(input) do 34 + case decode(input) do 35 + {packet, <<>>} -> [packet] 36 + {packet, rest} -> [packet | decode_all(rest)] 37 + end 38 + end 39 + 40 + defp literal(<<1::1, bits::4, rest::bitstring>>, acc) do 41 + literal(rest, acc * 0x10 + bits) 42 + end 43 + 44 + defp literal(<<0::1, bits::4, rest::bitstring>>, acc) do 45 + {acc * 0x10 + bits, rest} 46 + end 47 + end 48 + 49 + input = 50 + File.read!("day16.txt") 51 + |> String.trim() 52 + |> Base.decode16!() 53 + |> Day16.decode() 54 + |> elem(0) 55 + ``` 56 + 57 + ```output 58 + %Day16.Packet{ 59 + type: 0, 60 + value: [ 61 + %Day16.Packet{ 62 + type: 1, 63 + value: [ 64 + %Day16.Packet{type: 4, value: 20, version: 6}, 65 + %Day16.Packet{ 66 + type: 6, 67 + value: [ 68 + %Day16.Packet{type: 4, value: 14747, version: 1}, 69 + %Day16.Packet{type: 4, value: 14747, version: 6} 70 + ], 71 + version: 2 72 + } 73 + ], 74 + version: 1 75 + }, 76 + %Day16.Packet{ 77 + type: 3, 78 + value: [ 79 + %Day16.Packet{type: 4, value: 15, version: 5}, 80 + %Day16.Packet{type: 4, value: 10, version: 6} 81 + ], 82 + version: 7 83 + }, 84 + %Day16.Packet{ 85 + type: 1, 86 + value: [ 87 + %Day16.Packet{ 88 + type: 7, 89 + value: [ 90 + %Day16.Packet{type: 4, value: 2184, version: 1}, 91 + %Day16.Packet{type: 4, value: 130250, version: 6} 92 + ], 93 + version: 6 94 + }, 95 + %Day16.Packet{type: 4, value: 5442981, version: 4} 96 + ], 97 + version: 6 98 + }, 99 + %Day16.Packet{type: 4, value: 8281083, version: 0}, 100 + %Day16.Packet{ 101 + type: 2, 102 + value: [ 103 + %Day16.Packet{type: 4, value: 102, version: 5}, 104 + %Day16.Packet{type: 4, value: 647125, version: 7} 105 + ], 106 + version: 1 107 + }, 108 + %Day16.Packet{ 109 + type: 1, 110 + value: [ 111 + %Day16.Packet{type: 4, value: 178, version: 1}, 112 + %Day16.Packet{type: 4, value: 176, version: 6} 113 + ], 114 + version: 0 115 + }, 116 + %Day16.Packet{ 117 + type: 1, 118 + value: [ 119 + %Day16.Packet{ 120 + type: 6, 121 + value: [ 122 + %Day16.Packet{ 123 + type: 0, 124 + value: [ 125 + %Day16.Packet{type: 4, value: 13, version: 1}, 126 + %Day16.Packet{type: 4, value: 8, version: 4}, 127 + %Day16.Packet{type: 4, value: 4, version: 3} 128 + ], 129 + version: 2 130 + }, 131 + %Day16.Packet{ 132 + type: 0, 133 + value: [ 134 + %Day16.Packet{type: 4, value: 7, version: 7}, 135 + %Day16.Packet{type: 4, value: 11, version: 3}, 136 + %Day16.Packet{type: 4, value: 14, version: 2} 137 + ], 138 + version: 4 139 + } 140 + ], 141 + version: 7 142 + }, 143 + %Day16.Packet{type: 4, value: 2724, version: 0} 144 + ], 145 + version: 1 146 + }, 147 + %Day16.Packet{type: 4, value: 9, version: 4}, 148 + %Day16.Packet{ 149 + type: 1, 150 + value: [ 151 + %Day16.Packet{ 152 + type: 5, 153 + value: [ 154 + %Day16.Packet{type: 4, value: 7240238, version: 2}, 155 + %Day16.Packet{type: 4, value: 233, version: 7} 156 + ], 157 + version: 1 158 + }, 159 + %Day16.Packet{type: 4, value: 37, version: 6} 160 + ], 161 + version: 4 162 + }, 163 + %Day16.Packet{type: 2, value: [%Day16.Packet{type: 4, value: 2, version: 5}], version: 5}, 164 + %Day16.Packet{type: 4, value: 53749, version: 4}, 165 + %Day16.Packet{type: 4, value: 11, version: 3}, 166 + %Day16.Packet{ 167 + type: 1, 168 + value: [ 169 + %Day16.Packet{type: 4, value: 382979, version: 4}, 170 + %Day16.Packet{ 171 + type: 5, 172 + value: [ 173 + %Day16.Packet{ 174 + type: 0, 175 + value: [ 176 + %Day16.Packet{type: 4, value: 15, version: 1}, 177 + %Day16.Packet{type: 4, value: 10, version: 0}, 178 + %Day16.Packet{type: 4, value: 2, version: 6} 179 + ], 180 + version: 5 181 + }, 182 + %Day16.Packet{ 183 + type: 0, 184 + value: [ 185 + %Day16.Packet{type: 4, value: 4, version: 7}, 186 + %Day16.Packet{type: 4, value: 7, version: 4}, 187 + %Day16.Packet{type: 4, value: 2, version: 5} 188 + ], 189 + version: 1 190 + } 191 + ], 192 + version: 6 193 + } 194 + ], 195 + version: 2 196 + }, 197 + %Day16.Packet{type: 4, value: 21251, version: 1}, 198 + %Day16.Packet{ 199 + type: 1, 200 + value: [ 201 + %Day16.Packet{type: 4, value: 163, version: 6}, 202 + %Day16.Packet{ 203 + type: 5, 204 + value: [ 205 + %Day16.Packet{type: 4, value: 59, version: 3}, 206 + %Day16.Packet{type: 4, value: 836848134220, version: 1} 207 + ], 208 + version: 6 209 + } 210 + ], 211 + version: 2 212 + }, 213 + %Day16.Packet{ 214 + type: 2, 215 + value: [ 216 + %Day16.Packet{ 217 + type: 0, 218 + value: [ 219 + %Day16.Packet{ 220 + type: 0, 221 + value: [ 222 + %Day16.Packet{ 223 + type: 2, 224 + value: [ 225 + %Day16.Packet{ 226 + type: 2, 227 + value: [ 228 + %Day16.Packet{ 229 + type: 0, 230 + value: [ 231 + %Day16.Packet{ 232 + type: 3, 233 + value: [ 234 + %Day16.Packet{ 235 + type: 2, 236 + value: [ 237 + %Day16.Packet{ 238 + type: 2, 239 + value: [ 240 + %Day16.Packet{ 241 + type: 3, 242 + value: [%Day16.Packet{type: 0, value: [...], ...}], 243 + version: 0 244 + } 245 + ], 246 + version: 1 247 + } 248 + ], 249 + version: 1 250 + } 251 + ], 252 + version: 7 253 + } 254 + ], 255 + version: 0 256 + } 257 + ], 258 + version: 6 259 + } 260 + ], 261 + version: 2 262 + } 263 + ], 264 + version: 2 265 + } 266 + ], 267 + version: 6 268 + } 269 + ], 270 + version: 7 271 + }, 272 + %Day16.Packet{type: 1, value: [%Day16.Packet{type: 4, value: 44, version: 4}], version: 7}, 273 + %Day16.Packet{ 274 + type: 1, 275 + value: [ 276 + %Day16.Packet{type: 4, value: 255, version: 2}, 277 + %Day16.Packet{type: 4, value: 91, version: 5}, 278 + %Day16.Packet{type: 4, value: 176, version: 5}, 279 + %Day16.Packet{type: 4, value: 23, version: 1} 280 + ], 281 + version: 7 282 + }, 283 + %Day16.Packet{ 284 + type: 3, 285 + value: [ 286 + %Day16.Packet{type: 4, value: 11520, version: 4}, 287 + %Day16.Packet{type: 4, value: 6069, version: 0}, 288 + %Day16.Packet{type: 4, value: 1089149511401, version: 4}, 289 + %Day16.Packet{type: 4, value: 158, version: 2}, 290 + %Day16.Packet{type: 4, value: 620605, version: 0} 291 + ], 292 + version: 2 293 + }, 294 + %Day16.Packet{ 295 + type: 0, 296 + value: [ 297 + %Day16.Packet{type: 4, value: 62788, version: 7}, 298 + %Day16.Packet{type: 4, value: 9410622, version: 2}, 299 + %Day16.Packet{type: 4, value: 15912821, version: 4} 300 + ], 301 + version: 4 302 + }, 303 + %Day16.Packet{ 304 + type: 1, 305 + value: [ 306 + %Day16.Packet{type: 4, value: 22416, version: 5}, 307 + %Day16.Packet{ 308 + type: 5, 309 + value: [ 310 + %Day16.Packet{type: 4, value: 246, version: 1}, 311 + %Day16.Packet{type: 4, value: 246, version: 4} 312 + ], 313 + version: 2 314 + } 315 + ], 316 + version: 0 317 + }, 318 + %Day16.Packet{type: 3, value: [%Day16.Packet{type: 4, value: 13008601, version: 5}], version: 0}, 319 + %Day16.Packet{ 320 + type: 0, 321 + value: [ 322 + %Day16.Packet{ 323 + type: 1, 324 + value: [ 325 + %Day16.Packet{type: 4, value: 3, version: 4}, 326 + %Day16.Packet{type: 4, value: 14, version: 1}, 327 + %Day16.Packet{type: 4, value: 5, version: 0} 328 + ], 329 + version: 5 330 + }, 331 + %Day16.Packet{ 332 + type: 1, 333 + value: [ 334 + %Day16.Packet{type: 4, value: 2, version: 1}, 335 + %Day16.Packet{type: 4, value: 14, version: 1}, 336 + %Day16.Packet{type: 4, value: 10, version: 1} 337 + ], 338 + version: 6 339 + }, 340 + %Day16.Packet{ 341 + type: 1, 342 + value: [ 343 + %Day16.Packet{type: 4, value: 8, version: 3}, 344 + %Day16.Packet{type: 4, value: 6, version: 6}, 345 + %Day16.Packet{type: 4, value: 11, version: 0} 346 + ], 347 + version: 1 348 + } 349 + ], 350 + version: 5 351 + }, 352 + %Day16.Packet{ 353 + type: 1, 354 + value: [ 355 + %Day16.Packet{type: 4, value: 32940592237, version: 2}, 356 + %Day16.Packet{ 357 + type: 5, 358 + value: [ 359 + %Day16.Packet{type: 4, value: 100, version: 1}, 360 + %Day16.Packet{type: 4, value: 1393232728, version: 2} 361 + ], 362 + version: 2 363 + } 364 + ], 365 + version: 0 366 + }, 367 + %Day16.Packet{type: 4, value: 89, version: 3}, 368 + %Day16.Packet{ 369 + type: 2, 370 + value: [ 371 + %Day16.Packet{type: 4, value: 204, version: 6}, 372 + %Day16.Packet{type: 4, value: 260321821, version: 2}, 373 + %Day16.Packet{type: 4, value: 225241983, version: 6} 374 + ], 375 + version: 0 376 + }, 377 + %Day16.Packet{ 378 + type: 0, 379 + value: [ 380 + %Day16.Packet{type: 4, value: 960899, version: 3}, 381 + %Day16.Packet{type: 4, value: 58997, version: 5}, 382 + %Day16.Packet{type: 4, value: 54940, version: 6}, 383 + %Day16.Packet{type: 4, value: 10974, version: 2}, 384 + %Day16.Packet{type: 4, value: 882043, version: 2} 385 + ], 386 + version: 0 387 + }, 388 + %Day16.Packet{ 389 + type: 1, 390 + value: [ 391 + %Day16.Packet{ 392 + type: 6, 393 + value: [ 394 + %Day16.Packet{type: 4, value: 35633017255, version: 4}, 395 + %Day16.Packet{type: 4, value: 35633017255, version: 2} 396 + ], 397 + version: 3 398 + }, 399 + %Day16.Packet{type: 4, value: 1359, version: 6} 400 + ], 401 + version: 6 402 + }, 403 + %Day16.Packet{ 404 + type: 1, 405 + value: [ 406 + %Day16.Packet{type: 4, value: 92, version: 4}, 407 + %Day16.Packet{type: 4, value: 38, version: 3}, 408 + %Day16.Packet{type: 4, value: 160, version: 5}, 409 + %Day16.Packet{type: 4, value: 111, version: 1}, 410 + %Day16.Packet{type: 4, value: 64, version: 4} 411 + ], 412 + version: 4 413 + }, 414 + %Day16.Packet{ 415 + type: 0, 416 + value: [ 417 + %Day16.Packet{type: 4, value: 2541, version: 3}, 418 + %Day16.Packet{type: 4, value: 263947, version: 6}, 419 + %Day16.Packet{type: 4, value: 7686705, version: 5}, 420 + %Day16.Packet{type: 4, value: 31, version: 4} 421 + ], 422 + version: 2 423 + }, 424 + %Day16.Packet{ 425 + type: 1, 426 + value: [ 427 + %Day16.Packet{ 428 + type: 6, 429 + value: [ 430 + %Day16.Packet{type: 4, value: 3193865, version: 1}, 431 + %Day16.Packet{type: 4, value: 20223, version: 7} 432 + ], 433 + version: 2 434 + }, 435 + %Day16.Packet{type: 4, value: 9328522, version: 5} 436 + ], 437 + version: 0 438 + }, 439 + %Day16.Packet{ 440 + type: 2, 441 + value: [ 442 + %Day16.Packet{type: 4, value: 5, version: 4}, 443 + %Day16.Packet{type: 4, value: 7, version: 3}, 444 + %Day16.Packet{type: 4, value: 179420284, version: 4}, 445 + %Day16.Packet{type: 4, value: 19890, version: 1}, 446 + %Day16.Packet{type: 4, value: 2655, version: 0} 447 + ], 448 + version: 7 449 + }, 450 + %Day16.Packet{ 451 + type: 1, 452 + value: [ 453 + %Day16.Packet{type: 4, value: 862089, version: 1}, 454 + %Day16.Packet{ 455 + type: 6, 456 + value: [ 457 + %Day16.Packet{type: 4, value: 248, version: 3}, 458 + %Day16.Packet{type: 4, value: 3286, version: 5} 459 + ], 460 + version: 3 461 + } 462 + ], 463 + version: 3 464 + }, 465 + %Day16.Packet{ 466 + type: 1, 467 + value: [ 468 + %Day16.Packet{type: 4, value: 93, version: 6}, 469 + %Day16.Packet{ 470 + type: 5, 471 + value: [ 472 + %Day16.Packet{type: 4, value: 4269, version: 6}, 473 + %Day16.Packet{type: 4, value: 240, version: 3} 474 + ], 475 + version: 4 476 + } 477 + ], 478 + version: 5 479 + }, 480 + %Day16.Packet{ 481 + type: 3, 482 + value: [ 483 + %Day16.Packet{type: 4, value: 2938, version: 6}, 484 + %Day16.Packet{type: 4, value: 3, version: 6}, 485 + %Day16.Packet{type: 4, value: 211, version: 7} 486 + ], 487 + version: 3 488 + }, 489 + %Day16.Packet{ 490 + type: 1, 491 + value: [ 492 + %Day16.Packet{ 493 + type: 7, 494 + value: [ 495 + %Day16.Packet{type: 4, value: 159, version: 0}, 496 + %Day16.Packet{type: 4, value: 159, version: 5} 497 + ], 498 + version: 0 499 + }, 500 + %Day16.Packet{type: 4, value: 28, version: 1} 501 + ], 502 + version: 4 503 + }, 504 + %Day16.Packet{type: 4, value: 84, version: 4}, 505 + %Day16.Packet{ 506 + type: 1, 507 + value: [ 508 + %Day16.Packet{type: 4, value: 235, version: 4}, 509 + %Day16.Packet{ 510 + type: 6, 511 + value: [ 512 + %Day16.Packet{type: 0, value: [%Day16.Packet{...}, ...], version: 4}, 513 + %Day16.Packet{type: 0, value: [...], ...} 514 + ], 515 + version: 3 516 + } 517 + ], 518 + version: 6 519 + }, 520 + %Day16.Packet{type: 4, value: 1425, version: 4}, 521 + %Day16.Packet{ 522 + type: 1, 523 + value: [ 524 + %Day16.Packet{ 525 + type: 7, 526 + value: [%Day16.Packet{type: 0, value: [...], ...}, %Day16.Packet{type: 0, ...}], 527 + version: 5 528 + }, 529 + %Day16.Packet{type: 4, value: 13, version: 2} 530 + ], 531 + version: 2 532 + }, 533 + %Day16.Packet{type: 0, value: [%Day16.Packet{type: 4, value: 3121, version: 6}], version: 5}, 534 + %Day16.Packet{ 535 + type: 1, 536 + value: [ 537 + %Day16.Packet{type: 4, value: 51, version: 2}, 538 + %Day16.Packet{type: 4, value: 61, ...}, 539 + %Day16.Packet{type: 4, ...} 540 + ], 541 + version: 4 542 + }, 543 + %Day16.Packet{ 544 + type: 1, 545 + value: [%Day16.Packet{type: 4, value: 1393, ...}, %Day16.Packet{type: 5, ...}], 546 + version: 3 547 + }, 548 + %Day16.Packet{type: 1, value: [%Day16.Packet{type: 7, ...}, %Day16.Packet{...}], version: 3}, 549 + %Day16.Packet{type: 1, value: [%Day16.Packet{...}, ...], version: 7}, 550 + %Day16.Packet{type: 3, value: [...], ...}, 551 + %Day16.Packet{type: 2, ...}, 552 + %Day16.Packet{...}, 553 + ... 554 + ], 555 + version: 3 556 + } 557 + ``` 558 + 559 + ## Task 1 560 + 561 + ```elixir 562 + defmodule Day16.Task1 do 563 + alias Day16.Packet 564 + 565 + def sum(%Packet{type: 4, version: version}), do: version 566 + 567 + def sum(%Packet{version: version, value: value}) do 568 + Enum.reduce(value, version, &(sum(&1) + &2)) 569 + end 570 + end 571 + 572 + Day16.Task1.sum(input) 573 + ``` 574 + 575 + ```output 576 + 949 577 + ``` 578 + 579 + ## Task 2 580 + 581 + ```elixir 582 + defmodule Day16.Task2 do 583 + alias Day16.Packet 584 + 585 + def evaluate(%Packet{type: 0} = packet), do: reduce(packet, 0, &+/2) 586 + def evaluate(%Packet{type: 1} = packet), do: reduce(packet, 1, &*/2) 587 + def evaluate(%Packet{type: 2} = packet), do: reduce(packet, :inf, &min/2) 588 + def evaluate(%Packet{type: 3} = packet), do: reduce(packet, 0, &max/2) 589 + 590 + def evaluate(%Packet{type: 4, value: value}), do: value 591 + 592 + def evaluate(%Packet{type: 5} = packet), do: compare(packet, &>/2) 593 + def evaluate(%Packet{type: 6} = packet), do: compare(packet, &</2) 594 + def evaluate(%Packet{type: 7} = packet), do: compare(packet, &==/2) 595 + 596 + defp reduce(%Packet{value: value}, initial, op) do 597 + Enum.reduce(value, initial, &op.(evaluate(&1), &2)) 598 + end 599 + 600 + defp compare(%Packet{value: [a, b]}, op) do 601 + if op.(evaluate(a), evaluate(b)), do: 1, else: 0 602 + end 603 + end 604 + 605 + Day16.Task2.evaluate(input) 606 + ``` 607 + 608 + ```output 609 + 1114600142730 610 + ```
+185
2021/day17.livemd
··· 1 + <!-- vim:ft=markdown --> 2 + 3 + <!-- livebook:{"persist_outputs":true} --> 4 + 5 + # Day 17 6 + 7 + ## Setup 8 + 9 + ```elixir 10 + input = File.read!("day17.txt") 11 + # input = "target area: x=117..7310, y=-9546..-89" 12 + 13 + IO.puts(input) 14 + 15 + %{"a_x" => a_x, "a_y" => a_y, "b_x" => b_x, "b_y" => b_y} = 16 + Regex.named_captures( 17 + ~r/target area: x=(?<a_x>-?\d+)\.\.(?<b_x>-?\d+), y=(?<a_y>-?\d+)\.\.(?<b_y>-?\d+)/, 18 + input 19 + ) 20 + 21 + a = %{x: String.to_integer(a_x), y: String.to_integer(a_y)} 22 + b = %{x: String.to_integer(b_x), y: String.to_integer(b_y)} 23 + 24 + [a: a, b: b] 25 + ``` 26 + 27 + ```output 28 + target area: x=288..330, y=-96..-50 29 + ``` 30 + 31 + ```output 32 + [a: %{x: 288, y: -96}, b: %{x: 330, y: -50}] 33 + ``` 34 + 35 + ## Task 1 36 + 37 + ### Lemma 1 38 + 39 + The horizontal velocity there can be ignored, as we can always find a horizontal velocity 40 + that will reach the target area and will reduce the velocity to $$0$$, which mean that all 41 + further movement will happen only in one dimension. That velocity is: 42 + 43 + $$ 44 + v_x = \lceil \frac{-1 + \sqrt{1 + 8b_x}}{2} \rceil 45 + $$ 46 + 47 + #### Proof: 48 + 49 + Which came from the fact that distance traveled by the projectile is sum of the arithmetic 50 + sequence with $$r = -1$$, so the distance traveled is: 51 + 52 + $$ 53 + s_x = \frac{2v_{x0} - t + 1}{2}t 54 + $$ 55 + 56 + Where $$t$$ is travel time. As $$v_x(t) = v_{x0}$$ then $$v_x(t) = 0 \implies t = v_{x0}$$, 57 + so after substituting $$t$$ we get: 58 + 59 + $$ 60 + s_x = \frac{2v_{x0} - v_{x0} + 1}{2}v_{x0} \\ 61 + s_x = \frac{v_{x0} + 1}{2}v_{x0} \\ 62 + s_x = \frac{v_{x0}^2 + v_{x0}}{2} 63 + $$ 64 + 65 + As we want to find the nearest column where we want to stop movement in $$OX$$ then 66 + we are looking at $$s_x = b_x$$: 67 + 68 + $$ 69 + b_x = \frac{v_{x0}^2 + v_{x0}}{2} \\ 70 + 2b_x = v_{x0}^2 + v_{x0} \\ 71 + 0 = v_{x0}^2 + v_{x0} - 2b_x 72 + $$ 73 + 74 + The soultions for these equation are in form of: 75 + 76 + $$ 77 + v_{x0} = \frac{-1 \mp \sqrt{1 + 8b_x}}{2} 78 + $$ 79 + 80 + As we assume that $$b_x \gt 0$$, then the solutions will always be trivial. Additionally 81 + we do not care about negative roots, so we can take only: 82 + 83 + $$ 84 + v_{x0} = \frac{-1 + \sqrt{1 + 8b_x}}{2} 85 + $$ 86 + 87 + As this can be fractional and we want $$v_x0 \in \mathbb{Z}$$ and assume that target is 88 + big enough to have at least one point that we can land on, then we can simply round velocity 89 + up: 90 + 91 + $$ 92 + v_x = \lceil \frac{-1 + \sqrt{1 + 8b_x}}{2} \rceil\\ 93 + $$ 94 + 95 + $$\blacksquare$$ 96 + 97 + ### Lemma 2 98 + 99 + TODO 100 + 101 + As 102 + 103 + $$ 104 + v_{y0} = \frac{2a_y - t + t^2}{2t} 105 + $$ 106 + 107 + Left to prove that $$v_0$$ will have highest possible value for $$t = -2a_y$$. 108 + Then above equation reduces like that: 109 + 110 + $$ 111 + v_{y0} = \frac{2a_y + 2a_y + 4a_y^2}{4a_y} \\ 112 + v_{y0} = \frac{4a_y + 4a_y^2}{4a_y} \\ 113 + v_{y0} = 1 + a_y 114 + $$ 115 + 116 + ```elixir 117 + v_y = -min(a.y, b.y) - 1 118 + 119 + {v_y, v_y * (v_y + 1) / 2} 120 + ``` 121 + 122 + ```output 123 + {95, 4560.0} 124 + ``` 125 + 126 + ## Task 2 127 + 128 + ```elixir 129 + solveq_pos = fn a, b, c -> 130 + [ 131 + (-b - :math.sqrt(b * b - 4 * a * c)) / (2 * a), 132 + (-b + :math.sqrt(b * b - 4 * a * c)) / (2 * a) 133 + ] 134 + |> Enum.filter(&(&1 > 0)) 135 + end 136 + 137 + v_xmin_rest = ceil(hd(solveq_pos.(1, 1, -2 * min(a.x, b.x)))) 138 + v_xmax_rest = floor(hd(solveq_pos.(1, 1, -2 * max(a.x, b.x)))) 139 + 140 + v_ymax = -min(a.y, b.y) - 1 141 + v_ymin = min(a.y, b.y) 142 + 143 + {xmin, xmax} = Enum.min_max([a.x, b.x]) 144 + {ymin, ymax} = Enum.min_max([a.y, b.y]) 145 + 146 + offset = fn 147 + 0 -> {1, -1} 148 + v_y when v_y > 0 -> {2 * v_y + 1, -v_y - 1} 149 + v_y -> {0, v_y} 150 + end 151 + 152 + v_y_pairs = 153 + for v_y <- v_ymin..v_ymax, 154 + {offset, fv_y} = offset.(v_y), 155 + tmin <- solveq_pos.(-1, 2 * fv_y + 1, -2 * ymax), 156 + tmax <- solveq_pos.(-1, 2 * fv_y + 1, -2 * ymin), 157 + ceil(tmin) <= floor(tmax), 158 + t <- ceil(tmin)..floor(tmax), 159 + do: {v_y, t + offset} 160 + 161 + v_x_pairs = 162 + for t <- Enum.uniq(Enum.map(v_y_pairs, &elem(&1, 1))), 163 + v_xmin_move = ceil((2 * xmin / t + t - 1) / 2), 164 + v_xmax_move = floor((2 * xmax / t + t - 1) / 2), 165 + xrange = Enum.filter(v_xmin_move..v_xmax_move, &(&1 >= t)), 166 + xrange = 167 + if(v_xmin_rest < t, 168 + do: Enum.concat(xrange, v_xmin_rest..min(t, v_xmax_rest)), 169 + else: xrange 170 + ), 171 + v_x <- MapSet.new(xrange), 172 + do: {t, v_x} 173 + 174 + pairs = 175 + for {v_y, t} <- v_y_pairs, 176 + {^t, v_x} <- v_x_pairs, 177 + into: MapSet.new(), 178 + do: {v_x, v_y} 179 + 180 + MapSet.size(pairs) 181 + ``` 182 + 183 + ```output 184 + 3344 185 + ```
+1
2021/day17.txt
··· 1 + target area: x=288..330, y=-96..-50
+172
2021/day18.livemd
··· 1 + <!-- livebook:{"persist_outputs":true} --> 2 + 3 + # Day 18 4 + 5 + ## Input 6 + 7 + ```elixir 8 + input = 9 + File.stream!("day18.txt") 10 + |> Enum.map(&elem(Code.eval_string(&1), 0)) 11 + ``` 12 + 13 + ```output 14 + [ 15 + [[[6, [8, 3]], [2, 0]], [[[9, 5], [9, 1]], 3]], 16 + [[[9, [2, 2]], [5, 4]], [[[2, 2], [9, 6]], '\a\a']], 17 + [[[0, [3, 2]], 1], [[0, [2, 8]], [2, [0, 4]]]], 18 + [[4, 4], [[[7, 0], 5], [3, 1]]], 19 + [[5, 4], 1], 20 + [[[[7, 6], 4], 9], [[9, 1], 9]], 21 + [[[1, '\a\b'], ['\a\a', [1, 6]]], [1, [6, [7, 1]]]], 22 + [[[[6, 8], [5, 6]], [[1, 1], 8]], [[[2, 0], [3, 1]], [2, [2, 6]]]], 23 + [[[6, 3], [3, [7, 1]]], 8], 24 + [[[9, 4], [3, [0, 6]]], [[2, [3, 6]], ['\t\b', [1, 6]]]], 25 + [9, [0, [[0, 7], 2]]], 26 + [[[[8, 4], 7], [[9, 2], [0, 9]]], ['\a\t', [8, [0, 9]]]], 27 + [[1, 1], [[5, [3, 8]], [3, [4, 7]]]], 28 + [[[9, [2, 9]], [2, [2, 9]]], [[[3, 5], 5], [[3, 3], 2]]], 29 + [[[[5, 4], 9], 0], [[[5, 7], 2], [[5, 2], 9]]], 30 + [[2, [[1, 0], [6, 2]]], 0], 31 + [[[3, 7], [7, 6]], [[[2, 8], 5], [3, '\t\a']]], 32 + [[2, [2, '\b\b']], [['\t\t', [1, 1]], [[8, 6], [0, 3]]]], 33 + [[8, 1], [3, 5]], 34 + [[7, [[7, 6], [2, 0]]], 4], 35 + [[5, 4], [[1, 3], [5, [2, 8]]]], 36 + '\a\t', 37 + [[[[6, 9], 0], [1, [5, 0]]], [[[6, 4], 3], 7]], 38 + [[[[3, 7], 3], [2, 6]], [[0, 4], '\t\t']], 39 + [[[[1, 5], [5, 0]], [9, 4]], [[[8, 3], 3], [8, [3, 6]]]], 40 + [[[[3, 7], 5], [[8, 5], [1, 5]]], [[0, 6], [3, 4]]], 41 + [[[[4, 0], 2], [7, [8, 4]]], [0, [5, '\a\b']]], 42 + [[[[0, 8], [0, 4]], [9, 3]], [[[5, 4], [4, 8]], [[1, 6], [5, 4]]]], 43 + [[0, [0, 3]], [[3, [1, 5]], [[9, 6], [0, 6]]]], 44 + [[9, [8, 4]], [7, 1]], 45 + [[[[1, 9], '\a\a'], 9], [[6, [4, 5]], [8, [3, 2]]]], 46 + [5, [[2, [9, 5]], [3, [4, 0]]]], 47 + [[[6, 2], [[1, 8], 5]], 6], 48 + [[8, [6, [6, 4]]], [0, ['\t\b', 7]]], 49 + [[[[6, 3], [8, 0]], [8, [2, 7]]], 8], 50 + [[[6, [3, 6]], [[4, 0], [4, 7]]], [0, [[4, 0], [4, 5]]]], 51 + [[[3, [8, 1]], 1], [2, 3]], 52 + [[[6, [7, 0]], [[3, 5], [3, 4]]], 7], 53 + [[[[8, 0], 3], 8], [[[1, 6], 3], [[0, 5], 2]]], 54 + [[[3, 7], ['\t\b', 8]], [[[8, 4], 7], [3, [1, 7]]]], 55 + [[[0, 5], [[5, 5], '\a\b']], [9, [5, [2, 2]]]], 56 + [[2, 9], [[[7, 4], 4], [[8, 0], [6, 9]]]], 57 + [[['\a\b', '\b\b'], 0], 9], 58 + [[[4, [0, 6]], [[5, 9], [0, ...]]], [3, [6, 7]]], 59 + [[[7, [6, ...]], [5, [...]]], [[[3, ...], 6], [[...], ...]]], 60 + [3, [[[...], ...], [...]]], 61 + [[[3, ...], [...]], [[...], ...]], 62 + [['\t\a', ...], [...]], 63 + [[...], ...], 64 + [...], 65 + ... 66 + ] 67 + ``` 68 + 69 + ```elixir 70 + defmodule Day18 do 71 + def add(a, b) do 72 + sum = reduce([a, b]) 73 + 74 + # IO.puts(""" 75 + # #{inspect(a, charlists: :as_list)} 76 + # + #{inspect(b, charlists: :as_list)} 77 + # = #{inspect(sum, charlists: :as_list)} 78 + # """) 79 + 80 + sum 81 + end 82 + 83 + defp reduce(list) do 84 + # First try to explode 85 + # If that returned list in the same form, then try to split it 86 + # If all above returned input list, then we have reached fixed point 87 + with ^list <- explode(list), 88 + ^list <- split(list) do 89 + list 90 + else 91 + new_list -> reduce(new_list) 92 + end 93 + end 94 + 95 + defp explode(list) do 96 + {_, _, exploded} = explode(list, 0) 97 + 98 + exploded 99 + end 100 + 101 + defp explode(num, _) when is_number(num), do: {0, 0, num} 102 + 103 + defp explode([a, b], 4), do: {a, b, 0} 104 + 105 + defp explode([a, b], n) do 106 + {la, ra, na} = explode(a, n + 1) 107 + {lb, rb, nb} = explode(explode_add(ra, b), n + 1) 108 + 109 + {la, rb, [explode_add(na, lb), nb]} 110 + end 111 + 112 + defp explode_add([a, b], v), do: [a, explode_add(b, v)] 113 + defp explode_add(v, [a, b]), do: [explode_add(v, a), b] 114 + defp explode_add(a, b), do: a + b 115 + 116 + defp split(n) when n in 0..9, do: n 117 + defp split(n) when is_integer(n), do: [div(n, 2), div(n + 1, 2)] 118 + 119 + defp split([a, b]) do 120 + with {:a, ^a} <- {:a, split(a)}, 121 + {:b, ^b} <- {:b, split(b)} do 122 + [a, b] 123 + else 124 + {:a, mod} -> [mod, b] 125 + {:b, mod} -> [a, mod] 126 + end 127 + end 128 + 129 + def magnitude(n) when is_number(n), do: n 130 + def magnitude([a, b]), do: 3 * magnitude(a) + 2 * magnitude(b) 131 + end 132 + ``` 133 + 134 + ```output 135 + {:module, Day18, <<70, 79, 82, 49, 0, 0, 12, ...>>, {:magnitude, 1}} 136 + ``` 137 + 138 + ## Task 1 139 + 140 + ```elixir 141 + flip = fn f -> &f.(&2, &1) end 142 + 143 + input 144 + |> Enum.reduce(flip.(&Day18.add/2)) 145 + |> IO.inspect(charlists: :as_list) 146 + |> Day18.magnitude() 147 + ``` 148 + 149 + ```output 150 + [[[[7, 7], [7, 8]], [[8, 7], [0, 7]]], [[[6, 6], [6, 7]], 6]] 151 + ``` 152 + 153 + ```output 154 + 3411 155 + ``` 156 + 157 + ## Task 2 158 + 159 + ```elixir 160 + for a <- input, 161 + b <- input, 162 + a != b, 163 + m1 = Day18.magnitude(Day18.add(a, b)), 164 + m2 = Day18.magnitude(Day18.add(b, a)), 165 + reduce: 0 do 166 + acc -> max(acc, max(m1, m2)) 167 + end 168 + ``` 169 + 170 + ```output 171 + 4680 172 + ```
+100
2021/day18.txt
··· 1 + [[[6,[8,3]],[2,0]],[[[9,5],[9,1]],3]] 2 + [[[9,[2,2]],[5,4]],[[[2,2],[9,6]],[7,7]]] 3 + [[[0,[3,2]],1],[[0,[2,8]],[2,[0,4]]]] 4 + [[4,4],[[[7,0],5],[3,1]]] 5 + [[5,4],1] 6 + [[[[7,6],4],9],[[9,1],9]] 7 + [[[1,[7,8]],[[7,7],[1,6]]],[1,[6,[7,1]]]] 8 + [[[[6,8],[5,6]],[[1,1],8]],[[[2,0],[3,1]],[2,[2,6]]]] 9 + [[[6,3],[3,[7,1]]],8] 10 + [[[9,4],[3,[0,6]]],[[2,[3,6]],[[9,8],[1,6]]]] 11 + [9,[0,[[0,7],2]]] 12 + [[[[8,4],7],[[9,2],[0,9]]],[[7,9],[8,[0,9]]]] 13 + [[1,1],[[5,[3,8]],[3,[4,7]]]] 14 + [[[9,[2,9]],[2,[2,9]]],[[[3,5],5],[[3,3],2]]] 15 + [[[[5,4],9],0],[[[5,7],2],[[5,2],9]]] 16 + [[2,[[1,0],[6,2]]],0] 17 + [[[3,7],[7,6]],[[[2,8],5],[3,[9,7]]]] 18 + [[2,[2,[8,8]]],[[[9,9],[1,1]],[[8,6],[0,3]]]] 19 + [[8,1],[3,5]] 20 + [[7,[[7,6],[2,0]]],4] 21 + [[5,4],[[1,3],[5,[2,8]]]] 22 + [7,9] 23 + [[[[6,9],0],[1,[5,0]]],[[[6,4],3],7]] 24 + [[[[3,7],3],[2,6]],[[0,4],[9,9]]] 25 + [[[[1,5],[5,0]],[9,4]],[[[8,3],3],[8,[3,6]]]] 26 + [[[[3,7],5],[[8,5],[1,5]]],[[0,6],[3,4]]] 27 + [[[[4,0],2],[7,[8,4]]],[0,[5,[7,8]]]] 28 + [[[[0,8],[0,4]],[9,3]],[[[5,4],[4,8]],[[1,6],[5,4]]]] 29 + [[0,[0,3]],[[3,[1,5]],[[9,6],[0,6]]]] 30 + [[9,[8,4]],[7,1]] 31 + [[[[1,9],[7,7]],9],[[6,[4,5]],[8,[3,2]]]] 32 + [5,[[2,[9,5]],[3,[4,0]]]] 33 + [[[6,2],[[1,8],5]],6] 34 + [[8,[6,[6,4]]],[0,[[9,8],7]]] 35 + [[[[6,3],[8,0]],[8,[2,7]]],8] 36 + [[[6,[3,6]],[[4,0],[4,7]]],[0,[[4,0],[4,5]]]] 37 + [[[3,[8,1]],1],[2,3]] 38 + [[[6,[7,0]],[[3,5],[3,4]]],7] 39 + [[[[8,0],3],8],[[[1,6],3],[[0,5],2]]] 40 + [[[3,7],[[9,8],8]],[[[8,4],7],[3,[1,7]]]] 41 + [[[0,5],[[5,5],[7,8]]],[9,[5,[2,2]]]] 42 + [[2,9],[[[7,4],4],[[8,0],[6,9]]]] 43 + [[[[7,8],[8,8]],0],9] 44 + [[[4,[0,6]],[[5,9],[0,1]]],[3,[6,7]]] 45 + [[[7,[6,9]],[5,[6,4]]],[[[3,9],6],[[0,1],1]]] 46 + [3,[[[6,9],7],[5,8]]] 47 + [[[3,9],[[3,5],2]],[[[2,5],[4,6]],[8,0]]] 48 + [[[9,7],3],[[[2,7],[0,9]],[3,[0,3]]]] 49 + [[3,[4,0]],[[6,6],[4,5]]] 50 + [[0,0],[[5,9],1]] 51 + [[[6,8],[2,6]],[[[1,1],3],7]] 52 + [[[4,4],[[1,0],[2,4]]],[2,6]] 53 + [[[[6,0],6],[8,[9,9]]],[[4,2],[[1,8],[5,3]]]] 54 + [[[[1,6],[4,3]],[5,5]],[[7,[9,9]],4]] 55 + [[[[6,9],7],[9,3]],[[[9,6],5],0]] 56 + [[3,[[7,2],[8,1]]],[[7,[3,0]],1]] 57 + [0,[0,[1,3]]] 58 + [[[0,5],[[6,1],[4,6]]],[[[0,4],8],[[4,5],9]]] 59 + [[[[7,5],[7,0]],[6,[7,2]]],[7,[3,[4,1]]]] 60 + [[3,3],[0,[6,2]]] 61 + [[[3,8],[[7,3],6]],[[[0,8],3],[[8,9],[2,9]]]] 62 + [[4,[[5,6],[4,0]]],[[7,[7,5]],[5,0]]] 63 + [[[[2,5],[5,4]],9],[[[6,0],[0,0]],[[5,1],8]]] 64 + [[2,[[1,7],7]],[[[4,5],[7,9]],0]] 65 + [[[0,9],[[5,4],3]],3] 66 + [[9,[[1,9],[1,6]]],[[9,[0,3]],[[8,8],[0,7]]]] 67 + [[[[7,2],4],[7,8]],[[[4,1],[3,1]],[2,5]]] 68 + [[[[1,8],3],[2,5]],[[0,[5,8]],[[1,3],[5,2]]]] 69 + [[3,9],[[9,6],[5,[7,1]]]] 70 + [1,[[3,[6,5]],[5,[2,7]]]] 71 + [[[5,8],6],[8,[[9,4],[0,4]]]] 72 + [0,[[5,[6,6]],[[7,4],[4,6]]]] 73 + [[[[6,8],2],[[1,6],[8,2]]],6] 74 + [7,2] 75 + [[3,1],7] 76 + [[[2,[9,5]],0],[[[7,3],4],8]] 77 + [[[[0,0],[4,2]],5],[[8,6],2]] 78 + [[1,[7,8]],[2,[[6,6],[5,7]]]] 79 + [[[3,[6,0]],3],[[7,[4,4]],8]] 80 + [[[9,[8,7]],[[4,2],4]],[[6,1],[[3,3],[2,2]]]] 81 + [[[8,1],[[7,4],[5,9]]],9] 82 + [[[2,[8,6]],[[9,8],2]],[[9,5],[1,[9,8]]]] 83 + [[[[6,1],[3,1]],[[4,5],1]],[[[6,4],[6,2]],2]] 84 + [[[[4,0],[0,1]],[[1,4],6]],7] 85 + [[[[8,9],[0,2]],4],[[[9,8],8],[0,[0,6]]]] 86 + [0,[[[0,9],1],7]] 87 + [[1,[[3,7],3]],[[[2,4],3],0]] 88 + [[[[7,6],3],8],[[5,5],9]] 89 + [[2,[1,3]],[[[6,7],3],[[3,8],7]]] 90 + [[[[0,6],6],6],[[5,[0,9]],[8,[2,4]]]] 91 + [4,[[[3,0],[2,5]],[[7,4],1]]] 92 + [[[[7,9],3],[0,[8,2]]],[[8,[3,4]],[[2,3],[1,6]]]] 93 + [[[3,[6,3]],5],[[3,4],2]] 94 + [[[[1,9],[0,3]],[0,8]],[[[4,2],[4,3]],[[8,9],5]]] 95 + [[[[2,8],[4,9]],[[3,5],6]],[[6,[1,5]],[0,[9,7]]]] 96 + [[6,3],[[[7,7],[1,7]],[[6,5],[0,8]]]] 97 + [[1,[1,[5,8]]],7] 98 + [[0,6],[9,[[3,4],0]]] 99 + [[[[0,2],7],9],9] 100 + [9,6]
+306
2021/day19.livemd
··· 1 + <!-- livebook:{"persist_outputs":true} --> 2 + 3 + # Day 19 4 + 5 + ## Section 6 + 7 + ```elixir 8 + # File.read!("day19.txt") 9 + input = 10 + File.read!("day19.txt") 11 + |> String.split("\n\n") 12 + |> Enum.map(fn scanner -> 13 + scanner 14 + |> String.split("\n", trim: true) 15 + |> Enum.drop(1) 16 + |> Enum.map(fn coords -> 17 + coords 18 + |> String.split(",") 19 + |> Enum.map(&String.to_integer/1) 20 + |> Enum.zip(~w[x y z]a) 21 + |> Map.new(fn {v, k} -> {k, v} end) 22 + end) 23 + |> MapSet.new() 24 + end) 25 + 26 + length(input) 27 + ``` 28 + 29 + ```output 30 + 34 31 + ``` 32 + 33 + $$ 34 + \left\{ 35 + \begin{alignat*}{3} 36 + b_{x_1} r_x + b_{x_0} = a_{x_1} \\ 37 + b_{x_2} r_x + b_{x_0} = a_{x_2} 38 + \end{alignat*} 39 + \right. 40 + \left\{ 41 + \begin{alignat*}{3} 42 + b_{y_1} r_y + b_{y_0} = a_{y_1} \\ 43 + b_{y_2} r_y + b_{y_0} = a_{y_2} \\ 44 + \end{alignat*} 45 + \right. 46 + \left\{ 47 + \begin{alignat*}{3} 48 + b_{z_1} r_z + b_{z_0} = a_{z_1} \\ 49 + b_{z_2} r_z + b_{z_0} = a_{z_2} \\ 50 + \end{alignat*} 51 + \right. 52 + $$ 53 + 54 + Where $$r_x, r_y, r_z \in \{-1, 1\}$$ and $$a_{xyz}, b_{xyz} = \text{const}$$. 55 + This mean that we need to solve: 56 + 57 + $$ 58 + B_x x + b_0 = a_x \\ 59 + B_y y + b_0 = a_y \\ 60 + B_z z + b_0 = a_z 61 + $$ 62 + 63 + Where: 64 + 65 + $$ 66 + B_d = \begin{bmatrix} 67 + {b_1}_d & 1 \\ 68 + {b_2}_d & 1 \\ 69 + \end{bmatrix} 70 + d = \begin{bmatrix} 71 + r_d \\ 72 + b_{d_0} 73 + \end{bmatrix} 74 + a_d = \begin{bmatrix} 75 + {a_1}_d \\ 76 + {a_2}_d 77 + \end{bmatrix} 78 + $$ 79 + 80 + By applying [Cramer's Rule](https://en.wikipedia.org/wiki/Cramer%27s_rule) we can solve these 81 + linear equations with: 82 + 83 + $$ 84 + e_d = \frac{ 85 + \begin{vmatrix} 86 + {b_1}_d & 1 \\ 87 + {b_2}_d & 1 88 + \end{vmatrix} 89 + }{ 90 + \begin{vmatrix} 91 + {a_1}_d & 1 \\ 92 + {a_2}_d & 1 93 + \end{vmatrix} 94 + } = \frac{{b_1}_d - {b_2}_d}{{a_1}_d - {a_2}_d} \\ 95 + b_{d_0} = \frac{ 96 + \begin{vmatrix} 97 + {a_1}_d & {b_1}_d \\ 98 + {a_2}_d & {b_2}_d 99 + \end{vmatrix} 100 + }{ 101 + \begin{vmatrix} 102 + {a_1}_d & 1 \\ 103 + {a_2}_d & 1 104 + \end{vmatrix} 105 + } = \frac{{a_1}_d {b_2}_d - {b_1}_d {a_2}_d}{{a_1}_d - {a_2}_d} 106 + 107 + ```elixir 108 + defmodule Day19 do 109 + def rebase(base, pairs1) do 110 + pairs0 = pairs(base) 111 + # Take common points 112 + pa = Map.take(pairs0, Map.keys(pairs1)) 113 + pb = Map.take(pairs1, Map.keys(pairs0)) 114 + 115 + # Merge them 116 + [{{a, b, axes1}, {_, _, axes2}} = p0 | others] = 117 + Map.merge(pa, pb, fn _, a, b -> {a, b} end) 118 + |> Map.values() 119 + 120 + p1 = Enum.find(others, fn {{x, y, _}, _} -> a in [x, y] end) 121 + p2 = Enum.find(others, fn {{x, y, _}, _} -> b in [x, y] end) 122 + 123 + axes = axes_transformations(axes1, axes2) 124 + 125 + a_1 = a 126 + a_2 = b 127 + b_1 = reaxe(select_common(p0, p1), axes) 128 + b_2 = reaxe(select_common(p0, p2), axes) 129 + 130 + transform = 131 + for i <- ~w[x y z]a, into: %{} do 132 + a_1 = a_1[i] 133 + a_2 = a_2[i] 134 + b_1 = b_1[i] 135 + b_2 = b_2[i] 136 + det_b = b_1 - b_2 137 + r = div(a_1 - a_2, det_b) 138 + 139 + b_0 = div(b_1 * a_2 - a_1 * b_2, det_b) 140 + 141 + {i, {r, b_0}} 142 + end 143 + 144 + new_points = 145 + pairs1 146 + |> Map.values() 147 + |> Enum.flat_map(&[elem(&1, 0), elem(&1, 1)]) 148 + |> Enum.uniq() 149 + |> Enum.map(&reaxe(&1, axes)) 150 + |> do_rebase(transform) 151 + |> MapSet.new() 152 + 153 + %{x: {_, sx}, y: {_, sy}, z: {_, sz}} = transform 154 + scanner = %{x: sx, y: sy, z: sz} 155 + 156 + {new_points, scanner} 157 + end 158 + 159 + defp do_rebase(points, transform) do 160 + points 161 + |> Enum.map(fn p -> 162 + Map.merge(p, transform, fn _k, d, {r, b} -> d * r + b end) 163 + end) 164 + |> MapSet.new() 165 + end 166 + 167 + defp select_common(a, b) do 168 + case {a, b} do 169 + {{_, {_, x, _}}, {_, {_, x, _}}} -> x 170 + {{_, {x, _, _}}, {_, {x, _, _}}} -> x 171 + {{_, {_, x, _}}, {_, {x, _, _}}} -> x 172 + {{_, {x, _, _}}, {_, {_, x, _}}} -> x 173 + end 174 + end 175 + 176 + defp axes_transformations(a, b) do 177 + Map.merge(a, b, fn 178 + _, a, b -> {a, b} 179 + end) 180 + |> Map.values() 181 + |> Map.new() 182 + end 183 + 184 + defp reaxe(point, axes) do 185 + %{ 186 + x: point[axes[:x]], 187 + y: point[axes[:y]], 188 + z: point[axes[:z]] 189 + } 190 + end 191 + 192 + def pairs(points) do 193 + for a <- points, 194 + b <- points, 195 + a < b, 196 + dx = abs(a.x - b.x), 197 + dy = abs(a.y - b.y), 198 + dz = abs(a.z - b.z), 199 + into: %{}, 200 + do: {{dx ** 2 + dy ** 2 + dz ** 2, dx + dy + dz}, {a, b, %{dx => :x, dy => :y, dz => :z}}} 201 + end 202 + end 203 + ``` 204 + 205 + ```output 206 + {:module, Day19, <<70, 79, 82, 49, 0, 0, 26, ...>>, {:pairs, 1}} 207 + ``` 208 + 209 + ```elixir 210 + [first | rest] = Enum.map(input, &Day19.pairs/1) 211 + 212 + {joinable, later} = 213 + Enum.split_with(rest, fn pairs -> 214 + s1 = MapSet.new(first, fn {k, _} -> k end) 215 + s2 = MapSet.new(pairs, fn {k, _} -> k end) 216 + 217 + case MapSet.size(MapSet.intersection(s1, s2)) do 218 + 66 -> true 219 + x when x < 66 -> false 220 + end 221 + end) 222 + 223 + {length(joinable), length(later)} 224 + ``` 225 + 226 + ```output 227 + {3, 30} 228 + ``` 229 + 230 + ```elixir 231 + # Distances between each pair of points in `first` 232 + 233 + points_set = MapSet.new(hd(input)) 234 + 235 + {points_set, scanners} = 236 + Enum.reduce_while( 237 + 1..34, 238 + {points_set, joinable, later, []}, 239 + fn i, {set, joinable, later, scanners} -> 240 + {time, {set, scanners}} = 241 + :timer.tc(fn -> 242 + Enum.reduce(joinable, {set, scanners}, fn new, {base, scanners} -> 243 + {new, scanner} = Day19.rebase(base, new) 244 + 245 + {MapSet.union(new, base), [scanner | scanners]} 246 + end) 247 + end) 248 + 249 + IO.inspect(time / 1_000_000) 250 + 251 + current = Day19.pairs(set) 252 + 253 + Enum.split_with(later, fn pairs -> 254 + s1 = MapSet.new(current, fn {k, _} -> k end) 255 + s2 = MapSet.new(pairs, fn {k, _} -> k end) 256 + 257 + MapSet.size(MapSet.intersection(s1, s2)) >= 66 258 + end) 259 + |> case do 260 + {[], []} -> 261 + {:halt, {set, scanners}} 262 + 263 + {joinable, later} -> 264 + IO.inspect({length(joinable), length(later)}, label: i) 265 + {:cont, {set, joinable, later, scanners}} 266 + end 267 + end 268 + ) 269 + 270 + MapSet.size(points_set) 271 + ``` 272 + 273 + ```output 274 + 0.002822 275 + 1: {5, 25} 276 + 0.017052 277 + 2: {5, 20} 278 + 0.0355 279 + 3: {7, 13} 280 + 0.134655 281 + 4: {6, 7} 282 + 0.229952 283 + 5: {5, 2} 284 + 0.288351 285 + 6: {1, 1} 286 + 0.076665 287 + 7: {1, 0} 288 + 0.071942 289 + ``` 290 + 291 + ```output 292 + 396 293 + ``` 294 + 295 + ```elixir 296 + for( 297 + a <- scanners, 298 + b <- scanners, 299 + do: abs(a.x - b.x) + abs(a.y - b.y) + abs(a.z - b.z) 300 + ) 301 + |> Enum.max() 302 + ``` 303 + 304 + ```output 305 + 11828 306 + ```
+949
2021/day19.txt
··· 1 + --- scanner 0 --- 2 + -731,-763,-425 3 + 832,-512,-437 4 + 571,657,-514 5 + 594,551,-569 6 + -604,638,718 7 + -536,524,776 8 + 629,721,-564 9 + -623,-444,440 10 + -708,-610,437 11 + 550,-524,759 12 + 355,515,510 13 + -683,877,-615 14 + 763,-622,-365 15 + -833,-795,-362 16 + -663,840,-668 17 + -676,876,-848 18 + 7,-92,-35 19 + 560,-560,695 20 + -559,539,599 21 + 528,-504,779 22 + -709,-874,-390 23 + 457,445,563 24 + 841,-410,-363 25 + -742,-511,374 26 + 422,463,367 27 + 28 + --- scanner 1 --- 29 + 598,477,221 30 + 687,-702,-850 31 + -586,-650,-945 32 + -588,-636,-820 33 + -676,-819,603 34 + 431,-621,738 35 + -790,449,456 36 + 339,566,-635 37 + 386,708,-671 38 + 466,672,-647 39 + 245,-629,714 40 + -674,520,398 41 + -20,-191,-108 42 + 624,398,329 43 + -712,486,-889 44 + -851,477,396 45 + -791,580,-833 46 + 627,330,296 47 + 623,-679,-824 48 + -859,-833,629 49 + 697,-847,-874 50 + -463,-586,-905 51 + -607,554,-853 52 + -789,-836,551 53 + -168,-4,-10 54 + 413,-642,724 55 + 56 + --- scanner 2 --- 57 + 676,816,-834 58 + 614,746,-853 59 + -592,-743,-408 60 + -72,47,-39 61 + -744,-404,762 62 + 444,-703,786 63 + 753,-784,-474 64 + -534,-783,-416 65 + 735,717,-765 66 + 568,482,582 67 + -343,434,-675 68 + -488,758,370 69 + 545,517,368 70 + -489,888,446 71 + -642,-821,-498 72 + -351,372,-463 73 + 384,-705,874 74 + -827,-527,719 75 + 624,-720,837 76 + 88,-28,74 77 + 503,604,524 78 + -640,-593,761 79 + -419,427,-552 80 + 690,-818,-490 81 + -353,831,437 82 + 650,-734,-583 83 + 84 + --- scanner 3 --- 85 + -561,681,-898 86 + -696,-781,-955 87 + 674,322,-753 88 + -631,640,-859 89 + 421,399,364 90 + -559,-639,519 91 + 451,-574,320 92 + -599,-747,467 93 + -813,515,442 94 + 809,328,-802 95 + 478,-579,460 96 + -710,-656,-826 97 + 455,-597,-612 98 + -600,-812,-818 99 + 555,-700,367 100 + 593,379,413 101 + 382,-629,-639 102 + 810,259,-767 103 + -46,21,-86 104 + -662,548,550 105 + -618,-569,546 106 + -710,453,457 107 + -805,672,-885 108 + 479,482,472 109 + 444,-658,-572 110 + 75,-100,-5 111 + 112 + --- scanner 4 --- 113 + -720,-688,-429 114 + 75,21,146 115 + -524,-443,905 116 + -455,739,547 117 + 28,-141,13 118 + -697,-360,919 119 + 826,-631,876 120 + -556,623,540 121 + 710,450,-593 122 + -545,-345,887 123 + 697,394,-509 124 + 767,-745,773 125 + 875,-803,856 126 + 614,-573,-535 127 + 542,624,862 128 + -794,439,-772 129 + 561,-428,-543 130 + -746,370,-754 131 + -683,-626,-394 132 + 469,634,823 133 + -628,431,-669 134 + -754,-741,-370 135 + 741,613,-533 136 + 489,522,847 137 + -374,623,575 138 + 664,-373,-571 139 + 140 + --- scanner 5 --- 141 + 699,-825,730 142 + 537,-594,-346 143 + 346,566,583 144 + -631,-481,703 145 + -787,-523,790 146 + 859,752,-606 147 + 585,-767,662 148 + 424,-689,-351 149 + -648,384,-472 150 + 684,-648,707 151 + -709,511,419 152 + -683,421,-534 153 + -38,84,173 154 + -707,350,-419 155 + -342,-793,-586 156 + 765,684,-628 157 + -573,-546,825 158 + 493,-563,-373 159 + -785,510,549 160 + 701,831,-589 161 + -718,375,476 162 + -335,-697,-642 163 + 383,619,603 164 + -293,-795,-521 165 + 347,799,590 166 + 117,6,18 167 + 168 + --- scanner 6 --- 169 + -716,-702,538 170 + 795,547,748 171 + -711,527,-540 172 + 601,413,-940 173 + -863,-529,-512 174 + 388,-501,-871 175 + -723,-534,-539 176 + 787,759,810 177 + -637,-524,557 178 + 719,670,755 179 + 300,-440,423 180 + 580,395,-842 181 + -816,-655,-616 182 + 345,-571,505 183 + 554,-554,-934 184 + -633,593,601 185 + -741,560,752 186 + 547,-535,-827 187 + 753,381,-925 188 + 359,-597,479 189 + -819,444,-482 190 + 10,13,-72 191 + -664,-594,498 192 + -770,424,-654 193 + -726,498,649 194 + 195 + --- scanner 7 --- 196 + -582,-761,459 197 + -453,-839,-862 198 + 804,-878,437 199 + -612,749,581 200 + 436,398,564 201 + -487,-795,-703 202 + 807,842,-463 203 + 750,-880,275 204 + -549,511,-891 205 + 718,787,-531 206 + 145,-81,-100 207 + -503,-738,369 208 + -600,814,464 209 + 429,-893,-497 210 + -599,645,571 211 + -540,-758,410 212 + 718,-866,393 213 + 461,-908,-649 214 + -523,537,-905 215 + 595,780,-455 216 + -506,-902,-696 217 + 417,468,502 218 + 505,497,623 219 + 12,47,-20 220 + -392,455,-950 221 + 443,-810,-670 222 + 223 + --- scanner 8 --- 224 + 53,162,-22 225 + 967,695,948 226 + 770,-615,-548 227 + -670,-668,425 228 + 968,599,931 229 + 956,564,873 230 + -402,599,-642 231 + -440,-235,-401 232 + 840,-611,-438 233 + 684,602,-426 234 + 609,-449,832 235 + 691,788,-464 236 + -498,984,913 237 + 895,-586,-503 238 + -501,913,878 239 + 167,129,170 240 + 695,623,-587 241 + 493,-550,825 242 + -523,556,-616 243 + -368,-412,-433 244 + -478,-443,-393 245 + -7,18,134 246 + -390,903,852 247 + -353,475,-643 248 + 609,-631,797 249 + -691,-717,496 250 + -674,-800,467 251 + 252 + --- scanner 9 --- 253 + 523,-356,773 254 + -764,463,-560 255 + -425,-730,874 256 + 668,-366,749 257 + 728,-640,-825 258 + 67,173,60 259 + 903,419,-683 260 + -787,551,-542 261 + -403,-811,707 262 + 889,413,-586 263 + 749,-622,-839 264 + -763,407,-508 265 + 741,-808,-815 266 + -699,745,628 267 + -523,-387,-566 268 + -489,-747,745 269 + -606,801,513 270 + -724,-387,-543 271 + -647,-369,-544 272 + -682,846,572 273 + 658,516,448 274 + 518,532,446 275 + 460,523,469 276 + 94,-8,-68 277 + 885,388,-755 278 + 691,-430,723 279 + 280 + --- scanner 10 --- 281 + 632,619,803 282 + -337,-640,-546 283 + 746,-937,-943 284 + -81,54,-168 285 + 821,-857,548 286 + 706,756,751 287 + 683,-855,672 288 + -733,363,-817 289 + -615,381,-906 290 + -584,435,-808 291 + -329,-782,-669 292 + 586,461,-730 293 + 659,730,711 294 + -493,496,495 295 + 766,-822,-830 296 + -338,-687,-635 297 + -589,-913,412 298 + 721,-864,422 299 + -601,-806,278 300 + 397,451,-676 301 + -10,-104,0 302 + -604,404,408 303 + 487,463,-794 304 + 775,-762,-933 305 + -602,583,413 306 + -461,-925,315 307 + 308 + --- scanner 11 --- 309 + -746,899,-576 310 + 407,869,433 311 + -547,-309,328 312 + -416,-384,339 313 + -316,-483,-310 314 + 399,485,-678 315 + 698,-432,802 316 + -46,-77,89 317 + -648,857,-455 318 + -726,877,401 319 + -478,-429,-312 320 + -744,850,-511 321 + 608,-772,-282 322 + 433,544,-625 323 + 629,-790,-380 324 + -729,896,666 325 + 525,784,494 326 + -451,-326,327 327 + 46,69,-60 328 + 359,887,502 329 + 470,509,-563 330 + -434,-515,-324 331 + 456,-804,-297 332 + -788,819,534 333 + 779,-460,686 334 + 597,-425,686 335 + 336 + --- scanner 12 --- 337 + 363,-267,559 338 + 256,-401,547 339 + -772,-682,-877 340 + 314,-661,-725 341 + 19,64,-38 342 + -676,-711,473 343 + -685,590,-796 344 + -833,-770,417 345 + -719,-516,-940 346 + 529,557,295 347 + 387,680,287 348 + -625,644,776 349 + 244,-304,419 350 + 347,841,-808 351 + 407,944,-817 352 + -702,-725,499 353 + -173,172,-77 354 + -738,-523,-833 355 + -613,761,711 356 + -722,549,-776 357 + 232,954,-788 358 + -643,639,-799 359 + 312,-537,-863 360 + 305,-411,-763 361 + 482,646,296 362 + -626,751,607 363 + 364 + --- scanner 13 --- 365 + 292,-495,571 366 + 651,919,779 367 + -175,-32,46 368 + -939,696,356 369 + -690,411,-464 370 + -384,-810,562 371 + -785,-685,-485 372 + -795,451,-566 373 + 773,-408,-583 374 + -906,399,-435 375 + 781,-531,-441 376 + -455,-767,470 377 + 772,-497,-536 378 + 357,-612,559 379 + -950,531,445 380 + -455,-745,448 381 + 595,860,622 382 + 649,453,-298 383 + -917,726,512 384 + -20,152,68 385 + -778,-675,-648 386 + -763,-609,-482 387 + 509,416,-417 388 + 569,874,648 389 + 461,-602,572 390 + 521,550,-310 391 + 392 + --- scanner 14 --- 393 + -322,-641,670 394 + -349,354,-648 395 + -625,714,619 396 + 812,-715,-617 397 + -491,-748,669 398 + 821,527,-792 399 + 909,550,885 400 + -599,728,593 401 + -294,286,-737 402 + 87,-111,72 403 + 354,-956,679 404 + -668,-679,-347 405 + 425,-891,793 406 + 862,-818,-726 407 + -387,-758,682 408 + 887,580,729 409 + 425,-913,771 410 + -639,-800,-435 411 + -356,278,-525 412 + -46,-32,-48 413 + 899,577,-702 414 + 896,-755,-710 415 + 920,385,796 416 + 861,469,-784 417 + -738,-741,-366 418 + -681,773,462 419 + 420 + --- scanner 15 --- 421 + -863,636,832 422 + 887,603,374 423 + -66,-152,-18 424 + -406,-515,-665 425 + -501,-905,785 426 + 542,-591,-441 427 + 790,520,-691 428 + 562,-667,653 429 + 888,610,607 430 + -680,319,-645 431 + -611,-836,857 432 + 813,415,-771 433 + 732,-702,658 434 + 668,-644,708 435 + -784,760,860 436 + -380,-439,-590 437 + 66,2,27 438 + -839,277,-736 439 + 811,556,-859 440 + -752,658,797 441 + -576,-505,-555 442 + -746,345,-682 443 + 543,-455,-365 444 + 851,590,554 445 + -399,-914,859 446 + 436,-477,-381 447 + 448 + --- scanner 16 --- 449 + 695,-489,-727 450 + -393,764,-274 451 + 513,-404,724 452 + 733,406,705 453 + 788,-449,-811 454 + 804,-386,-777 455 + -591,-456,576 456 + -715,-313,-340 457 + -544,907,364 458 + 135,43,-46 459 + -534,924,338 460 + -559,835,455 461 + -315,762,-398 462 + 444,-463,823 463 + 424,417,-730 464 + 695,626,745 465 + -693,-291,-340 466 + -378,843,-372 467 + 425,-525,753 468 + 454,414,-693 469 + -604,-446,472 470 + -601,-248,-269 471 + 465,460,-686 472 + -592,-563,407 473 + 749,580,604 474 + 76,148,91 475 + 476 + --- scanner 17 --- 477 + 455,-760,-649 478 + 670,-470,334 479 + 569,454,608 480 + -358,-652,-715 481 + -522,413,-718 482 + 578,-408,376 483 + -499,503,-639 484 + -510,818,236 485 + -465,-659,-734 486 + 530,478,-610 487 + 534,643,-733 488 + -435,-673,316 489 + -123,-22,19 490 + -481,808,411 491 + 630,-482,500 492 + -421,-818,-768 493 + 541,457,-771 494 + -573,-797,318 495 + -490,705,351 496 + -535,-547,309 497 + -502,454,-681 498 + 385,-756,-759 499 + 330,-731,-694 500 + 20,-66,-142 501 + 736,518,636 502 + 522,517,683 503 + 504 + --- scanner 18 --- 505 + 488,-495,-482 506 + 753,833,793 507 + 575,545,-722 508 + 437,-478,-662 509 + -380,740,-476 510 + -589,-884,-619 511 + -447,-668,405 512 + 512,-794,706 513 + 66,67,-124 514 + -535,581,492 515 + -383,-610,455 516 + 555,-671,789 517 + -392,808,-633 518 + -659,-782,-672 519 + -477,812,-495 520 + 741,783,712 521 + -641,-817,-476 522 + 721,728,746 523 + -433,523,401 524 + 513,-605,602 525 + 613,677,-617 526 + 188,-120,-51 527 + -553,-645,460 528 + 400,-493,-422 529 + -598,533,370 530 + 546,787,-712 531 + 532 + --- scanner 19 --- 533 + 680,468,656 534 + -895,-366,652 535 + -732,-787,-709 536 + -801,-610,-698 537 + 451,-753,587 538 + 600,-429,-518 539 + -808,-712,-655 540 + -85,174,-91 541 + 381,-734,525 542 + 480,-665,466 543 + -787,899,-508 544 + -696,913,386 545 + -631,962,384 546 + -752,920,482 547 + 499,-445,-344 548 + -864,885,-423 549 + -821,796,-468 550 + 523,758,-784 551 + 56,66,25 552 + 466,693,-633 553 + 593,624,698 554 + 715,682,633 555 + 501,782,-567 556 + -897,-420,814 557 + 459,-483,-564 558 + -883,-452,696 559 + 560 + --- scanner 20 --- 561 + 397,-456,465 562 + 822,541,-705 563 + -805,-570,-623 564 + 484,-683,-391 565 + -592,793,-393 566 + -867,737,670 567 + -592,-860,531 568 + -506,805,-437 569 + -881,820,497 570 + -560,807,-275 571 + 432,554,511 572 + -12,12,62 573 + 780,662,-607 574 + 467,492,474 575 + 406,-399,601 576 + 773,606,-703 577 + 328,-770,-433 578 + -893,-541,-502 579 + -503,-915,463 580 + 330,-529,600 581 + 408,439,440 582 + -715,-853,455 583 + -849,835,649 584 + 542,-805,-456 585 + -129,-146,27 586 + -874,-471,-564 587 + 588 + --- scanner 21 --- 589 + 533,528,-756 590 + 635,945,504 591 + 924,-707,-431 592 + 926,-248,469 593 + -453,651,678 594 + 743,907,422 595 + 18,113,48 596 + -426,-601,-285 597 + -587,-409,730 598 + -602,-306,668 599 + 934,-310,681 600 + 450,651,-713 601 + -736,841,-422 602 + 788,-764,-440 603 + 858,-303,558 604 + 637,717,-755 605 + -701,958,-484 606 + 685,867,414 607 + -219,-659,-318 608 + 789,-634,-364 609 + -609,608,678 610 + -494,-457,635 611 + -602,695,664 612 + -672,954,-527 613 + -322,-639,-423 614 + 615 + --- scanner 22 --- 616 + 665,-972,357 617 + 157,-75,5 618 + -645,524,554 619 + -661,-821,715 620 + 552,-766,-295 621 + 572,402,640 622 + 534,-897,368 623 + -544,439,-366 624 + -641,414,484 625 + 569,492,-403 626 + 596,-852,-283 627 + -616,479,429 628 + -479,-856,715 629 + 6,-31,124 630 + 618,534,-400 631 + 434,-798,-281 632 + 593,563,629 633 + -537,458,-259 634 + -703,405,-322 635 + -338,-477,-268 636 + -580,-849,831 637 + 758,440,633 638 + 569,-955,356 639 + 528,455,-423 640 + -490,-509,-253 641 + -511,-491,-351 642 + 643 + --- scanner 23 --- 644 + 388,-809,-352 645 + -367,872,532 646 + -415,-631,622 647 + 743,-603,724 648 + -753,552,-643 649 + 562,-642,690 650 + 139,81,144 651 + 451,-707,-384 652 + -381,-642,874 653 + 383,456,849 654 + -411,-684,-537 655 + 416,-685,-273 656 + -384,-613,831 657 + -338,776,398 658 + 412,553,858 659 + 399,591,733 660 + -264,869,422 661 + -733,574,-623 662 + -414,-599,-703 663 + 674,-497,728 664 + 48,-39,41 665 + 389,865,-737 666 + -669,584,-587 667 + 463,856,-635 668 + -348,-718,-636 669 + 391,787,-525 670 + 671 + --- scanner 24 --- 672 + -784,-392,606 673 + -484,366,661 674 + 736,683,764 675 + -663,-858,-769 676 + 833,-740,823 677 + -553,-789,-841 678 + 821,-458,-849 679 + -765,-867,-843 680 + 700,495,-558 681 + 87,-2,28 682 + -325,324,752 683 + 790,830,797 684 + 705,-593,-833 685 + 836,-846,942 686 + -418,392,698 687 + 830,-555,-820 688 + 1,-137,118 689 + 870,-733,933 690 + 662,640,-670 691 + -380,807,-844 692 + -301,683,-816 693 + -588,-458,571 694 + 696,601,-489 695 + -412,705,-781 696 + -758,-468,681 697 + 661,785,811 698 + 699 + --- scanner 25 --- 700 + 500,-759,-543 701 + 637,-476,865 702 + 844,524,-809 703 + 691,-401,789 704 + 755,549,-692 705 + -670,-822,952 706 + 680,-578,858 707 + 374,779,921 708 + -536,581,-571 709 + -543,-454,-324 710 + 326,-743,-442 711 + -738,485,812 712 + -605,-435,-394 713 + -832,-768,954 714 + 827,534,-783 715 + 396,700,869 716 + -697,522,832 717 + -24,26,176 718 + -643,582,-740 719 + -484,-523,-423 720 + 546,-705,-402 721 + -526,594,-675 722 + 36,-123,83 723 + -648,564,835 724 + -714,-736,940 725 + 311,819,948 726 + 727 + --- scanner 26 --- 728 + -609,-865,-696 729 + -730,-552,628 730 + 320,796,-676 731 + -480,446,-760 732 + -789,-814,-679 733 + 752,-686,698 734 + 86,-103,-33 735 + -54,-53,105 736 + 601,-621,755 737 + -543,462,-794 738 + -688,-396,541 739 + 312,517,722 740 + 462,-422,-642 741 + 426,-451,-511 742 + -557,806,840 743 + 535,-710,720 744 + -619,825,770 745 + 366,785,-669 746 + -849,-902,-681 747 + 532,555,762 748 + -498,737,741 749 + 444,-531,-542 750 + -665,-610,506 751 + 323,826,-713 752 + -583,555,-710 753 + 486,501,621 754 + 755 + --- scanner 27 --- 756 + 440,-949,710 757 + -548,356,729 758 + -860,601,-538 759 + 464,-767,-452 760 + 653,723,873 761 + -846,-908,-728 762 + 440,436,-892 763 + -730,-861,516 764 + 4,-62,-113 765 + 541,420,-718 766 + 407,-702,-603 767 + 581,741,842 768 + 484,727,848 769 + 442,-791,-669 770 + -674,-844,415 771 + 458,-926,798 772 + -923,-894,-813 773 + -880,-805,-768 774 + -93,-141,27 775 + -550,496,745 776 + 400,474,-672 777 + -571,298,738 778 + -615,-768,460 779 + -867,703,-581 780 + -791,778,-527 781 + 406,-925,854 782 + 783 + --- scanner 28 --- 784 + 647,354,627 785 + 754,-710,818 786 + -32,-37,79 787 + -607,574,728 788 + 706,-823,-325 789 + -440,806,-361 790 + 811,-701,682 791 + -630,680,673 792 + 686,-718,-428 793 + -604,-428,344 794 + 627,391,574 795 + -907,-614,-778 796 + 593,431,-839 797 + 681,-777,683 798 + -481,-385,427 799 + 452,429,-751 800 + 557,452,-671 801 + 9,100,-69 802 + -911,-657,-807 803 + -554,700,-421 804 + 648,-856,-532 805 + -665,510,678 806 + 640,355,394 807 + -670,-386,531 808 + -794,-719,-842 809 + -418,699,-345 810 + 811 + --- scanner 29 --- 812 + 345,-686,278 813 + 590,445,375 814 + -10,-33,-90 815 + 730,443,391 816 + -830,567,-808 817 + -329,-599,712 818 + -452,-400,-567 819 + 725,770,-497 820 + -454,-606,663 821 + 788,466,382 822 + 580,746,-507 823 + 359,-589,272 824 + 557,720,-571 825 + -688,531,-855 826 + -520,-433,-570 827 + -571,763,607 828 + 363,-758,247 829 + -794,543,-728 830 + -464,-557,820 831 + -121,76,13 832 + -599,-325,-596 833 + -469,671,559 834 + -529,590,644 835 + 520,-828,-781 836 + 507,-818,-949 837 + 499,-842,-763 838 + 839 + --- scanner 30 --- 840 + 898,-783,-440 841 + 922,437,482 842 + -471,-599,844 843 + 754,-763,593 844 + 74,-14,20 845 + -699,-844,-819 846 + 905,-782,548 847 + 7,-163,-135 848 + 864,402,436 849 + -386,-589,679 850 + 427,680,-886 851 + 405,573,-902 852 + -465,303,-496 853 + -661,-982,-715 854 + -477,-574,623 855 + -728,245,476 856 + -719,-949,-922 857 + 541,574,-826 858 + -570,326,-576 859 + 781,-845,-405 860 + -555,248,370 861 + -606,305,-408 862 + 907,-709,651 863 + 894,-740,-469 864 + 916,504,488 865 + -697,342,327 866 + 867 + --- scanner 31 --- 868 + 246,-795,-450 869 + 689,777,-513 870 + -737,-654,-829 871 + 659,821,460 872 + 300,-430,432 873 + -748,371,-546 874 + -636,391,-522 875 + -451,-517,506 876 + 555,774,586 877 + -738,444,-507 878 + -33,-82,-118 879 + -476,718,803 880 + 329,-622,-464 881 + -576,-488,551 882 + 231,-643,-482 883 + -498,868,705 884 + 632,681,465 885 + -737,-472,-794 886 + -853,-553,-822 887 + 631,669,-596 888 + 5,80,24 889 + 344,-589,466 890 + -506,-492,441 891 + 517,728,-493 892 + -469,691,760 893 + 237,-596,485 894 + 895 + --- scanner 32 --- 896 + 299,519,833 897 + -547,650,-617 898 + 395,-426,414 899 + -954,-698,761 900 + 643,-437,-429 901 + -715,929,492 902 + -555,612,-825 903 + -856,-676,911 904 + -911,-705,734 905 + 313,846,-260 906 + -657,-723,-474 907 + -658,986,590 908 + 267,489,859 909 + -714,907,743 910 + 371,-538,434 911 + 342,863,-343 912 + 671,-321,-510 913 + -592,-668,-449 914 + -702,-598,-445 915 + -134,142,-43 916 + -587,540,-648 917 + 239,648,792 918 + 356,-436,487 919 + 678,-437,-611 920 + -22,23,114 921 + 271,842,-392 922 + 923 + --- scanner 33 --- 924 + 353,649,717 925 + 632,-572,-385 926 + 627,-425,511 927 + 569,-375,575 928 + -478,613,-778 929 + 566,-759,-427 930 + 420,506,769 931 + 759,692,-309 932 + 455,702,787 933 + 742,512,-360 934 + 592,-430,681 935 + -443,636,-564 936 + -678,-709,356 937 + 744,452,-272 938 + -665,-529,392 939 + -606,857,594 940 + -792,-285,-709 941 + -685,-476,355 942 + 39,-2,98 943 + -561,738,693 944 + -31,148,10 945 + -849,-421,-700 946 + -565,571,-622 947 + -538,915,708 948 + 443,-676,-384 949 + -719,-420,-776
+80
2021/day2.livemd
··· 1 + <!-- vim:ft=markdown 2 + --> 3 + 4 + <!-- livebook:{"persist_outputs":true} --> 5 + 6 + # Day 2 7 + 8 + ## Load input 9 + 10 + We do parsing there, as it will help us with the latter tasks. Pattern matching 11 + is the simplest approach there, as input is in form of: 12 + 13 + ``` 14 + forward 10 15 + up 20 16 + down 30 17 + ``` 18 + 19 + We need to `trim/1` input to make sure that the last newline will not interrupt 20 + `String.to_integer/1` calls. 21 + 22 + ```elixir 23 + stream = 24 + File.stream!("day2.txt") 25 + |> Stream.map(fn input -> 26 + case String.trim(input) do 27 + "forward " <> n -> {:forward, String.to_integer(n)} 28 + "up " <> n -> {:up, String.to_integer(n)} 29 + "down " <> n -> {:down, String.to_integer(n)} 30 + end 31 + end) 32 + ``` 33 + 34 + ```output 35 + #Stream<[ 36 + enum: %File.Stream{ 37 + line_or_bytes: :line, 38 + modes: [:raw, :read_ahead, :binary], 39 + path: "day2.txt", 40 + raw: true 41 + }, 42 + funs: [#Function<47.58486609/1 in Stream.map/2>] 43 + ]> 44 + ``` 45 + 46 + ## Task 1 47 + 48 + ```elixir 49 + {h, d} = 50 + stream 51 + |> Enum.reduce({0, 0}, fn 52 + {:forward, n}, {h, d} -> {h + n, d} 53 + {:up, n}, {h, d} -> {h, d - n} 54 + {:down, n}, {h, d} -> {h, d + n} 55 + end) 56 + 57 + h * d 58 + ``` 59 + 60 + ```output 61 + 1499229 62 + ``` 63 + 64 + ## Task 2 65 + 66 + ```elixir 67 + {h, d, _} = 68 + stream 69 + |> Enum.reduce({0, 0, 0}, fn 70 + {:forward, n}, {h, d, a} -> {h + n, d + a * n, a} 71 + {:up, n}, {h, d, a} -> {h, d, a - n} 72 + {:down, n}, {h, d, a} -> {h, d, a + n} 73 + end) 74 + 75 + h * d 76 + ``` 77 + 78 + ```output 79 + 1340836560 80 + ```
+259
2021/day20.livemd
··· 1 + <!-- livebook:{"persist_outputs":true} --> 2 + 3 + # Day 20 4 + 5 + ## Section 6 + 7 + ```elixir 8 + [algo, board] = 9 + File.read!("day20.txt") 10 + |> String.split("\n\n") 11 + 12 + board = 13 + board 14 + |> String.split("\n", trim: true) 15 + |> Enum.with_index() 16 + |> Enum.flat_map(fn {row, y} -> 17 + :binary.bin_to_list(row) 18 + |> Enum.with_index() 19 + |> Enum.map(fn {c, x} -> {{x, y}, if(c == ?#, do: 1, else: 0)} end) 20 + end) 21 + |> Map.new() 22 + 23 + defmodule Day20 do 24 + defmodule Image do 25 + defstruct [:board, :background] 26 + 27 + @behaviour Access 28 + 29 + def new(board, background \\ 0), 30 + do: %__MODULE__{board: board, background: background} 31 + 32 + def dims(%__MODULE__{board: board}) do 33 + {{min_x, min_y}, {max_x, max_y}} = board |> Map.keys() |> Enum.min_max() 34 + 35 + {min_x..max_x, min_y..max_y} 36 + end 37 + 38 + def lighted(%__MODULE__{background: 1}), do: :inf 39 + def lighted(%__MODULE__{board: board}), do: board |> Map.values() |> Enum.sum() 40 + 41 + @impl Access 42 + def fetch(%__MODULE__{} = img, {_, _} = key) do 43 + case Map.fetch(img.board, key) do 44 + {:ok, value} -> {:ok, value} 45 + :error -> {:ok, img.background} 46 + end 47 + end 48 + 49 + def fetch(_data, _key), do: :error 50 + 51 + @impl Access 52 + def get_and_update(_data, _key, _func), do: :error 53 + 54 + @impl Access 55 + def pop(_data, _key), do: :error 56 + 57 + defimpl Inspect do 58 + import Inspect.Algebra 59 + 60 + def inspect(%@for{} = img, _opts) do 61 + {min_x..max_x, min_y..max_y} = @for.dims(img) 62 + 63 + display = 64 + for y <- (min_y - 1)..(max_y + 1) do 65 + row = 66 + for x <- (min_x - 1)..(max_x + 1) do 67 + if img[{x, y}] == 1, do: "█", else: " " 68 + end 69 + 70 + concat([concat(row), line()]) 71 + end 72 + 73 + concat([ 74 + "#Image<{#{max_x - min_x + 1}x#{max_y - min_y + 1}}", 75 + line(), 76 + concat(display), 77 + ">" 78 + ]) 79 + end 80 + end 81 + end 82 + 83 + defmodule Algo do 84 + defstruct [:desc] 85 + 86 + @behaviour Access 87 + 88 + def new(desc), do: %__MODULE__{desc: desc} 89 + 90 + @impl Access 91 + def fetch(%__MODULE__{desc: desc}, pos) do 92 + loc = rem(pos, 512) 93 + {:ok, if(binary_part(desc, loc, 1) == "#", do: 1, else: 0)} 94 + end 95 + 96 + @impl Access 97 + def get_and_update(_data, _key, _func), do: :error 98 + 99 + @impl Access 100 + def pop(_data, _key), do: :error 101 + end 102 + 103 + def get_bits(img, {x, y}) do 104 + digits = 105 + for dy <- -1..1, 106 + dx <- -1..1, 107 + do: img[{x + dx, y + dy}] 108 + 109 + Integer.undigits(digits, 2) 110 + end 111 + 112 + def enchance(img, algo) do 113 + {min_x..max_x, min_y..max_y} = Image.dims(img) 114 + 115 + board = 116 + for y <- (min_y - 1)..(max_y + 1), 117 + x <- (min_x - 1)..(max_x + 1), 118 + into: %{}, 119 + do: {{x, y}, algo[get_bits(img, {x, y})]} 120 + 121 + Image.new(board, algo[512 - img.background]) 122 + end 123 + end 124 + 125 + alg = Day20.Algo.new(algo) 126 + img = Day20.Image.new(board) 127 + ``` 128 + 129 + ```output 130 + #Image<{100x100} 131 + 132 + █ █ █ ██ ████████ ██ █ █ ███ █ ██ ██ █ ███ █ ██ █ █ █ ██ ███ █ ██ ██ █ ██ █ 133 + ███ █ █ █ █ ██ ██ █ ████ ██ █ █ ███ █ █ █ █ ███ █ █ ███ ██ ██████ █ █ █████ 134 + ██ █ ███ █ █ ███ ██ ███ █ █ █ █ █ █ ██ ███ ███ ██████ ████ █ █ ██ █ ██ ████ █ ██ 135 + █ ██ ████████ ██ █ █ █ █ ██ █ █ █ █ ██ ██ █ █ █ ██ █ █ █ ██████ █ █ █ 136 + ███ █ ██ ████ █ █ █ ███ ███ ██ █ █ ███ █ ██ █ ██ ███ █ ██ ██ ██ █ █ ████ █ █ 137 + ████ ███ █ ███ █ █ █ █ █████████ ████ █ █ ██ ██ █ █ █ █ █ █ █ █ ███ ██ ██ 138 + ███ █ █████ ████ ██ ████ █ █████ ██ ██ ████ ███ ███ ██ █ █ █ ██████ ██ █ ██ █ 139 + █ █ █ ███ █ █ █ █ ████ ████ █ █ █ █ █ █ █ ██ █ █ █ █ █████ ██ █ █ ███ 140 + ██ ██ ███ █ █ █ █ █ ████ █ ██ ███ █ █ █ ██ █ █ ██ ███ ███ █ █████ █ █ 141 + ██ █ █ █ █ ██ █ ██ ███ ███ ██ █ █ █████ █ ██ █ ███ █ █ ██ ███ █ █ ████ ██ ██████ 142 + █ █ ████ ███ █████ ███ ██ ██ ████ ██ ██ █████████ █ █ ████ ██ █ █ ██ █ ██ 143 + █ █ █ █ █ █ █ █ █ ███ ██ █ ██ █ █ ██ █ █████ █ ███ ██ █ █ █ ██ ██ ██████ ██ 144 + ██ ████ ██ █ ███████ ██ ██ ██ ████ ████ ██ ████ █ ███ █ ███ ██ █ ████ ███ ██ 145 + █ █ █ █ █ █ █ █ █ █████ █ █ ███ █ ██ █████ ██ █ █ █ ██ █ █ █ ███ █ █ █ █ █ 146 + ██ █ █ █ ███ ███ ██ ████ ███ █ ██ █ █ ██ ███ ██ █ █ ██ █ ██ █ ██ ██ █ █ █ █ █ ███ 147 + █ ██ █ █ █ █ ███ ██ ███████ ███ █ █ █████ ███ █ █ ███ ███ ███ ██████ █ █ █ █████ █ 148 + ████ █ ████ █ ████ ██ ████ ██ █ ██████ ███ ███ █ █ █ █ ██ ███████ ██ █ ████ ██ █ 149 + ██ █ ███ ██ ██ ███ █ █ █ █ ██ ███ ██ ██ █ ████ █ █ █ ████ █ ██ █ █ █ ██ █ 150 + █ █ █ ██ ███ █ ████ ██ ██ █ █ ██ ██ ██ ███ ██ ██ █ ███ ███ █ █ ███ █ 151 + ███ █ █ ██ ████ █ ██ ███ █ ██ █ █ █ █ ███ ██ ███ █ █ █ █ █ █████ █ ████ ██ ████ ██ 152 + █ █ █ ██ █ █ █ ███ ██████████ ██ █ ████ ██ ██ ███ ██ █ ██ █ █ █ ██ ███ █ 153 + █ █ ██ █ █ █ █ ██████████ ███ █ █ █ ██ █████ █ ██ █ ████ ███ █ █ ███ ███ ██ █ 154 + ███ █ ██ ██ ████ █ ████ ██ ██████ █ █ █ ██ █████ ████ ██ ████ ██████ █ ██ ██ █ 155 + ██ █████ █ ██ ███ ███ █ █ █ ██████ █ ████ ████ ██ ██ ██ ██ █ █ ████ █████ ██████ 156 + ██ █ █ ███ █ ████ █ ████ ██ █ ████ ██ ████ ██ █ ███ █ ███ █ █ █ ██ █ 157 + █ ███ ██ ██ █ ██ ██ █ █ ███ ██ █ █ █ ██ █ █ ██ █ █ █ ██ ██ █ █ █ █ █ ██ █ 158 + █████ █ ███ ███ █ █ ██ ███ ███ ██ ██ █ ███ █ ██ ███ █ ███ ██ ██ █ ██ ███ ████ ███ 159 + █ ████ █ █ ███ ██ █ ██ ██ █ █ █ ██ █ █ █ █ ██ █ ██ ██████ ██ ████ ██ █ █ 160 + █ █ █ ██ ██ ██ ███ █ ███ █ ██ █ █████ █ █ ██ ███████ ██ █ █ ██ ████ █████ █ █ ██ 161 + █ █ █ █ ██ ██ ██ ██ █ ██ ██ ███ █ █ █ ██ █ █ █ ██ ███ █ ███ █ █ ██ 162 + █ █ ████ █ ██ █ ███ ██ █ ██ █████████ ███ ██ ██ █ █ █ █ ██ ███ ██ █ 163 + ███ ██ █ █ █ ██ ██ ██ ██ █ █ █ ██ █ ██ █ ██ █ ██ ██ █ █ ████ ███ █ ██ ██ █ ███ ██ 164 + ███ █ ██████ █ ███ ██ ███ ██ █ ██████ ███ ███ █ ██ ██ █ ██ ██ ██ █ █ ██ ██ █ 165 + ██ █ █ ██ ██ █ █ ████ ██ █ █ █ ██ █████ ██ ██ █ ███ ███ ███ █ 166 + ██ ███ █ █ █ █ ██ █ ██ ████ ███ ██ █████ ██ █ ██ ██ █ █ █ ██████ █ █ ███ 167 + ██ ██ █ ███ █ ███ █ █ ███ ████ ██ █ █ █ ████ █ ████ ██ ███ █ ██ ██ ████ ███ █ █ ██ ██ 168 + █ █ █████ ██ █ ██ ███ █ █ █ █ █████████ ██ ██ █ █ ███ █ ██ ████████ █ ██ 169 + ██ ██ ██ ██ ██ ███ █ █ ████ █ █ █ ███ █ █ █ █ ███ █ █ ██ ██ ██ █ █ 170 + █ ██ █████ ██ █ ███ ██ ██ ██ █ █ █ █ █ █ █████ █ ██ █ ██ █ █ ████ ██ 171 + ██ ████ ██ █ ███ ████ ███ █ ██ ██ █ ██ █ ███ ███ █ █ ██████ █ █████ ██ █ ███ █ █ 172 + █ █ █ █ ███ █ █ ██ ███ █ ██ ████ █ █ █████ █ ███ ██████ █ ███ ██ ████ █ ██ █ █ 173 + █ ██ ██ █ ██ █ ██ █ █ █ █ ██ ██ █ ██ █ ██ █ █ ██ ███ ███ ██ █ █ █ ██ 174 + ███ ██ ██ █ █ ██ ████ ███ █ ████ ███ █ ██ █ █ █ ███ █ █ ███ █ ████ ██ █ █ ████ 175 + █ █ ██ ██ █ ██ █ █ ██ ██ ███ ███ ████ ██ ███ █ ██ ██ ██ ████ █ █ ██ ██ █ 176 + █ █ ██ █ █ ██ █ ████ ███████ ██ █ █ ██ █ █ ███ ███ █ ██ █ ██ █ ██ ██ █ █ ███ █ 177 + ████ █████ ██ ██ █████ █ █ ██ ██ ███ █ ███ █ █ ██ ███ ███ █████ ██ █ 178 + █ ███ ███ █ █ █ ██████ ███ ████ █████ ███ ███ ███ ██ █ ██ █ ██ ██ █ ███ █████ 179 + █ █ ██ █ ████ █████ ███ █ █████ █ █ █ █ █ ██ ██ █ █ █ █ ███ ███ ███ █████ █ ██ █ █ █ █ 180 + █ █ █ █ ██ █ ████ ███ █ █ ████████ ████ █ ██ █████ █ █ █ ███ █ █ ████ █ █ 181 + ██ ███ ███ █ ██ █ █ █ ████ █ ███ ██ █ █ ██████ ██ ██ █ █ ████ █ ███ █ 182 + ██ ████ ██ █ █ ████ █ ██ ██ ██ ███ █ ██ █ █ ██ █████ █████ █ █ █ █ ██ 183 + █ ██ █ ███ █ █ ██ ███ ███ ██ █ ██ ███ ████ █ █ █ █ ██ █ █ █ █████ █ █ █ █ 184 + █ ██ ███ ███ ███ █ █ █ ██ █ ███ ███ █ ██ █ █ ███ ██ █ ██ █ ██ ██ ██ █ 185 + ███ █ █ █ ███ ███ █ █ █████ ████ █ █ ██ █████ █ ███ █ █ ███████ ████ █ ██ 186 + █ ██ █████ █ ██ ███ ██ █ █ ██ ██ ██ █ █ █ █ ███ █ ██ █ ██ ██ █ █ ██ ██ ███ █ █ ██ 187 + ██ █ ████ ██ █ █████ █ █ ██████ ███ █ █ ██ ██ ██ █ ██ █ █ ██ ██ █ █ █ █ █ █ █ ██ █ 188 + █ ███████ █ █ ██ █ █ █ █ ████ █ █ █ █ █ ████ █ █ █ █ ██ ██ ██ ██ █ █ 189 + ██ █ ████ █ █ █ ████████ █ █ ███ █ ████ █ █████ ██ ████ █ ███ ██ █ █ █ ██ █████ 190 + ██ █ ██ █ █ █ █ █ █ █████████ █████ █ ███ █ ██ ██ █ ██ ███ ██ █ █ █ █ ████ █ █ ████ █ 191 + █████ ████ ██ ██ █ █ █ ██████ █ █ █ █ █ █ █ ██ █ █ ███ █ █ ████ ███ ██ █ █ █ █ 192 + ██ █ ███ ██████ █ █ █ ██████ ██ █ █ ██████ ███ ██ █████ ████ █ █ █ ██ ███ █ ██ ██ 193 + █ ████ ██ █ █ █ █ ███ ██ █ ██ █ █ █████ ██ ██ █ ████ ███ █ █ ██ ██ ████ ███ 194 + ██ ███ █ ███ █ ██ █ ██ ██ ███████ ██ █ █ ████ █ ████ ████ ███ ██ ██ ██ █ █ █ █ █ 195 + ██ █ ██████ █ █ ██ ██████ █████ ███ █ ███ ██ █ ███ █ █ █ ███ █ ████ ████ ██ ██ 196 + ████ █ ██ ██ █ █ █ ██ █ █ ██ █ ██ █ ███████ █ ██ ███ █ █ ███ ████ ███ █ █ █ 197 + █ ██ █ █ ██ ████ ███████ ██ █ ██ █ █ ██ █ ███ █ █ █ ███ █ █ ████ █ ██ █ █ 198 + ██ █ ██ ██ █ █ █ ███████ ██ █ ███ █ ███ █ ██ █ █ █ █ █ ██ ██ █ ███ ███ ██ ██ 199 + █ █ ███ █ ██ █████ █ ██ █ ██ ███ █ █ █ ██ █████ █████ ███ █ ████ █ █ ███ █ 200 + █ ████ █ █ █ █ ██████ ██ ██ ██ █ █ █ █ █ ██ █ ████████████ ███ ████ ███ ███ 201 + █ █ █ █ ██ ██ █ █ █ ████ ██ ██ █ █ █ ██ ██ █ █ █ █ █ █ ███ █ █████ ██ ███ █ █ 202 + █ █ ██ ███ █ █ ███ █ █ █ ██ ██ ████████ █ █ █████ █ █ █ ██ █ ██ ████ 203 + █ █████ █ ██ ███ █ █ █ █ ███ ██ █ ██ ██ █ █████ █ █ ██ █ ███ ██ █ █ ██ █ █ █ █ 204 + ███ █ █ █ █ ██ █ █ █ █ █ █ █ ███ ██ ████ ██████ █ █████ ███ ██ █ █ 205 + █ █ █ ██ █ █ ████ █ █ █████ █ █ █ █ ██ ██ █ █ █ █████ █ ██ █ 206 + █ ████ █ █ █ ██ ██ █ █ █ ██ ██ ██ ██ ██ █ █ █ ██ ██ ██ █ ██ █ █ ██ █ █ 207 + █ ████ ███ █████ █ █ ████ ██ █████ ██ ███ █ ███ ██ ██ ██ █ █ █ ███ █ 208 + █ █ ████ █ ██ █ █ ██████ ███████ █ ██ ███ ███ █ █ ██ █ ████ ███ █ ███ █ █ 209 + ███ ██ █ ██ █ █ █████ ██████ █ ██████ ██ █ ██ █ ██ ███ █ █ █ █ ███ ██ ████ ██ █ 210 + █ ███ █ █████ █ █ ███ ██ ██ ██ ███ █ █ █ █ █ ████ █ ████ █ ██ █ █ ██ 211 + █ ████ ███ █ █ ████ █ █ ██ ███ █ ██ █ █ ██ █ █ ██ █ █ ██ ██ █████ █ █ ███ █ ████ 212 + █ ██ ██ ██ ██ █ █ ██ ███ ████ ███ ████ █ ██ █ █ ███ ███ ██████ █████ ███ ████ █ 213 + ██ █ ███ █ █ ███ █ ██ ███ █ ██ █████ █ ███ █ █ ██ █ █ █ ████ ██ ██ ███ █ █ █ ██ 214 + █ ███ ███ ███ ██ █ ███ █ ████ ██ █ █ ███ █ ██ ██████ █ █ ███ █ ██ ██ ███ ██ █ █ 215 + █ █ █ █ █ █ █ █ █ █ ██ █ █ ███ ███ █ █ █████ █ █ █ █ █ █ █ █ ██ ██ █ ██ █ 216 + █ ██ █ █ ██ ██████ █ █ █ ██ █ █ ██ █ ███ █ █ █ ██ ██ █ █ ███████ 217 + ██ ██ █ █ █ █ █ ██████ ██ ████ █ █ █ ██ █ █ █ █ ███ █ ███ █ █ █ ██ ███ 218 + █ ████ █ ██ ██ ███ █ ██ █ ██ ████ █ █ ██ █ █ █ ███ █ ██ ██ ████ ███ 219 + █ ██ ██ █ █ █ █ ███ ██ █ ████ ████ ███ ██ ██ ██ ███ █ ██████ 220 + ███ ███ ██ █ █ ██ ██ █ ██ █ █ █ █ ███ █ ███ █ ██ ███ █ █████ ███ ███ ████ █ █ ██ 221 + ██ █ █ ████ █ █ ███ ██ █████ █ █ ██ █ █ ██ ██ █ ███ █ █ █ █ █ █ ██ █ ██ ██ 222 + ███ █████ ██ ██ █ ███ █ █ ███ ████ ██ █ █████ ██ █ ██ ████ █ █ █ 223 + ███ █ █ ███ █ ██ █ █████ █ ██ ████████ ██ ████ █ ████████ █ ███ █ ████ █ █ 224 + █ █ ██ █ ██ █ █ █ ██ ██ █ ██ █ ██ █ █ ██ ██ ██ █ ██ ███ ███ █ ██ ███ 225 + █ ███ ██ █ █ ███ ███ ██ ██ █ █ █ █ █ ███ █ ██ ██ █ █ ███████ █ ███ ███ 226 + ██ █ █ █ █ ████ ██ █ █████ ██████ █ █ █ █ █ ██ █ █ ███ █ █ █ █ ██ 227 + █ █ █ █ ████ ██ ██ █ █ █ ███ █ █ █ ██ █ █ ██ █ ██ █ █ █ ██ █ ███ █ ███ ██ 228 + ██ █ █ ██ ██ █ █ █ █ ███ █ ██ █ ██ █ █ █ █ ██ ██ ███ ██ ███ ██ ██████ ███ 229 + ██ █ █ █ █ █ ███ ███ ████ ██ ██ ███ █ █ ████ █ ███ █ ██ ██ █ █ ███ ███ █ █ █ ███ █ 230 + ██ ████ ██ █ █ █ █ █ ██ ██████ ██ █ █ █ █ █ █ █ █ ██ █ █ ████████ █ 231 + ████ ██ █ █ ████ █ █ ██ █ █ █ █ ██ █ █ █ ████ █ █████ ███ ██ █ ████ ██ ███ █ █ █ █████ 232 + 233 + > 234 + ``` 235 + 236 + ## Task 1 237 + 238 + ```elixir 239 + img 240 + |> Day20.enchance(alg) 241 + |> Day20.enchance(alg) 242 + |> Day20.Image.lighted() 243 + ``` 244 + 245 + ```output 246 + 5179 247 + ``` 248 + 249 + ## Task 2 250 + 251 + ```elixir 252 + 1..50 253 + |> Enum.reduce(img, fn _, acc -> Day20.enchance(acc, alg) end) 254 + |> Day20.Image.lighted() 255 + ``` 256 + 257 + ```output 258 + 16112 259 + ```
+102
2021/day20.txt
··· 1 + ####...###.###.##.##.##..###..##.#.##.#...####..##...#..#..#....#..#..##.##..#.#.####.######.#..#.##..##....#.####.##...#.#..#.####.#.#.#..###.##..#.#.#.#...#.....###.#.#...#..#....#######....#..#...###.##.........#.#.##.#........##...#..##.......####.#.#.#.#.#.####..#..........#.##......##......###.#..##.#.#.....###.#..#...###.##........#..#.##.#.###.#..#####..##..#..#.#.#...###..##..#.###.##...#.##.#.....#.#..........#..##.#########.#.#..##.#.##..######.....####...###..###.#..##########.#.#.....###.##.##. 2 + 3 + #.#...#..##..########...##....#.#.###.#.##.##...#..###.#.##.#.#..#..##..###....#..##.##....#...##.#. 4 + .###.#..#.#.#..##.##.#.####..##.#...#.###...#.#....#.#.###..#.#..###...##..######..#..#..#####...... 5 + ##.#.###.#.#..###...##..###.#.#..#....#...#..#.....##..###.###.######.####.#.#...##.#.##.####..#.##. 6 + ...#..##...########.##..#..#...#...#...##.#..#.#..#.##..##.#..#...#.##........#.#.#.######..#..#.#.. 7 + .....###....#.##....####..#.#.#.###.###.##.#.#.###..#..##.#...##.###..#.##..##.##..#.#....####..#.#. 8 + ..####..###.#..###.#.....#..#..#....#########.####.#..#.##.##..#....#.....#.#.#..#.#..#..###.##...## 9 + ###.#..#####...####.##...####...#.#####.##...##.####.###...###...##...#..#.#.######.##....#....##..# 10 + ...#...#.#.###..#.#..#.#.####..####.#..#...#...#.#...#...#.....##..#.....#.#.#....#####.##..#.#..### 11 + ##...##..###..#..#...#..#..#.####...#.##.###.#.#....#..##....#.....#.##.###.###.#.....#####.#...#... 12 + .##.#..#..#..#.##.#.##.###.###....##.#.#...#####.#..##..#....###..#.#...##.###.#..#.####..##..###### 13 + #.#..####.###.#####.###.##....##..####.##.##.#########.........#.#.....####.##.....#.#...##.#....##. 14 + .#..#.#.#..#.#.#.#.#..###....##.#.##.#....#.##.#....#####.#..###...##......#..#.#.##..##..######..## 15 + ..##.####.##.....#.#######..##.##...##.####.####.##...####..#.###....#..###..##..#.####....###..##.. 16 + #.#....#...#.#.#..#.#..#...#####..#.#..###.#.##...#####.....##.#....#.#.##.#..#.#..###...#.#.#..#..# 17 + ##.#.#..#.###.###.##.####....###.#.##.#.#.##...###.##.#.#...##.#.##..#.##.##.#.#....#.....#.#.###... 18 + .#.##.#....#.#.#.###.##..#######.###..#...#...#####.###.#.#.###..###...###.######.#.#....#...#####.# 19 + ####..#..####.#......####..##...####...##.#.######.###.###.#.#.#.#....##.#######....##.#..####..##.# 20 + ..##.#..###...##....##.###.#.#.#....#..##..###..##..##..#.####..#....#.#.####..#..##.#..#....#..##.# 21 + .#..#.#..##.###....#...####...##.##..#.#..##.##.##.###....##...##.....#.###......###..#.#..###....#. 22 + ###.#...#.##...####.#.##.###..#.....##.#.#...#.#..###.##..###.#..#.#.#.#.#####.#.####.##..####..##.. 23 + .....#.#..#.##...#..#.....#.###.##########.##.....#..####.##.##.###.##..#.##..#....#.#..##...###.#.. 24 + #..#.##.#.#.#..#....##########.###..#.#...#.##...#####..#..##..#..####.......###..#..#.###..###.##.# 25 + ###.#..##..##..####...#.####..##.######....#..#...#..##...#####.####.##.####...######..#..##...##..# 26 + ..##.#####...#.##..###...###.#......#.#.######.#...####.####.##.##....##..##.#.#..####.#####.######. 27 + ..##..#.#..###..#.....####..#.####.##.#.####.##.....####..##..#...###.#...###...#.#.#........##...#. 28 + .#.###.##.##.#.##.##..#.#.###...##..#..#..#.##.#.#..##.#.#.#.##....##....#.#......#....#..#....##.#. 29 + #####.#.###...###.#..#.##.###...###.##.##........#.###.#...##.###.#...###.##.##..#.##.###..####.###. 30 + #....####.#..#.###....##.#.##..##.....#..#...#...##.#..#.#...#..##.#..##..######.##..####.##...#.#.. 31 + ..#.#..#..##.##...##.###...#...###..#.##..#.#####..#.#.##.#######.##.#.#..##..####.....#####..#.#.## 32 + #.#.....#.#.##.##.##.##......#...##.##.###..#...#.#........##....#.#.....#.##.###....#..###..#..#.## 33 + ..#.#.####..#.##...#.###.##....#.##.#########.###...##...##.#.#....#...#...##.....###.##.........#.. 34 + ###.##.#.#...#...##...##...##.##.#..#.#....##.#.##..#..##.#.##.##..#.#.####.###.#.##.##....#.###.##. 35 + ###..#.######.#.###.##.###..##.#..######..###.....###......#.##..##..#.....##..##.##..#.#....##.##.# 36 + ..##.#....#.........##.##.#.#..####..##.#......#....#...##.#####..##........##....#.###...###.###..# 37 + ##...###.#.#..#.#..##.#.##.####....###....##.#####.##....#.##...##..#.....#....#...######..#.#...### 38 + .##.##.#..###.#.###.#.#.###...####.##.#.#.#.####.#...####.##..###.#...##..##.####..###.#.#..##..##.. 39 + #..#...#####.##...#...##..###.#.#....#.#...#########..##.....##.#.#...###......#.##.########..#.##.. 40 + ##..##.##.......##..##........###.#....#.####.#..#.#.###....#.#.#.#.###.#.#..##..##...##.#.....#.... 41 + ....#..##...#####...##..#.###....##.##..##.#....#....#..#.#...#.#####...#..##.#.##...#.#...####...## 42 + ..##..####.##....#.###.####...###.#.##.##...#..##..#.###.###.#.#.######.#..#####......##..#.###.#.#. 43 + #..#.#....#...###.#.#....##.###..#....##..####.#..#.#####.#.###.######...#..###.##..####.#...##.#..# 44 + ..#.##.##.#.##........#..##.....#.#.#.#.##.##..#..##...#.##...#...#.##.###..###.....##..#....#.#..## 45 + ###.##...##.#.#...##...####.###.#...####..###...#.##.#..#.#.###......#.#...###..#.####.##.#.#.####.. 46 + #.#.##.##...#..##..#....#.##..##......###..###...####..##...###.#.##.##..##...####.#.....#.##.##...# 47 + .....#...#.##.#..#.##.#.####.#######......##.#..#...##..#...#.###.###.#.##.#.##..#.##.##.#..#.###..# 48 + ####...#####..##....##.#####...#...#...##.....##..###..#...###..#...#...##.###..###.#####...##.#.... 49 + #..###...###....#.#.#.######.###..####..#####...###..###..###....##.#.##..#.##..##..#.###.#####..... 50 + #.#.##.#.####..#####.###.#..#####.#..#.#.#..#.##....##.#.#.#.#.###.###..###...#####.#.##.#.#.#..#... 51 + .#.#...#..#.##.#..####..###.#..#.########.####......#...##..#####..#...#.#..###..#.#....####....#..# 52 + ##.###.###..#..##.#..#...#..####..#.###..##....#.#...######.##....##...#....#.........####.#.###.#.. 53 + .##..####.##.#.#..####...#.##..##.##..###...#.....##...#......#....##...#####..#####.#.#.#...#..##.. 54 + .#...##.#.###.#.#.##....###..###.##.#.##.....###.####.......#.#.#.#....##.#..#..#..#####..#....#.#.# 55 + ..#.##.###.###.................###.#...#...#.##.#.###..###..#..##..#.#..###..##.#.##.#.##.##.##.#... 56 + ###.#...#..#...###.......###.#.#..#####.####.#..#...##...#####..#........###.#..#.#######..####.#.## 57 + ...#.##.#####.#...##.###...##.#..#..##.##.##..#.#.#.#.###...#.##..#.##.##.#.#.##...##.###....#..#.## 58 + ##.#.####.##.#..#####.#.#...######.###.#.#.##.##...##.#.##.#..#...##.##.#..#...#..#..#..#..#.##.#... 59 + #.#######.#..#.##..#..#.#..#..####....#.#..#..#...#.....####...#..#.......#..#...##..##.##.##..#.#.. 60 + ..##.#.####.#.#.#......########..#..#.....###.#.####.#..#####.##..####.#.###....##.#.#..#.##..#####. 61 + .##.#.##.#.#..#.#.#.#...#########...#####..#...###.#.##..##.#..##...###.##.#.#.#.#...####.#.#.####.# 62 + .#####.####..##.##....#.#.#...######.#.#..#.#.#....#.#....##.#..#.###..#..#.####...###..##.#.#.#.#.. 63 + .##..#..###.######.#.#.#..######.##..#..#.######....###.##..#####.....####.#.#.#...##.###.#...##.##. 64 + .#.####..##.#..#.#..#.###.##.#....##..#.#..#####.##.##...#..####..###..#........#.##..##.####...###. 65 + ..##..###.#.###.#...##.#.##.##.#######..##.#....#.####.#...####...####.###.##.##...##.#..#.#....#..# 66 + .##..#.######..#.#.##.....######.#####......###.#....###.##.#.###.#..#.#.###.#.####...####.##.....## 67 + .####....#.##.##.#.#....#.##.#..#...##.....#..##......#..#######..#.##.###.#..#.###.####..###.#.#..# 68 + ..#.##.#.#..##..####....#######.##...#.##.....#.#.##....#.###.#.#..#.###.#.....#.####.#.....##.#...# 69 + ##...#.##..##.#.........#..#..#######.##.#..###.#.###..#.##.#..#...#..#..#.##.##.#..###.###...##.##. 70 + ...#.#..###..#.##.#####.#.##...#.##..###.#...#...#.##....#####..#####....###..#.####.#...#.###.....# 71 + ..#.####..#..#.#..#.######...##.##...##...#.#.#.....#..#...##..#.############.###.####....###..###.. 72 + #.#...#.#.##..##..#.#..#...####.##.##.#.#.#.##..##.#.#.....#....#...#...#.###.#.#####..##.###...#..# 73 + .#....#.##..###.#..#.###.#..#.#..##..##.......########.#...#...#####.#...#..#..##.....#.##.....####. 74 + #.#####.#.##.###.#.#....#.#.###...##.#.....##..##..#.#####..#.#.##.#..###..##...#.#.##.#.#.....#.#.. 75 + ..###...#.#.......#.#......##.#..#.#.#.#.#...#.###.##...####....######......#...#####..###.##...#..# 76 + #..#...#..##..#...#...####.#...#....#####.#...#...#.#.....##...##..#...#....#..#####...#.....##...#. 77 + #.####.#...#...#..##...##....#...#.#.##.##.##...##..##.#..#..#.##.##.##.#.##......#.#...##.....#...# 78 + .#..####..###........#####...#....#.####..##..#####.##.###..#..###...##..##...##.....#..#.#.###.#... 79 + .#....#.####....#....##..#.#.######.#######.#.##.###.###...#.#....##..#..####.###.#....###...#.#.... 80 + ...###..##.#.##..#.#.#####.######.#..######.##...#.##.#..##.###.#.......#..#...#.###...##..####.##.# 81 + #....###....#..#####.#..#...###..##.##...##.###...#...#....#..#...#..####.#.####...#..##....#...#.## 82 + #.####.###...#..#.####...#..#.##.###.#.##.#....#..##.#.#...##.#..#.##.##..#####..#..#...###...#.#### 83 + #.##.##..##.##......#.#.##...###.####.###.####.#...##...#.#...###..###.######.#####....###.####.#... 84 + ##..#.###....#.#..###.#..##..###.#..##..#####.#.###..#.#...##.#.#.#.####....##...##....###.#.#.#..## 85 + ...#.###.###..###.##...#.###.#.####.##..#.#..###...#..##.######.#.#..###..#.##...##.###....##.#...#. 86 + #..#.#..#.#..#.#.#.#.#..##..#....#..###.###.#...#.#####.#..#..#.#....#.#.#.#....##.##..#...##......# 87 + ...#...##....#....#.##.######.#...#.....#.##..#....#..##.#.........###..#..#..#.##.##...#.#..####### 88 + ##.##..#..#.#..#.#.######.##...####...#...#..#..##.#......#.#....#.###..#.###...#...#...#.##...###.. 89 + #.####.#.##....##..###....#.##.#.##....####.#.#.##.#....#..#..###...#.....##.##....####..###........ 90 + ..#..##...##.#...#..#.#..###....##...#...####.....####....###..##..##..##.###..#.....######......... 91 + .###.###.##.#...#.##..##.#.##.#.#..#.#..###.#....###.#..##.###....#...#####.###..###.####..#.#...##. 92 + ..##.#.#.####.#..#..###.##.#####.#.#....##..#.#.##..##..#...###.#...#...#...#...#..#..##.#...##...## 93 + ......###..#####...##..##.#.....###.#...#..###..####..##..#..#####..##..#..##..####.#..#.........#.. 94 + ###............#.#.......###..#..##..#.#####.#.##.########.##..####.#.########..#.###.....#.####.#.# 95 + .#.....#....##..#.##..#...#.#.##.##..#.##...#.##.#..#......##.....##..##.#..##.###...###....#.##.### 96 + ..#...###....##....#.#...###.###..##.##...#.#.#.#..#....###.#.##.....##.#..#.#######.#.###...###.... 97 + ##.#.#.#.#...####.##..#.#####..######..#.#...#.#.........#....##.....#....#.###....#.#.#..#...##.... 98 + .......#.#.#..#....####.##.##.#.......#.#.###..#..#..#..##.#.#.##.#.##.#.#.#..##.#..###..#.###...##. 99 + ..##.#.#..##.##...#..#..#..#..###..#.##..#.##..#..#....#....#.##.##.###.##.###..##.......######.###. 100 + ##.#.#.#.#.#..###...###..####...##..##.###.#..#..####.#...###..#.##.##.#.#.###..###.#.#.#...###..#.. 101 + ..##...####......##..#..#..#...#...#..##...######.##......#.#.#....#.#.#.#..#..##.#...#.########...# 102 + ####.##.#.#.####..#.#.##.#..#...#.#.##.#....#..#.####.#.#####.###..##.#.####...##.###.#.#....#.#####
+95
2021/day21.livemd
··· 1 + <!-- livebook:{"persist_outputs":true} --> 2 + 3 + # Day 21 4 + 5 + ## Section 6 + 7 + ```elixir 8 + input = File.read!("day21.txt") 9 + 10 + [[_, p1], [_, p2]] = Regex.scan(~r/: (\d)/, input) 11 + 12 + p1 = String.to_integer(p1) 13 + p2 = String.to_integer(p2) 14 + 15 + {p1, p2} 16 + ``` 17 + 18 + ```output 19 + {3, 5} 20 + ``` 21 + 22 + ```elixir 23 + round = 24 + Stream.unfold(0, &{&1, &1 + 1}) 25 + |> Stream.scan({{0, p1}, {0, p2}}, fn n, {{s, p}, other} -> 26 + p = rem(p - 1 + 6 + n * 9, 10) + 1 27 + 28 + {other, {s + p, p}} 29 + end) 30 + |> Enum.take_while(fn {{s, _}, {_, _}} -> s < 1000 end) 31 + 32 + {rounds, {{loser, _}, _}} = {length(round), List.last(round)} 33 + 34 + rounds * 3 * loser 35 + ``` 36 + 37 + ```output 38 + 720750 39 + ``` 40 + 41 + ```elixir 42 + defmodule Day21.Task2 do 43 + def play(p1, p2) do 44 + tid = :ets.new(__MODULE__, []) 45 + {a, b} = cached_round({p1 - 1, 0}, {p2 - 1, 0}, tid) 46 + :ets.delete(tid) 47 + max(a, b) 48 + end 49 + 50 + defp cached_round(a, b, tid) do 51 + case :ets.lookup(tid, {a, b}) do 52 + [{_, v}] -> 53 + v 54 + 55 + [] -> 56 + value = round(a, b, tid) 57 + 58 + :ets.insert(tid, {{a, b}, value}) 59 + 60 + value 61 + end 62 + end 63 + 64 + defp round({_, s}, _, _) when s >= 21, do: {1, 0} 65 + defp round(_, {_, s}, _) when s >= 21, do: {0, 1} 66 + 67 + defp round({pos, score}, p2, tid) do 68 + for a <- 1..3, b <- 1..3, c <- 1..3, reduce: {0, 0} do 69 + {wins1, wins2} -> 70 + next = rem(pos + a + b + c, 10) 71 + 72 + {nscore2, nscore1} = 73 + cached_round( 74 + p2, 75 + {next, score + next + 1}, 76 + tid 77 + ) 78 + 79 + {wins1 + nscore1, wins2 + nscore2} 80 + end 81 + end 82 + end 83 + ``` 84 + 85 + ```output 86 + {:module, Day21.Task2, <<70, 79, 82, 49, 0, 0, 12, ...>>, {:round, 3}} 87 + ``` 88 + 89 + ```elixir 90 + Day21.Task2.play(p1, p2) 91 + ``` 92 + 93 + ```output 94 + 275067741811212 95 + ```
+2
2021/day21.txt
··· 1 + Player 1 starting position: 3 2 + Player 2 starting position: 5
+165
2021/day22.livemd
··· 1 + <!-- livebook:{"persist_outputs":true} --> 2 + 3 + # Day 22 4 + 5 + ## Input 6 + 7 + ```elixir 8 + input = 9 + File.stream!("day22.txt") 10 + |> Stream.map(&String.trim/1) 11 + |> Stream.map(&String.split(&1, [" "])) 12 + |> Enum.map(fn [action, rest] -> 13 + {_, bindings} = 14 + rest 15 + |> String.replace(",", ";") 16 + |> Code.eval_string() 17 + 18 + {String.to_atom(action), Map.new(bindings)} 19 + end) 20 + ``` 21 + 22 + ```output 23 + [ 24 + on: %{x: -40..7, y: -3..49, z: -48..6}, 25 + on: %{x: -38..10, y: -11..37, z: -30..19}, 26 + on: %{x: -43..1, y: -16..30, z: -38..13}, 27 + on: %{x: -10..44, y: -8..46, z: -41..4}, 28 + on: %{x: -27..19, y: -2..45, z: -33..12}, 29 + on: %{x: -41..4, y: -18..32, z: -34..19}, 30 + on: %{x: -43..9, y: -20..27, z: -34..20}, 31 + on: %{x: -47..-2, y: -5..49, z: -20..32}, 32 + on: %{x: -20..33, y: -40..6, z: -16..33}, 33 + on: %{x: -25..24, y: -47..-2, z: -46..6}, 34 + off: %{x: -28..-9, y: -6..4, z: 22..37}, 35 + on: %{x: -34..14, y: -16..32, z: -43..3}, 36 + off: %{x: -36..-18, y: -44..-33, z: 5..16}, 37 + on: %{x: -23..22, y: -34..11, z: -38..12}, 38 + off: %{x: -24..-15, y: 26..39, z: -18..-9}, 39 + on: %{x: -23..22, y: -31..20, z: -38..13}, 40 + off: %{x: -16..-6, y: 7..19, z: -44..-30}, 41 + on: %{x: -8..45, y: -18..28, z: -27..18}, 42 + off: %{x: -24..-8, y: -3..7, z: 33..45}, 43 + on: %{x: -28..18, y: -15..39, z: -18..35}, 44 + on: %{x: 52706..68579, y: -51721..-24984, z: -29134..-4745}, 45 + on: %{x: 19158..43390, y: 48482..62915, z: 36278..51760}, 46 + on: %{x: 33529..54535, y: 41410..44729, z: 35536..62066}, 47 + on: %{x: 39279..54831, y: -54196..-35294, z: -46321..-19146}, 48 + on: %{x: -49951..-33034, y: -75783..-65241, z: -32974..-9141}, 49 + on: %{x: 16267..33862, y: 32962..38520, z: 55102..80003}, 50 + on: %{x: 28231..33305, y: -13203..11551, z: -82121..-71765}, 51 + on: %{x: -3880..15012, y: -97354..-71276, z: -32509..-10704}, 52 + on: %{x: -59644..-43923, y: -56932..-39976, z: -46680..-24924}, 53 + on: %{x: -22171..6559, y: 59909..65127, z: 51012..71854}, 54 + on: %{x: -35278..-11377, y: -90913..-54535, z: 15441..29860}, 55 + on: %{x: 42440..47504, y: -77130..-54916, z: -5117..22780}, 56 + on: %{x: -23382..-925, y: -96268..-67199, z: -1408..16864}, 57 + on: %{x: 46073..66555, y: 2178..6843, z: -72379..-46993}, 58 + on: %{x: -7367..16256, y: 27822..35444, z: -81222..-57262}, 59 + on: %{x: 70121..85076, y: -2405..20765, z: -25162..-6383}, 60 + on: %{x: -38188..-8731, y: 303..24311, z: -85237..-74901}, 61 + on: %{x: 9308..35679, y: 72560..89334, z: -12862..6802}, 62 + on: %{x: 19088..20550, y: -54261..-29941, z: -66813..-56094}, 63 + on: %{x: 58563..67361, y: 32116..50251, z: -40547..-22471}, 64 + on: %{x: 63946..72885, y: -45525..-32975, z: 6297..33150}, 65 + on: %{x: 35523..45582, y: -46123..-39187, z: -62601..-55854}, 66 + on: %{x: -45263..-16076, y: 66141..71305, z: 24152..51511}, 67 + on: %{x: -56833..-39277, y: -61785..-39127, z: 20400..30866}, 68 + on: %{x: -64099..-47168, y: -14802..-10218, z: 59578..78286}, 69 + on: %{x: 54485..79540, y: -9884..13564, z: -33614..-29502}, 70 + on: %{x: -56136..-41543, y: 40175..50868, z: 18766..46233}, 71 + on: %{x: -29888..-22443, y: 56778..79471, ...}, 72 + on: %{x: 57940..83198, ...}, 73 + on: %{...}, 74 + ... 75 + ] 76 + ``` 77 + 78 + ## Implementation 79 + 80 + ```elixir 81 + defmodule Day22 do 82 + def volume(%{x: x, y: y, z: z}), 83 + do: Range.size(x) * Range.size(y) * Range.size(z) 84 + 85 + def volume(list), do: list |> Enum.map(&volume/1) |> Enum.sum() 86 + 87 + def apply({action, new}, cuboids) do 88 + cuboids = Enum.flat_map(cuboids, fn old -> sub(old, new) end) 89 + 90 + case action do 91 + :on -> [new | cuboids] 92 + :off -> cuboids 93 + end 94 + end 95 + 96 + defp sub(%{x: ax, y: ay, z: az} = a, %{x: bx, y: by, z: bz} = b) do 97 + if overlap?(a, b) do 98 + rx = split(ax, bx) 99 + ry = split(ay, by) 100 + rz = split(az, bz) 101 + 102 + for x <- rx, 103 + y <- ry, 104 + z <- rz, 105 + cube = cube(x, y, z), 106 + overlap?(cube, a), 107 + not overlap?(cube, b), 108 + do: cube 109 + else 110 + [a] 111 + end 112 + end 113 + 114 + defp overlap?(%{x: ax, y: ay, z: az}, %{x: bx, y: by, z: bz}) do 115 + not (Range.disjoint?(ax, bx) or 116 + Range.disjoint?(ay, by) or 117 + Range.disjoint?(az, bz)) 118 + end 119 + 120 + defp cube(x, y, z), do: %{x: x, y: y, z: z} 121 + 122 + # `b` is "whithin" `a` 123 + defp split(a1..a2, b1..b2) do 124 + [ 125 + a1..(b1 - 1)//1, 126 + max(a1, b1)..min(a2, b2)//1, 127 + (min(a2, b2) + 1)..a2//1 128 + ] 129 + |> Enum.reject(&(Range.size(&1) == 0)) 130 + end 131 + end 132 + ``` 133 + 134 + ```output 135 + {:module, Day22, <<70, 79, 82, 49, 0, 0, 18, ...>>, {:split, 2}} 136 + ``` 137 + 138 + ## Task 1 139 + 140 + ```elixir 141 + range = -50..50 142 + 143 + input 144 + |> Enum.reject(fn {_, v} -> 145 + Enum.any?(Map.values(v), &Range.disjoint?(&1, range)) 146 + end) 147 + |> Enum.reduce([], &Day22.apply/2) 148 + |> Day22.volume() 149 + ``` 150 + 151 + ```output 152 + 556501 153 + ``` 154 + 155 + ## Task 2 156 + 157 + ```elixir 158 + input 159 + |> Enum.reduce([], &Day22.apply/2) 160 + |> Day22.volume() 161 + ``` 162 + 163 + ```output 164 + 1217140271559773 165 + ```
+420
2021/day22.txt
··· 1 + on x=-40..7,y=-3..49,z=-48..6 2 + on x=-38..10,y=-11..37,z=-30..19 3 + on x=-43..1,y=-16..30,z=-38..13 4 + on x=-10..44,y=-8..46,z=-41..4 5 + on x=-27..19,y=-2..45,z=-33..12 6 + on x=-41..4,y=-18..32,z=-34..19 7 + on x=-43..9,y=-20..27,z=-34..20 8 + on x=-47..-2,y=-5..49,z=-20..32 9 + on x=-20..33,y=-40..6,z=-16..33 10 + on x=-25..24,y=-47..-2,z=-46..6 11 + off x=-28..-9,y=-6..4,z=22..37 12 + on x=-34..14,y=-16..32,z=-43..3 13 + off x=-36..-18,y=-44..-33,z=5..16 14 + on x=-23..22,y=-34..11,z=-38..12 15 + off x=-24..-15,y=26..39,z=-18..-9 16 + on x=-23..22,y=-31..20,z=-38..13 17 + off x=-16..-6,y=7..19,z=-44..-30 18 + on x=-8..45,y=-18..28,z=-27..18 19 + off x=-24..-8,y=-3..7,z=33..45 20 + on x=-28..18,y=-15..39,z=-18..35 21 + on x=52706..68579,y=-51721..-24984,z=-29134..-4745 22 + on x=19158..43390,y=48482..62915,z=36278..51760 23 + on x=33529..54535,y=41410..44729,z=35536..62066 24 + on x=39279..54831,y=-54196..-35294,z=-46321..-19146 25 + on x=-49951..-33034,y=-75783..-65241,z=-32974..-9141 26 + on x=16267..33862,y=32962..38520,z=55102..80003 27 + on x=28231..33305,y=-13203..11551,z=-82121..-71765 28 + on x=-3880..15012,y=-97354..-71276,z=-32509..-10704 29 + on x=-59644..-43923,y=-56932..-39976,z=-46680..-24924 30 + on x=-22171..6559,y=59909..65127,z=51012..71854 31 + on x=-35278..-11377,y=-90913..-54535,z=15441..29860 32 + on x=42440..47504,y=-77130..-54916,z=-5117..22780 33 + on x=-23382..-925,y=-96268..-67199,z=-1408..16864 34 + on x=46073..66555,y=2178..6843,z=-72379..-46993 35 + on x=-7367..16256,y=27822..35444,z=-81222..-57262 36 + on x=70121..85076,y=-2405..20765,z=-25162..-6383 37 + on x=-38188..-8731,y=303..24311,z=-85237..-74901 38 + on x=9308..35679,y=72560..89334,z=-12862..6802 39 + on x=19088..20550,y=-54261..-29941,z=-66813..-56094 40 + on x=58563..67361,y=32116..50251,z=-40547..-22471 41 + on x=63946..72885,y=-45525..-32975,z=6297..33150 42 + on x=35523..45582,y=-46123..-39187,z=-62601..-55854 43 + on x=-45263..-16076,y=66141..71305,z=24152..51511 44 + on x=-56833..-39277,y=-61785..-39127,z=20400..30866 45 + on x=-64099..-47168,y=-14802..-10218,z=59578..78286 46 + on x=54485..79540,y=-9884..13564,z=-33614..-29502 47 + on x=-56136..-41543,y=40175..50868,z=18766..46233 48 + on x=-29888..-22443,y=56778..79471,z=19514..30387 49 + on x=57940..83198,y=4819..24637,z=-36050..-14367 50 + on x=-35953..-18054,y=-92305..-62464,z=-24944..433 51 + on x=66547..83499,y=14135..24578,z=33083..41247 52 + on x=23558..38387,y=64415..73072,z=-28114..-14640 53 + on x=-13398..25438,y=-78327..-54021,z=32535..47622 54 + on x=59279..70463,y=-48832..-12639,z=18768..30270 55 + on x=-34289..-32327,y=35546..59245,z=55554..73170 56 + on x=15715..29890,y=-84334..-64420,z=12788..32323 57 + on x=-38593..-17951,y=-24585..-12831,z=-84437..-70981 58 + on x=-81422..-51852,y=-44476..-32475,z=-32716..-22730 59 + on x=-5856..25405,y=22130..39071,z=-84393..-56966 60 + on x=5807..22366,y=-82846..-62290,z=17828..22587 61 + on x=40912..63282,y=7257..37789,z=-67351..-34269 62 + on x=-60312..-52700,y=17308..35727,z=32687..57593 63 + on x=10748..21594,y=33001..48676,z=-71306..-63061 64 + on x=-67665..-47017,y=-76167..-51735,z=-13297..-8021 65 + on x=3312..26580,y=-35665..1379,z=-82617..-69610 66 + on x=35278..52989,y=25977..48545,z=55789..71242 67 + on x=17649..50914,y=-77065..-64303,z=-32515..-3058 68 + on x=55174..70296,y=-63489..-51834,z=-20117..3614 69 + on x=21633..36099,y=-56734..-43497,z=42283..51140 70 + on x=32220..54369,y=48382..79084,z=-38669..-15641 71 + on x=-41133..-21130,y=-43943..-12508,z=-72464..-67577 72 + on x=1841..14519,y=34565..69226,z=58731..72943 73 + on x=-81410..-71020,y=-41070..-11211,z=-25653..-2929 74 + on x=54878..79738,y=37397..60247,z=-29325..-413 75 + on x=-60358..-43018,y=-65054..-60356,z=991..20784 76 + on x=-73582..-57508,y=31733..47988,z=-185..25415 77 + on x=-8304..-1150,y=-81827..-65189,z=31671..57958 78 + on x=-76108..-70108,y=20214..27537,z=-16291..3825 79 + on x=15838..47053,y=-82389..-54043,z=3683..28928 80 + on x=33142..48892,y=-69396..-53597,z=10868..36599 81 + on x=-38048..-10804,y=-52011..-36488,z=51368..69373 82 + on x=-4568..12859,y=-45556..-29570,z=-81370..-56776 83 + on x=-16514..1528,y=-72602..-60172,z=-49767..-15535 84 + on x=53082..91975,y=-5166..3133,z=22143..45433 85 + on x=-88733..-57149,y=-41214..-19757,z=-22443..12286 86 + on x=46893..68079,y=-50078..-29688,z=-39574..-23241 87 + on x=-75085..-43624,y=16715..41482,z=-56327..-32898 88 + on x=-76474..-45397,y=-64897..-52688,z=-20583..9143 89 + on x=-19957..-2573,y=-59234..-31642,z=-79358..-61082 90 + on x=26667..54887,y=-48864..-21382,z=47058..75678 91 + on x=-44122..-16611,y=38155..71045,z=31473..49769 92 + on x=-33391..-25134,y=-28005..-19241,z=51281..71668 93 + on x=-87044..-63854,y=-23392..-7146,z=-2434..12126 94 + on x=-591..19282,y=49600..86073,z=-55053..-37283 95 + on x=-49830..-25077,y=45107..64739,z=-42830..-39577 96 + on x=-11624..9796,y=-69135..-58118,z=-60400..-46121 97 + on x=-45799..-24612,y=-62524..-47519,z=-37426..-28681 98 + on x=34798..65120,y=26496..42571,z=41925..56566 99 + on x=66112..68536,y=36258..50828,z=-1591..13570 100 + on x=-15520..17879,y=72198..76196,z=23426..37175 101 + on x=-39470..-24249,y=-82394..-63435,z=-20694..-7322 102 + on x=-51300..-19607,y=23582..45094,z=49327..75939 103 + on x=-40352..-26133,y=44295..65777,z=-60202..-38106 104 + on x=3094..9439,y=-7619..7072,z=-94190..-71205 105 + on x=70662..76847,y=32659..50544,z=-16957..-5542 106 + on x=76282..96199,y=-26320..7056,z=-18269..10065 107 + on x=-76248..-56030,y=23305..44186,z=-27243..-2017 108 + on x=37045..57820,y=59279..72594,z=-5542..20408 109 + on x=-44346..-20543,y=-87528..-58656,z=-35428..-2530 110 + on x=37275..59953,y=-13753..2122,z=-74562..-53204 111 + on x=52620..86557,y=23965..51715,z=-9509..-3827 112 + on x=35795..63942,y=-46269..-22225,z=-54424..-31197 113 + on x=-59544..-33767,y=9103..43984,z=-75618..-48873 114 + on x=48874..58442,y=-77723..-42490,z=-14491..-11057 115 + on x=37993..45421,y=60275..85636,z=-30638..4194 116 + on x=54414..87440,y=7165..14487,z=21373..49667 117 + on x=-31071..-8516,y=-63048..-54694,z=48010..53504 118 + on x=37842..60715,y=-72053..-51698,z=-19271..-12587 119 + on x=-44461..-12953,y=-33140..-19148,z=65167..75808 120 + on x=-25510..2687,y=-55779..-24569,z=-69951..-46736 121 + on x=-58173..-28520,y=-54375..-34513,z=-67610..-42556 122 + on x=49497..80937,y=22263..43733,z=-42858..-17317 123 + on x=-77801..-62492,y=-18176..-2842,z=16740..31884 124 + on x=-40193..-19152,y=-32522..2707,z=-79663..-66600 125 + on x=-50373..-23703,y=-46038..-12247,z=52074..71463 126 + on x=52388..77469,y=-31867..-443,z=-50390..-36826 127 + on x=-88034..-68737,y=-23143..-10464,z=-36065..-16663 128 + on x=-65232..-53363,y=-17477..5073,z=38324..58181 129 + on x=30925..53428,y=175..8144,z=57953..85443 130 + on x=-49373..-38200,y=-311..6146,z=-77273..-48532 131 + on x=32384..60171,y=53267..59287,z=12544..43012 132 + on x=-48309..-24591,y=69828..73698,z=-21642..-5616 133 + on x=-28570..-845,y=-24614..-5964,z=75229..91783 134 + on x=-84432..-51564,y=-17335..-10501,z=-41225..-31395 135 + on x=26592..43310,y=59225..62145,z=-45690..-22050 136 + on x=4610..29014,y=65924..77350,z=-42917..-26623 137 + on x=7145..20907,y=59641..72450,z=33512..51351 138 + on x=-7362..2555,y=66424..85969,z=-34868..-15252 139 + on x=-67112..-48950,y=-34742..-29850,z=33549..51770 140 + on x=5116..24556,y=-77258..-53349,z=-59199..-49610 141 + on x=-5223..12832,y=-85767..-62154,z=-63137..-25288 142 + on x=-57402..-38394,y=23575..43849,z=49017..68715 143 + on x=-5769..-3315,y=39128..68183,z=-71021..-52847 144 + on x=6932..24244,y=30420..51629,z=55953..65526 145 + on x=-29541..7458,y=-90145..-57044,z=-35054..-11576 146 + on x=-10648..7954,y=-52949..-37015,z=51897..84477 147 + on x=71634..87410,y=-20915..-15029,z=21564..38229 148 + on x=-45805..-19490,y=-76458..-46791,z=13612..38412 149 + on x=46952..72024,y=12007..31441,z=-64360..-43961 150 + on x=-83434..-50243,y=-40251..-12284,z=10710..45032 151 + on x=-84933..-68979,y=10644..21421,z=18662..43382 152 + on x=41424..64670,y=49202..67746,z=-3488..24596 153 + on x=-58317..-38261,y=25020..54489,z=-62333..-35139 154 + on x=31402..52264,y=-39865..-3557,z=-61229..-45665 155 + on x=11038..34450,y=-70660..-57200,z=23378..47844 156 + on x=-61703..-48338,y=28118..53935,z=40276..44980 157 + on x=-53403..-37172,y=-42771..-24798,z=44461..67302 158 + on x=-6688..14480,y=75749..99074,z=-5417..6505 159 + on x=5384..35432,y=-77335..-56400,z=-59871..-33791 160 + on x=1603..24013,y=59386..75157,z=17493..37220 161 + on x=16902..40265,y=20481..51075,z=-81132..-52892 162 + on x=-31160..-5046,y=-92494..-74285,z=8537..12802 163 + on x=-18183..-13833,y=13153..49953,z=66118..75643 164 + on x=55672..76342,y=2135..27763,z=-45212..-19364 165 + on x=35438..68301,y=43753..57908,z=-41226..-18528 166 + on x=23646..35699,y=-76449..-53997,z=-21377..-14127 167 + on x=-31654..-19008,y=18663..34709,z=-81288..-51590 168 + on x=-76966..-59040,y=-46340..-22258,z=-5666..22990 169 + on x=-31214..-20656,y=12464..42872,z=-86327..-52582 170 + on x=21093..34180,y=-67130..-31862,z=44205..71945 171 + on x=-68172..-49487,y=-62236..-47858,z=-31864..-4610 172 + on x=13353..24199,y=66632..85682,z=-12135..20096 173 + on x=-74820..-59297,y=-51864..-14460,z=-18528..3692 174 + on x=-13545..3537,y=63598..83395,z=-31867..528 175 + on x=-62438..-44176,y=-30526..3969,z=46663..68416 176 + on x=22083..43728,y=2257..18901,z=54139..77885 177 + on x=63102..90207,y=-36610..-21973,z=17017..37294 178 + on x=-25513..-2920,y=-55321..-26346,z=-82595..-58662 179 + on x=-59282..-47912,y=-22135..4940,z=-76370..-45984 180 + on x=-46516..-37421,y=-40875..-30419,z=50078..67090 181 + on x=247..17678,y=59666..73669,z=41161..66030 182 + on x=41843..59744,y=-66781..-53325,z=-8026..-866 183 + on x=56442..67337,y=31447..38104,z=15633..26441 184 + on x=22246..52258,y=-33697..-12636,z=45175..80705 185 + on x=25597..36312,y=1997..19204,z=-79738..-54986 186 + on x=-15480..5974,y=-36965..-8946,z=72200..96085 187 + on x=-44938..-16803,y=14179..37894,z=63576..70737 188 + on x=-60563..-26278,y=35288..61821,z=28791..43958 189 + on x=-2781..27047,y=-78181..-60658,z=7115..28869 190 + on x=10325..34851,y=-48783..-28260,z=-85849..-67966 191 + on x=-9545..5720,y=-66451..-53654,z=44770..66479 192 + on x=-58489..-28712,y=44411..67195,z=-58310..-33840 193 + on x=24722..34486,y=-67833..-40454,z=-67381..-40990 194 + on x=58610..73788,y=-12225..7126,z=23646..51111 195 + on x=-37164..-13729,y=62914..77209,z=11097..21143 196 + on x=50156..70243,y=-47706..-13090,z=-39835..-13351 197 + on x=76207..92507,y=-24144..7547,z=-2126..5790 198 + on x=7817..31657,y=-55682..-32888,z=-81159..-52172 199 + on x=71906..91201,y=12680..26262,z=3440..23272 200 + on x=-38023..-4461,y=-83735..-46050,z=-56158..-38260 201 + on x=-29161..-15540,y=-46665..-40319,z=57913..75651 202 + on x=-21117..-9729,y=-29641..-21318,z=70665..79125 203 + on x=-87374..-70709,y=-21190..-6753,z=-8554..26648 204 + on x=18046..42722,y=48725..78913,z=-43262..-35039 205 + on x=29634..46384,y=48479..70190,z=-54430..-25966 206 + on x=49482..67130,y=-27612..-5693,z=32204..54616 207 + on x=-18852..-12914,y=68426..76907,z=-30812..-26331 208 + on x=31377..37346,y=22930..58293,z=-67913..-49831 209 + on x=-39598..-27748,y=6896..20187,z=-73733..-67722 210 + on x=27751..40846,y=44762..73826,z=25432..54560 211 + on x=67176..86690,y=-29998..-10307,z=-42471..-11162 212 + on x=-60642..-28188,y=-43985..-29075,z=-70335..-53311 213 + on x=-23536..-1020,y=61753..77289,z=-65238..-29581 214 + on x=-75390..-64417,y=5503..30410,z=-42131..-14557 215 + on x=38542..53411,y=-59214..-34215,z=40608..53343 216 + on x=-9650..8906,y=-28406..3212,z=-82649..-62885 217 + on x=-2849..20704,y=-5170..17802,z=-79401..-74877 218 + on x=-56789..-34867,y=12504..18099,z=-63987..-57513 219 + on x=-42510..-29442,y=60034..69734,z=30430..48273 220 + on x=40496..64946,y=5792..10312,z=45679..68128 221 + off x=36887..57526,y=47538..63530,z=-42985..-28341 222 + off x=33479..58411,y=-68548..-46527,z=13251..39103 223 + on x=63072..81417,y=15646..49394,z=21504..45148 224 + off x=-76216..-61912,y=-30534..-17551,z=-50280..-26222 225 + off x=25878..59914,y=-64350..-36188,z=27874..39360 226 + on x=-51496..-46945,y=-5396..29398,z=-78407..-50985 227 + off x=-68762..-50445,y=33207..52061,z=-42617..-15847 228 + off x=-45658..-24730,y=-13226..12659,z=57392..77206 229 + on x=-8068..23761,y=-48399..-28155,z=50498..71412 230 + on x=16850..27765,y=-77260..-62223,z=-47859..-28554 231 + on x=-24227..-1152,y=60223..84591,z=-28685..-1888 232 + on x=-83203..-60907,y=-38213..-1290,z=-19771..-3635 233 + off x=22050..29566,y=-55088..-28774,z=-82502..-48350 234 + off x=55602..73932,y=30508..60779,z=-18418..563 235 + on x=18396..43696,y=48295..65403,z=-50879..-28862 236 + off x=58964..95810,y=5076..9444,z=-15462..-7722 237 + off x=65419..97082,y=-12404..4511,z=-19581..3679 238 + off x=58822..78853,y=-31174..-6818,z=-32926..-19059 239 + off x=2312..14918,y=-14468..-8421,z=-82159..-63347 240 + off x=-8615..6715,y=-34749..-9928,z=-85890..-73180 241 + on x=10021..28727,y=60507..75964,z=-46068..-16944 242 + on x=47209..85189,y=-33718..-120,z=-50448..-29027 243 + off x=-69679..-64804,y=-62936..-27943,z=-6028..3121 244 + on x=11568..38288,y=-77218..-72840,z=-1658..28856 245 + off x=68949..83664,y=-11073..17816,z=29484..47100 246 + on x=-42138..-25168,y=22944..40683,z=45644..72158 247 + off x=-54212..-23198,y=54848..84031,z=-34752..-8583 248 + off x=-61743..-43915,y=-62636..-51044,z=-40084..-19481 249 + off x=-58593..-36205,y=-53837..-28785,z=34877..51154 250 + on x=-29140..-7627,y=-81905..-73121,z=714..9303 251 + off x=-70736..-46090,y=-53884..-41570,z=-23826..-13883 252 + on x=64926..88584,y=-32881..-6387,z=18988..43795 253 + on x=33758..45337,y=-41289..-13923,z=66720..86882 254 + off x=67177..85594,y=-1270..27149,z=-12298..10562 255 + on x=-30728..-9677,y=-80101..-71392,z=-7737..6045 256 + on x=-34058..-11169,y=-84130..-59611,z=-2411..25556 257 + on x=-82888..-45532,y=-53498..-43399,z=-15466..12569 258 + on x=53096..73732,y=-31292..-271,z=46937..54564 259 + off x=58806..72491,y=-35114..-15573,z=-32393..-15887 260 + on x=-32570..-20445,y=-70056..-55586,z=15130..43528 261 + off x=8231..26748,y=-52110..-30753,z=-83079..-61762 262 + on x=-7168..18004,y=-85219..-76351,z=-55..15553 263 + on x=-48759..-17822,y=56514..81093,z=-17816..-268 264 + off x=71494..89379,y=-20577..5421,z=-16229..3599 265 + on x=-74127..-61857,y=-37318..-16386,z=23418..48020 266 + off x=46250..64727,y=39997..55663,z=-659..22759 267 + on x=-3747..18906,y=-88542..-51288,z=-50866..-25393 268 + on x=11967..39179,y=-42409..-27075,z=51760..78913 269 + off x=32634..54583,y=53351..78683,z=37069..52980 270 + on x=-45801..-34391,y=6739..35543,z=-80719..-61475 271 + off x=-59939..-43493,y=-2816..19380,z=43062..76353 272 + on x=-54552..-45916,y=30463..59717,z=-60676..-40687 273 + off x=947..37295,y=17259..35699,z=-77711..-57213 274 + on x=-34155..-16112,y=58205..77747,z=10469..35078 275 + off x=-41364..-24954,y=-55475..-20679,z=53974..74195 276 + on x=-5866..6658,y=-10037..4333,z=69763..93051 277 + off x=40058..68698,y=51027..74309,z=-3345..5414 278 + on x=-41513..-26098,y=-47848..-29818,z=44033..62222 279 + off x=-68876..-57248,y=30233..44005,z=21522..38471 280 + on x=-10503..7050,y=-33479..-26016,z=-81965..-69000 281 + on x=-63996..-35550,y=23827..38930,z=50227..78098 282 + on x=-34663..-17363,y=57015..82338,z=-32869..-17105 283 + on x=30784..51645,y=32138..66808,z=31941..61168 284 + off x=-3755..2895,y=-64141..-57971,z=36971..58497 285 + on x=-20087..3384,y=-63838..-35555,z=57392..69703 286 + on x=-86557..-54970,y=14861..40412,z=27350..36531 287 + on x=15258..32146,y=26537..42919,z=65823..68594 288 + off x=13862..42242,y=-84456..-71150,z=-13132..5905 289 + off x=-42982..-21849,y=-73917..-48154,z=21993..50847 290 + on x=-29379..-7101,y=29242..38662,z=-79142..-60459 291 + off x=11546..49500,y=61301..86969,z=-22865..4577 292 + on x=-48399..-37677,y=60118..82209,z=-25376..-6657 293 + on x=-57062..-36839,y=-59454..-56603,z=13677..38428 294 + off x=-34067..-21168,y=-81243..-56765,z=-17444..3822 295 + off x=44352..64136,y=50950..67304,z=1643..23339 296 + off x=64615..79759,y=19545..29449,z=-24935..-16190 297 + off x=25709..39422,y=-76035..-66047,z=-30123..3414 298 + on x=-66361..-38785,y=-60420..-53479,z=13651..34601 299 + on x=26547..53719,y=25778..42415,z=-71893..-46470 300 + off x=35485..64687,y=32129..59334,z=31017..53502 301 + off x=-27532..-16323,y=42528..53056,z=44767..66976 302 + off x=-85657..-60092,y=-4500..16282,z=25434..42820 303 + on x=10591..32952,y=-55737..-51910,z=45939..63149 304 + off x=37813..46415,y=-23900..-17178,z=-86629..-47985 305 + on x=-73010..-52678,y=21009..53737,z=11818..30585 306 + on x=54601..63218,y=-64449..-41296,z=-8460..15915 307 + on x=-16576..-10827,y=4232..34251,z=-81741..-62897 308 + on x=67542..81394,y=-5704..24443,z=-36781..-3582 309 + on x=-10656..21150,y=-13060..12841,z=-92317..-74508 310 + on x=-64593..-54055,y=38045..53878,z=-46825..-28151 311 + off x=36627..44665,y=-34351..-5917,z=-85072..-68088 312 + off x=-23261..-5824,y=-22196..13929,z=57375..80182 313 + off x=-32414..-14305,y=-83945..-60848,z=-17901..-6229 314 + off x=-69199..-45106,y=-35361..-11117,z=47106..48416 315 + on x=-17361..309,y=-87112..-75083,z=-17309..-846 316 + on x=49576..70268,y=-52965..-28866,z=-33749..-13320 317 + off x=-84872..-60225,y=21104..41143,z=-33952..253 318 + off x=25065..53172,y=-74764..-50642,z=-27008..-12427 319 + on x=5466..28561,y=58871..87353,z=3407..31099 320 + off x=58159..69905,y=1719..21038,z=-56660..-32952 321 + on x=49812..75324,y=42397..58595,z=10501..19992 322 + off x=-28176..-5545,y=-4561..10768,z=66184..83235 323 + on x=-36512..-16357,y=6529..33157,z=61540..79962 324 + on x=-76835..-51187,y=23689..47550,z=26996..57187 325 + on x=15920..39818,y=-73996..-51623,z=-40686..-18624 326 + on x=74449..92921,y=-30516..-17926,z=6351..21131 327 + off x=-36036..-18588,y=66163..82239,z=12845..17683 328 + on x=-58293..-40285,y=41167..63632,z=5699..26703 329 + off x=55508..80984,y=411..28348,z=45931..48884 330 + on x=36567..70716,y=-64313..-46937,z=19533..31078 331 + on x=57973..76789,y=640..32503,z=-46928..-15585 332 + on x=40700..59637,y=58372..73306,z=-34813..-17979 333 + on x=-35809..-16448,y=14279..36807,z=59850..75883 334 + off x=-11980..15927,y=71172..89369,z=27605..44939 335 + off x=-28383..-12868,y=-49010..-14693,z=67766..71069 336 + on x=-63520..-57313,y=-65070..-41322,z=7548..28820 337 + off x=-30097..-9794,y=50203..76545,z=-47190..-22675 338 + on x=-10027..13876,y=42660..67586,z=-62549..-45351 339 + off x=-75743..-41761,y=-18063..-8438,z=43896..51143 340 + on x=-53973..-21852,y=19812..35895,z=-65245..-53623 341 + on x=9327..30980,y=60724..81052,z=4679..22655 342 + on x=-9382..14696,y=-12635..-7880,z=-92088..-71928 343 + on x=-49568..-21303,y=45400..66270,z=-37218..-23585 344 + on x=26374..50716,y=29522..45024,z=-72113..-50858 345 + off x=-7123..9906,y=-30606..-21570,z=-89692..-60367 346 + off x=24645..34685,y=-7385..-535,z=-75457..-69280 347 + off x=46600..75937,y=42638..62019,z=-15214..-800 348 + off x=-73156..-64899,y=-18542..6622,z=-51976..-33625 349 + on x=-46953..-31989,y=-43453..-17942,z=48050..68549 350 + off x=44491..64439,y=-52270..-47527,z=25565..42399 351 + on x=54480..85695,y=-56683..-30655,z=-8303..15795 352 + on x=29997..57709,y=62586..84888,z=-22633..2635 353 + on x=-56730..-33262,y=-61124..-36167,z=-44900..-31218 354 + on x=-36099..-17509,y=59225..80566,z=-49431..-28644 355 + on x=45514..74203,y=-2009..10424,z=-65113..-45173 356 + off x=-31309..-22150,y=-84143..-63111,z=26691..48979 357 + off x=-68448..-52444,y=-49282..-47076,z=-6567..21766 358 + on x=9190..23305,y=-40030..-24391,z=56198..85303 359 + off x=5498..22227,y=-43923..-15355,z=-85770..-69241 360 + off x=-61505..-41086,y=34956..58168,z=-43349..-24183 361 + on x=-458..11929,y=14735..44319,z=60006..73064 362 + off x=54250..68185,y=-71222..-34674,z=-28518..-15694 363 + off x=-28528..42,y=-45762..-25317,z=64430..72231 364 + off x=17184..32440,y=-43934..-25096,z=-75789..-65047 365 + on x=-54107..-45535,y=-647..29416,z=56621..66738 366 + on x=-63306..-50383,y=-54815..-51798,z=3488..23514 367 + off x=-33064..-17821,y=-68795..-40276,z=48722..58281 368 + off x=28813..45569,y=10091..43242,z=48567..79748 369 + on x=-34407..-13658,y=-82959..-67725,z=-14721..-7549 370 + off x=11006..38914,y=-64578..-54646,z=31394..48188 371 + on x=-89516..-56035,y=-33338..-20011,z=23842..40221 372 + on x=12382..42662,y=51972..71326,z=-51009..-29545 373 + on x=-23497..-510,y=-14057..6559,z=-82664..-61835 374 + off x=42738..44332,y=-45357..-25100,z=44137..62767 375 + off x=-19799..9546,y=-63709..-45750,z=48687..64170 376 + off x=-50529..-30472,y=-47930..-19905,z=-75205..-45624 377 + off x=-23531..14033,y=68487..89564,z=8925..28259 378 + on x=1663..20113,y=56791..75346,z=12276..44119 379 + off x=45731..75170,y=-23286..393,z=-64525..-28621 380 + on x=-78486..-56778,y=-31099..-18591,z=-48346..-25135 381 + on x=-43514..-34754,y=67709..72495,z=-16374..5180 382 + off x=32961..61842,y=-62894..-41340,z=-33931..-15049 383 + on x=-52937..-36075,y=64942..83439,z=-3622..27175 384 + off x=41640..61376,y=-70913..-50192,z=-23373..-12724 385 + on x=16109..24715,y=-19443..8667,z=75001..90517 386 + off x=14880..41615,y=37677..55218,z=-64590..-40070 387 + off x=-93344..-73236,y=-27796..-24908,z=-10127..16501 388 + off x=59960..65418,y=-4002..12224,z=-67984..-42193 389 + on x=42351..56746,y=-20084..-13129,z=-65765..-51230 390 + off x=-59234..-29355,y=-71438..-58469,z=-11162..7404 391 + on x=51040..67401,y=-60224..-40198,z=-546..19625 392 + on x=-77978..-59874,y=36001..58307,z=14976..23796 393 + off x=56211..75341,y=8311..17708,z=-53749..-20735 394 + on x=-36432..-7183,y=19575..30346,z=-86318..-58459 395 + off x=-287..4588,y=-90791..-66459,z=-21768..4012 396 + off x=-79379..-62831,y=-31440..-593,z=-17403..8089 397 + off x=-35905..-18333,y=29389..56106,z=42947..70271 398 + off x=25117..47923,y=3093..37238,z=-77359..-65332 399 + on x=56769..88321,y=-37074..-5686,z=-21787..-6401 400 + on x=-28981..-10417,y=28580..52377,z=-77998..-54458 401 + off x=-24957..-267,y=35439..53345,z=51302..86849 402 + off x=-47011..-30673,y=-6746..-378,z=65710..79497 403 + off x=-73026..-58387,y=-27117..-1079,z=-58305..-36042 404 + off x=-20512..4246,y=45491..71174,z=48277..50414 405 + on x=23379..43354,y=63961..93513,z=3964..25213 406 + off x=597..17616,y=-83653..-72150,z=-11879..21798 407 + off x=-58597..-46587,y=12126..39528,z=-75993..-36792 408 + on x=-2903..11768,y=72176..88526,z=23687..33143 409 + on x=12525..24278,y=-2148..6961,z=59625..82181 410 + on x=-84588..-72500,y=-29471..-14022,z=-16989..13434 411 + off x=-58154..-34165,y=-74940..-54914,z=12160..19819 412 + off x=-6724..14627,y=22646..53365,z=-88495..-61533 413 + on x=-87262..-70236,y=-23648..3813,z=11206..27547 414 + on x=53546..71522,y=-28908..-8027,z=46725..60604 415 + on x=-81664..-64558,y=-26054..-6136,z=-43138..-11228 416 + off x=74496..91204,y=1367..9913,z=-2108..16186 417 + on x=-69821..-39879,y=-4418..23997,z=-65231..-50478 418 + off x=6104..33203,y=65171..78461,z=26193..44937 419 + off x=-4928..16268,y=50554..71798,z=-66020..-34009 420 + off x=22174..43968,y=-69871..-46557,z=-37898..-23874
+90
2021/day3.livemd
··· 1 + <!-- vim:ft=markdown 2 + --> 3 + 4 + <!-- livebook:{"persist_outputs":true} --> 5 + 6 + # Day 3 7 + 8 + ## Input 9 + 10 + ```elixir 11 + stream = 12 + File.stream!("day3.txt") 13 + |> Enum.map(&String.trim/1) 14 + |> Enum.map(&String.to_charlist/1) 15 + 16 + defmodule Day3 do 17 + def count(list) do 18 + Enum.reduce(list, List.duplicate(0, 12), fn input, acc -> 19 + for {value, counter} <- Enum.zip(input, acc) do 20 + case value do 21 + ?1 -> counter + 1 22 + ?0 -> counter 23 + end 24 + end 25 + end) 26 + end 27 + end 28 + ``` 29 + 30 + ```output 31 + {:module, Day3, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:count, 1}} 32 + ``` 33 + 34 + ## Task 1 35 + 36 + ```elixir 37 + half = div(length(stream), 2) 38 + 39 + {a, b} = 40 + stream 41 + |> Day3.count() 42 + |> Enum.reduce({0, 0}, fn elem, {a, b} -> 43 + if elem > half do 44 + {a * 2 + 1, b * 2} 45 + else 46 + {a * 2, b * 2 + 1} 47 + end 48 + end) 49 + 50 + a * b 51 + ``` 52 + 53 + ```output 54 + 3847100 55 + ``` 56 + 57 + ## Task 2 58 + 59 + ```elixir 60 + defmodule Day3.Task2 do 61 + def reduce(list, cb), do: reduce(list, 0, cb) 62 + 63 + defp reduce([elem], _, _), do: elem 64 + 65 + defp reduce(list, at, cb) do 66 + counts = Day3.count(list) 67 + 68 + half = div(length(list), 2) 69 + count = Enum.at(counts, at) 70 + 71 + bit = 72 + cond do 73 + count == half and cb.(count + 1, half) -> ?1 74 + count != half and cb.(count, half) -> ?1 75 + true -> ?0 76 + end 77 + 78 + reduce(Enum.filter(list, &(Enum.at(&1, at) == bit)), at + 1, cb) 79 + end 80 + end 81 + 82 + co2 = List.to_integer(Day3.Task2.reduce(stream, &</2), 2) 83 + o2 = List.to_integer(Day3.Task2.reduce(stream, &>/2), 2) 84 + 85 + co2 * o2 86 + ``` 87 + 88 + ```output 89 + 4105235 90 + ```
+126
2021/day4.livemd
··· 1 + <!-- vim:ft=markdown 2 + --> 3 + 4 + <!-- livebook:{"persist_outputs":true} --> 5 + 6 + # Day 4 7 + 8 + ## Input 9 + 10 + This time it is a little bit more convoluted, as there are 2 parts of the input. 11 + Fortunately we can easily disect the parts via pattern matching. 12 + 13 + Technically the conversion to the numbers is not needed, but it does no harm 14 + and provides additional layer of safety against some whitespace characters left there 15 + and here. 16 + 17 + The `Day4.win/2` function is manually unrolled, as it is easier to write than some 18 + random jumping in the list. 19 + 20 + <!-- livebook:{"disable_formatting":true} --> 21 + 22 + ```elixir 23 + [numbers | bingos] = 24 + File.read!("day4.txt") 25 + |> String.split("\n\n", trim: true) 26 + 27 + numbers = 28 + numbers 29 + |> String.trim() 30 + |> String.split(",") 31 + |> Enum.map(&String.to_integer/1) 32 + 33 + bingos = 34 + bingos 35 + |> Enum.map(fn bingo -> 36 + bingo 37 + |> String.split(~r/\s+/, trim: true) 38 + |> Enum.map(&String.to_integer/1) 39 + end) 40 + 41 + defmodule Day4 do 42 + def win( 43 + [ 44 + a1, a2, a3, a4, a5, 45 + b1, b2, b3, b4, b5, 46 + c1, c2, c3, c4, c5, 47 + d1, d2, d3, d4, d5, 48 + e1, e2, e3, e4, e5 49 + ], 50 + nums 51 + ) do 52 + # Rows 53 + all_in([a1, a2, a3, a4, a5], nums) or 54 + all_in([b1, b3, b3, b4, b5], nums) or 55 + all_in([c1, c2, c3, c4, c5], nums) or 56 + all_in([d1, d2, d3, d4, d5], nums) or 57 + all_in([e1, e2, e3, e4, e5], nums) or 58 + # Columns 59 + all_in([a1, b1, c1, d1, e1], nums) or 60 + all_in([a2, b2, c2, d2, e2], nums) or 61 + all_in([a3, b3, c3, d3, e3], nums) or 62 + all_in([a4, b4, c4, d4, e4], nums) or 63 + all_in([a5, b5, c5, d5, e5], nums) 64 + end 65 + 66 + def not_matched(bingo, nums) do 67 + Enum.reject(bingo, &(&1 in nums)) 68 + end 69 + 70 + defp all_in(list, nums) do 71 + Enum.all?(list, &(&1 in nums)) 72 + end 73 + end 74 + ``` 75 + 76 + ```output 77 + {:module, Day4, <<70, 79, 82, 49, 0, 0, 15, ...>>, {:all_in, 2}} 78 + ``` 79 + 80 + ## Task 1 81 + 82 + We simply traverse the `numbers` list aggregating the numbers (order doesn't really matter, 83 + here we aggregate them in reverse order to speedup the code). When we have enough numbers 84 + that any of the `bingos` is winning one, then we halt the reduction and return computed 85 + result. 86 + 87 + ```elixir 88 + numbers 89 + |> Enum.reduce_while([], fn elem, acc -> 90 + matches = [elem | acc] 91 + 92 + case Enum.find(bingos, &Day4.win(&1, matches)) do 93 + nil -> {:cont, matches} 94 + bingo -> {:halt, Enum.sum(Day4.not_matched(bingo, matches)) * elem} 95 + end 96 + end) 97 + ``` 98 + 99 + ```output 100 + 34506 101 + ``` 102 + 103 + ## Task 2 104 + 105 + ```elixir 106 + numbers 107 + |> Enum.reduce_while({bingos, []}, fn elem, {bingos, acc} -> 108 + matches = [elem | acc] 109 + 110 + case bingos do 111 + [bingo] -> 112 + if Day4.win(bingo, matches) do 113 + {:halt, Enum.sum(Day4.not_matched(bingo, matches)) * elem} 114 + else 115 + {:cont, {bingos, matches}} 116 + end 117 + 118 + _ -> 119 + {:cont, {Enum.reject(bingos, &Day4.win(&1, matches)), matches}} 120 + end 121 + end) 122 + ``` 123 + 124 + ```output 125 + 7686 126 + ```
+109
2021/day5.livemd
··· 1 + <!-- vim:ft=markdown 2 + --> 3 + 4 + <!-- livebook:{"persist_outputs":true} --> 5 + 6 + # Day 5 7 + 8 + ```elixir 9 + defmodule Day5 do 10 + defmodule Point do 11 + defstruct [:x, :y] 12 + 13 + def parse(input) do 14 + [x, y] = String.split(input, ",") 15 + 16 + %__MODULE__{x: String.to_integer(x), y: String.to_integer(y)} 17 + end 18 + end 19 + 20 + defmodule Line do 21 + defstruct [:start, :finish] 22 + 23 + def new(a, b) do 24 + {start, finish} = 25 + cond do 26 + a.x < b.x -> {a, b} 27 + a.y < b.y -> {a, b} 28 + true -> {b, a} 29 + end 30 + 31 + %__MODULE__{start: start, finish: finish} 32 + end 33 + 34 + def horizontal?(a), do: a.start.y == a.finish.y 35 + def vertical?(a), do: a.start.x == a.finish.x 36 + 37 + def points(a) do 38 + case {sign(a.finish.x - a.start.x), sign(a.finish.y - a.start.y)} do 39 + {0, dy} -> for y <- a.start.y..a.finish.y//dy, do: {a.start.x, y} 40 + {dx, 0} -> for x <- a.start.x..a.finish.x//dx, do: {x, a.start.y} 41 + {dx, dy} -> Enum.zip(a.start.x..a.finish.x//dx, a.start.y..a.finish.y//dy) 42 + end 43 + end 44 + 45 + def orientation(a) do 46 + cond do 47 + horizontal?(a) -> :horizontal 48 + vertical?(a) -> :vertical 49 + true -> :diagonal 50 + end 51 + end 52 + 53 + defp sign(0), do: 0 54 + defp sign(x) when x < 0, do: -1 55 + defp sign(x) when x > 0, do: 1 56 + end 57 + end 58 + 59 + lines = 60 + File.stream!("day5.txt") 61 + |> Stream.map(&String.trim/1) 62 + |> Stream.map(fn input -> 63 + [a, b] = String.split(input, " -> ") 64 + 65 + pa = Day5.Point.parse(a) 66 + pb = Day5.Point.parse(b) 67 + 68 + Day5.Line.new(pa, pb) 69 + end) 70 + ``` 71 + 72 + ```output 73 + #Stream<[ 74 + enum: %File.Stream{ 75 + line_or_bytes: :line, 76 + modes: [:raw, :read_ahead, :binary], 77 + path: "day5.txt", 78 + raw: true 79 + }, 80 + funs: [#Function<47.58486609/1 in Stream.map/2>, #Function<47.58486609/1 in Stream.map/2>] 81 + ]> 82 + ``` 83 + 84 + ## Task 1 85 + 86 + ```elixir 87 + lines 88 + |> Stream.filter(&(Day5.Line.orientation(&1) != :diagonal)) 89 + |> Stream.flat_map(&Day5.Line.points/1) 90 + |> Enum.frequencies() 91 + |> Enum.count(fn {_k, v} -> v > 1 end) 92 + ``` 93 + 94 + ```output 95 + 5197 96 + ``` 97 + 98 + ## Task 2 99 + 100 + ```elixir 101 + lines 102 + |> Stream.flat_map(&Day5.Line.points/1) 103 + |> Enum.frequencies() 104 + |> Enum.count(fn {_k, v} -> v > 1 end) 105 + ``` 106 + 107 + ```output 108 + 18605 109 + ```
+57
2021/day6.livemd
··· 1 + <!-- vim:ft=markdown --> 2 + 3 + <!-- livebook:{"persist_outputs":true} --> 4 + 5 + # Day 6 6 + 7 + ## Section 8 + 9 + ```elixir 10 + initial = for i <- 0..8, into: %{}, do: {i, 0} 11 + 12 + counts = 13 + File.read!("day6.txt") 14 + |> String.trim() 15 + |> String.split(",") 16 + |> Enum.map(&String.to_integer/1) 17 + |> Enum.frequencies() 18 + |> Map.merge(initial, fn _, a, _ -> a end) 19 + 20 + defmodule Day6 do 21 + def next(%{0 => next} = population) do 22 + 1..8 23 + |> Map.new(&{&1 - 1, population[&1]}) 24 + |> Map.merge(%{6 => next, 8 => next}, fn _, v1, v2 -> v1 + v2 end) 25 + end 26 + end 27 + ``` 28 + 29 + ```output 30 + {:module, Day6, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:next, 1}} 31 + ``` 32 + 33 + ## Task 1 34 + 35 + ```elixir 36 + 1..80 37 + |> Enum.reduce(counts, fn _, acc -> Day6.next(acc) end) 38 + |> Map.values() 39 + |> Enum.sum() 40 + ``` 41 + 42 + ```output 43 + 343441 44 + ``` 45 + 46 + ## Task 2 47 + 48 + ```elixir 49 + 1..256 50 + |> Enum.reduce(counts, fn _, acc -> Day6.next(acc) end) 51 + |> Map.values() 52 + |> Enum.sum() 53 + ``` 54 + 55 + ```output 56 + 1569108373832 57 + ```
+56
2021/day7.livemd
··· 1 + <!-- vim:ft=markdown 2 + --> 3 + 4 + <!-- livebook:{"persist_outputs":true} --> 5 + 6 + # Day 7 7 + 8 + ```elixir 9 + input = 10 + File.read!("day7.txt") 11 + |> String.trim() 12 + |> String.split(",") 13 + |> Enum.map(&String.to_integer/1) 14 + ``` 15 + 16 + ```output 17 + [1101, 1, 29, 67, 1102, 0, 1, 65, 1008, 65, 35, 66, 1005, 66, 28, 1, 67, 65, 20, 4, 0, 1001, 65, 1, 18 + 65, 1106, 0, 8, 99, 35, 67, 101, 99, 105, 32, 110, 39, 101, 115, 116, 32, 112, 97, 115, 32, 117, 19 + 110, 101, 32, 105, ...] 20 + ``` 21 + 22 + ## Task 1 23 + 24 + ```elixir 25 + median = Enum.at(Enum.sort(input), div(length(input), 2)) 26 + 27 + input 28 + |> Enum.map(&abs(&1 - median)) 29 + |> Enum.sum() 30 + ``` 31 + 32 + ```output 33 + 336721 34 + ``` 35 + 36 + ## Task 2 37 + 38 + ```elixir 39 + arith_sum = fn n -> div(n * n + n, 2) end 40 + 41 + max = Enum.max(input) 42 + 43 + mean = Enum.sum(input) / length(input) 44 + 45 + [floor(mean), ceil(mean)] 46 + |> Enum.map(fn n -> 47 + input 48 + |> Enum.map(&arith_sum.(abs(&1 - n))) 49 + |> Enum.sum() 50 + end) 51 + |> Enum.min() 52 + ``` 53 + 54 + ```output 55 + 91638945 56 + ```
+141
2021/day8.livemd
··· 1 + <!-- vim:ft=markdown 2 + --> 3 + 4 + <!-- livebook:{"persist_outputs":true} --> 5 + 6 + # Day 8 7 + 8 + ```elixir 9 + input = 10 + File.stream!("day8.txt") 11 + |> Stream.map(fn line -> 12 + line 13 + |> String.split(" | ") 14 + |> Enum.map(fn part -> 15 + part 16 + |> String.trim() 17 + |> String.split(" ") 18 + |> Enum.map(fn disp -> 19 + # Sort characters in each entry to simplify later work 20 + disp 21 + |> String.to_charlist() 22 + |> Enum.sort() 23 + |> List.to_string() 24 + end) 25 + end) 26 + |> List.to_tuple() 27 + end) 28 + ``` 29 + 30 + ```output 31 + #Stream<[ 32 + enum: %File.Stream{ 33 + line_or_bytes: :line, 34 + modes: [:raw, :read_ahead, :binary], 35 + path: "day8.txt", 36 + raw: true 37 + }, 38 + funs: [#Function<47.58486609/1 in Stream.map/2>] 39 + ]> 40 + ``` 41 + 42 + ## Task 1 43 + 44 + We simply need to count all occurences of the values that have 2, 3, 4, or 7 highlighted 45 + segments. 46 + 47 + ```elixir 48 + input 49 + |> Enum.map(fn {_, output} -> 50 + Enum.count(output, &(byte_size(&1) in [2, 3, 4, 7])) 51 + end) 52 + |> Enum.sum() 53 + ``` 54 + 55 + ```output 56 + 390 57 + ``` 58 + 59 + ## Task 2 60 + 61 + ```elixir 62 + defmodule Day8.Task2 do 63 + defp a --- b, do: MapSet.difference(a, b) 64 + 65 + defp a +++ b, do: MapSet.union(a, b) 66 + 67 + defp a <~> b, do: MapSet.intersection(a, b) 68 + 69 + # 1. 7. 4. 2|3|5. 2|3|5. 2|3|5. 6|9|0. 6|9|0. 6|9|0. 8. 70 + def deduce([cf, acf, bcdf, acdeg, acdfg, abdfg, abdefg, abcdfg, abcefg, abcdefg]) do 71 + eg = abcdefg --- (acf +++ bcdf) 72 + bd = bcdf --- cf 73 + adg = acdeg <~> acdfg <~> abdfg 74 + abfg = abdefg <~> abcdfg <~> abcefg 75 + a = acf --- cf 76 + b = abfg <~> bd 77 + f = abfg <~> cf 78 + g = adg <~> eg 79 + d = adg <~> bd 80 + c = cf --- f 81 + e = eg --- g 82 + 83 + [a, b, c, d, e, f, g] = 84 + [a, b, c, d, e, f, g] 85 + |> Enum.map(&extract/1) 86 + 87 + [ 88 + # 0 89 + [a, b, c, e, f, g], 90 + # 1 91 + [c, f], 92 + # 2 93 + [a, c, d, e, g], 94 + # 3 95 + [a, c, d, f, g], 96 + # 4 97 + [b, c, d, f], 98 + # 5 99 + [a, b, d, f, g], 100 + # 6 101 + [a, b, d, e, f, g], 102 + # 7 103 + [a, c, f], 104 + # 8 105 + [a, b, c, d, e, f, g], 106 + # 9 107 + [a, b, c, d, f, g] 108 + ] 109 + |> Enum.map(&List.to_string(Enum.sort(&1))) 110 + |> Enum.with_index() 111 + |> Map.new() 112 + end 113 + 114 + defp extract(a) do 115 + # Just additional sanity check 116 + [v] = MapSet.to_list(a) 117 + 118 + v 119 + end 120 + 121 + def decode(matches, output) do 122 + output 123 + |> Enum.map(&matches[&1]) 124 + |> Integer.undigits() 125 + end 126 + end 127 + 128 + input 129 + |> Enum.map(fn {input, output} -> 130 + input 131 + |> Enum.sort_by(&byte_size/1) 132 + |> Enum.map(&MapSet.new(String.to_charlist(&1))) 133 + |> Day8.Task2.deduce() 134 + |> Day8.Task2.decode(output) 135 + end) 136 + |> Enum.sum() 137 + ``` 138 + 139 + ```output 140 + 1011785 141 + ```
+114
2021/day9.livemd
··· 1 + <!-- vim:ft=markdown 2 + --> 3 + 4 + <!-- livebook:{"persist_outputs":true} --> 5 + 6 + 7 + # Day 9 8 + 9 + ## Setup 10 + 11 + ```elixir 12 + Mix.install([ 13 + {:nx, github: "elixir-nx/nx", sparse: "nx"}, 14 + {:kino, github: "livebook-dev/kino"} 15 + ]) 16 + ``` 17 + 18 + ```output 19 + :ok 20 + ``` 21 + 22 + ## Input 23 + 24 + ```elixir 25 + input = 26 + File.read!("day9.txt") 27 + |> String.split("\n", trim: true) 28 + |> Enum.map(&String.to_charlist(String.trim(&1))) 29 + |> Nx.tensor(names: [:y, :x]) 30 + |> Nx.subtract(?0) 31 + |> Nx.add(1) 32 + 33 + {width, height} = shape = Nx.shape(input) 34 + ``` 35 + 36 + ```output 37 + {100, 100} 38 + ``` 39 + 40 + ## Task 1 41 + 42 + ```elixir 43 + minima = fn padded, size, axis -> 44 + shifted = Nx.slice_axis(padded, 0, size, axis) 45 + x1 = Nx.less(input, shifted) 46 + 47 + shifted = Nx.slice_axis(padded, 2, size, axis) 48 + x2 = Nx.less(input, shifted) 49 + 50 + Nx.logical_and(x1, x2) 51 + end 52 + 53 + padded = Nx.pad(input, 99, [{0, 0, 0}, {1, 1, 0}]) 54 + 55 + x = minima.(padded, width, :x) 56 + 57 + padded = Nx.pad(input, 99, [{1, 1, 0}, {0, 0, 0}]) 58 + 59 + y = minima.(padded, height, :y) 60 + 61 + minimas = Nx.logical_and(x, y) 62 + 63 + input 64 + |> Nx.multiply(minimas) 65 + |> Nx.sum() 66 + |> Nx.to_number() 67 + ``` 68 + 69 + ```output 70 + 452 71 + ``` 72 + 73 + ## Task 2 74 + 75 + ```elixir 76 + input 77 + |> Nx.equal(10) 78 + |> Nx.logical_not() 79 + |> Nx.select(Nx.iota(shape), 9999) 80 + |> Nx.to_flat_list() 81 + |> Enum.reject(&(&1 == 9999)) 82 + |> Enum.map(fn point -> {div(point, width), rem(point, width)} end) 83 + |> Enum.reduce([], fn {y, x} = point, basins -> 84 + basin_left = Enum.find_index(basins, &({y, x - 1} in &1)) 85 + basin_up = Enum.find_index(basins, &({y - 1, x} in &1)) 86 + 87 + case {basin_left, basin_up} do 88 + {nil, nil} -> 89 + [MapSet.new([point]) | basins] 90 + 91 + {idx, nil} -> 92 + List.update_at(basins, idx, &MapSet.put(&1, point)) 93 + 94 + {nil, idx} -> 95 + List.update_at(basins, idx, &MapSet.put(&1, point)) 96 + 97 + {idx, idx} -> 98 + List.update_at(basins, idx, &MapSet.put(&1, point)) 99 + 100 + {idx1, idx2} -> 101 + {old, basins} = List.pop_at(basins, max(idx1, idx2)) 102 + 103 + List.update_at(basins, min(idx1, idx2), &(&1 |> MapSet.union(old) |> MapSet.put(point))) 104 + end 105 + end) 106 + |> Enum.map(&MapSet.size/1) 107 + |> Enum.sort(:desc) 108 + |> Enum.take(3) 109 + |> Enum.reduce(&*/2) 110 + ``` 111 + 112 + ```output 113 + 1263735 114 + ```
-1985
2021/solutions.livemd
··· 1 - <!-- 2 - vim:ft=markdown --!> 3 - livebook:{"persist_outputs":true} 4 - --> 5 - 6 - <!-- livebook:{"persist_outputs":true} --> 7 - 8 - # Advent of Code 2021 9 - 10 - ## Setup 11 - 12 - ```elixir 13 - Mix.install([ 14 - {:nx, github: "elixir-nx/nx", sparse: "nx"}, 15 - {:kino, github: "livebook-dev/kino"} 16 - ]) 17 - ``` 18 - 19 - ```output 20 - :ok 21 - ``` 22 - 23 - ## Day 1 24 - 25 - ### Load input 26 - 27 - ```elixir 28 - stream = 29 - File.stream!("day1.txt") 30 - |> Stream.map(&String.to_integer(String.trim(&1))) 31 - ``` 32 - 33 - ```output 34 - #Stream<[ 35 - enum: %File.Stream{ 36 - line_or_bytes: :line, 37 - modes: [:raw, :read_ahead, :binary], 38 - path: "day1.txt", 39 - raw: true 40 - }, 41 - funs: [#Function<47.58486609/1 in Stream.map/2>] 42 - ]> 43 - ``` 44 - 45 - ### Task 1 46 - 47 - <!-- livebook:{"break_markdown":true} --> 48 - 49 - Compute count of consecutive increases 50 - 51 - ```elixir 52 - stream 53 - |> Stream.chunk_every(2, 1, :discard) 54 - |> Enum.count(fn [a, b] -> a < b end) 55 - ``` 56 - 57 - ```output 58 - 1688 59 - ``` 60 - 61 - ### Task 2 62 - 63 - <!-- livebook:{"break_markdown":true} --> 64 - 65 - Compute count of consecutive increases of sums of trigrams. 66 - 67 - However we can notice, that if we have list like: 68 - 69 - $$ 70 - [a, b, c, d] 71 - $$ 72 - 73 - Then when we want to compare consecutive trigrams then we compare: 74 - 75 - $$ 76 - a + b + c < b + c + d \\ 77 - a < d 78 - $$ 79 - 80 - So we can traverse each 4 elements and then just compare first and last one 81 - instead of summing and then traversing it again. 82 - 83 - ```elixir 84 - stream 85 - |> Stream.chunk_every(4, 1, :discard) 86 - |> Enum.count(fn [a, _, _, b] -> a < b end) 87 - ``` 88 - 89 - ```output 90 - 1728 91 - ``` 92 - 93 - ## Day 2 94 - 95 - ### Load input 96 - 97 - We do parsing there, as it will help us with the latter tasks. Pattern matching 98 - is the simplest approach there, as input is in form of: 99 - 100 - ``` 101 - forward 10 102 - up 20 103 - down 30 104 - ``` 105 - 106 - We need to `trim/1` input to make sure that the last newline will not interrupt 107 - `String.to_integer/1` calls. 108 - 109 - ```elixir 110 - stream = 111 - File.stream!("day2.txt") 112 - |> Stream.map(fn input -> 113 - case String.trim(input) do 114 - "forward " <> n -> {:forward, String.to_integer(n)} 115 - "up " <> n -> {:up, String.to_integer(n)} 116 - "down " <> n -> {:down, String.to_integer(n)} 117 - end 118 - end) 119 - ``` 120 - 121 - ```output 122 - #Stream<[ 123 - enum: %File.Stream{ 124 - line_or_bytes: :line, 125 - modes: [:raw, :read_ahead, :binary], 126 - path: "day2.txt", 127 - raw: true 128 - }, 129 - funs: [#Function<47.58486609/1 in Stream.map/2>] 130 - ]> 131 - ``` 132 - 133 - ### Task 1 134 - 135 - ```elixir 136 - {h, d} = 137 - stream 138 - |> Enum.reduce({0, 0}, fn 139 - {:forward, n}, {h, d} -> {h + n, d} 140 - {:up, n}, {h, d} -> {h, d - n} 141 - {:down, n}, {h, d} -> {h, d + n} 142 - end) 143 - 144 - h * d 145 - ``` 146 - 147 - ```output 148 - 1499229 149 - ``` 150 - 151 - ### Task 2 152 - 153 - ```elixir 154 - {h, d, _} = 155 - stream 156 - |> Enum.reduce({0, 0, 0}, fn 157 - {:forward, n}, {h, d, a} -> {h + n, d + a * n, a} 158 - {:up, n}, {h, d, a} -> {h, d, a - n} 159 - {:down, n}, {h, d, a} -> {h, d, a + n} 160 - end) 161 - 162 - h * d 163 - ``` 164 - 165 - ```output 166 - 1340836560 167 - ``` 168 - 169 - ## Day 3 170 - 171 - ### Input 172 - 173 - ```elixir 174 - stream = 175 - File.stream!("day3.txt") 176 - |> Enum.map(&String.trim/1) 177 - |> Enum.map(&String.to_charlist/1) 178 - 179 - defmodule Day3 do 180 - def count(list) do 181 - Enum.reduce(list, List.duplicate(0, 12), fn input, acc -> 182 - for {value, counter} <- Enum.zip(input, acc) do 183 - case value do 184 - ?1 -> counter + 1 185 - ?0 -> counter 186 - end 187 - end 188 - end) 189 - end 190 - end 191 - ``` 192 - 193 - ```output 194 - {:module, Day3, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:count, 1}} 195 - ``` 196 - 197 - ### Task 1 198 - 199 - ```elixir 200 - half = div(length(stream), 2) 201 - 202 - {a, b} = 203 - stream 204 - |> Day3.count() 205 - |> Enum.reduce({0, 0}, fn elem, {a, b} -> 206 - if elem > half do 207 - {a * 2 + 1, b * 2} 208 - else 209 - {a * 2, b * 2 + 1} 210 - end 211 - end) 212 - 213 - a * b 214 - ``` 215 - 216 - ```output 217 - 3847100 218 - ``` 219 - 220 - ### Task 2 221 - 222 - ```elixir 223 - defmodule Day3.Task2 do 224 - def reduce(list, cb), do: reduce(list, 0, cb) 225 - 226 - defp reduce([elem], _, _), do: elem 227 - 228 - defp reduce(list, at, cb) do 229 - counts = Day3.count(list) 230 - 231 - half = div(length(list), 2) 232 - count = Enum.at(counts, at) 233 - 234 - bit = 235 - cond do 236 - count == half and cb.(count + 1, half) -> ?1 237 - count != half and cb.(count, half) -> ?1 238 - true -> ?0 239 - end 240 - 241 - reduce(Enum.filter(list, &(Enum.at(&1, at) == bit)), at + 1, cb) 242 - end 243 - end 244 - 245 - co2 = List.to_integer(Day3.Task2.reduce(stream, &</2), 2) 246 - o2 = List.to_integer(Day3.Task2.reduce(stream, &>/2), 2) 247 - 248 - co2 * o2 249 - ``` 250 - 251 - ```output 252 - 4105235 253 - ``` 254 - 255 - ## Day 4 256 - 257 - ### Input 258 - 259 - This time it is a little bit more convoluted, as there are 2 parts of the input. 260 - Fortunately we can easily disect the parts via pattern matching. 261 - 262 - Technically the conversion to the numbers is not needed, but it does no harm 263 - and provides additional layer of safety against some whitespace characters left there 264 - and here. 265 - 266 - The `Day4.win/2` function is manually unrolled, as it is easier to write than some 267 - random jumping in the list. 268 - 269 - <!-- livebook:{"disable_formatting":true} --> 270 - 271 - ```elixir 272 - [numbers | bingos] = 273 - File.read!("day4.txt") 274 - |> String.split("\n\n", trim: true) 275 - 276 - numbers = 277 - numbers 278 - |> String.trim() 279 - |> String.split(",") 280 - |> Enum.map(&String.to_integer/1) 281 - 282 - bingos = 283 - bingos 284 - |> Enum.map(fn bingo -> 285 - bingo 286 - |> String.split(~r/\s+/, trim: true) 287 - |> Enum.map(&String.to_integer/1) 288 - end) 289 - 290 - defmodule Day4 do 291 - def win( 292 - [ 293 - a1, a2, a3, a4, a5, 294 - b1, b2, b3, b4, b5, 295 - c1, c2, c3, c4, c5, 296 - d1, d2, d3, d4, d5, 297 - e1, e2, e3, e4, e5 298 - ], 299 - nums 300 - ) do 301 - # Rows 302 - all_in([a1, a2, a3, a4, a5], nums) or 303 - all_in([b1, b3, b3, b4, b5], nums) or 304 - all_in([c1, c2, c3, c4, c5], nums) or 305 - all_in([d1, d2, d3, d4, d5], nums) or 306 - all_in([e1, e2, e3, e4, e5], nums) or 307 - # Columns 308 - all_in([a1, b1, c1, d1, e1], nums) or 309 - all_in([a2, b2, c2, d2, e2], nums) or 310 - all_in([a3, b3, c3, d3, e3], nums) or 311 - all_in([a4, b4, c4, d4, e4], nums) or 312 - all_in([a5, b5, c5, d5, e5], nums) 313 - end 314 - 315 - def not_matched(bingo, nums) do 316 - Enum.reject(bingo, &(&1 in nums)) 317 - end 318 - 319 - defp all_in(list, nums) do 320 - Enum.all?(list, &(&1 in nums)) 321 - end 322 - end 323 - ``` 324 - 325 - ```output 326 - {:module, Day4, <<70, 79, 82, 49, 0, 0, 15, ...>>, {:all_in, 2}} 327 - ``` 328 - 329 - ### Task 1 330 - 331 - We simply traverse the `numbers` list aggregating the numbers (order doesn't really matter, 332 - here we aggregate them in reverse order to speedup the code). When we have enough numbers 333 - that any of the `bingos` is winning one, then we halt the reduction and return computed 334 - result. 335 - 336 - ```elixir 337 - numbers 338 - |> Enum.reduce_while([], fn elem, acc -> 339 - matches = [elem | acc] 340 - 341 - case Enum.find(bingos, &Day4.win(&1, matches)) do 342 - nil -> {:cont, matches} 343 - bingo -> {:halt, Enum.sum(Day4.not_matched(bingo, matches)) * elem} 344 - end 345 - end) 346 - ``` 347 - 348 - ```output 349 - 34506 350 - ``` 351 - 352 - ### Task 2 353 - 354 - ```elixir 355 - numbers 356 - |> Enum.reduce_while({bingos, []}, fn elem, {bingos, acc} -> 357 - matches = [elem | acc] 358 - 359 - case bingos do 360 - [bingo] -> 361 - if Day4.win(bingo, matches) do 362 - {:halt, Enum.sum(Day4.not_matched(bingo, matches)) * elem} 363 - else 364 - {:cont, {bingos, matches}} 365 - end 366 - 367 - _ -> 368 - {:cont, {Enum.reject(bingos, &Day4.win(&1, matches)), matches}} 369 - end 370 - end) 371 - ``` 372 - 373 - ```output 374 - 7686 375 - ``` 376 - 377 - ## Day 5 378 - 379 - ```elixir 380 - defmodule Day5 do 381 - defmodule Point do 382 - defstruct [:x, :y] 383 - 384 - def parse(input) do 385 - [x, y] = String.split(input, ",") 386 - 387 - %__MODULE__{x: String.to_integer(x), y: String.to_integer(y)} 388 - end 389 - end 390 - 391 - defmodule Line do 392 - defstruct [:start, :finish] 393 - 394 - def new(a, b) do 395 - {start, finish} = 396 - cond do 397 - a.x < b.x -> {a, b} 398 - a.y < b.y -> {a, b} 399 - true -> {b, a} 400 - end 401 - 402 - %__MODULE__{start: start, finish: finish} 403 - end 404 - 405 - def horizontal?(a), do: a.start.y == a.finish.y 406 - def vertical?(a), do: a.start.x == a.finish.x 407 - 408 - def points(a) do 409 - case {sign(a.finish.x - a.start.x), sign(a.finish.y - a.start.y)} do 410 - {0, dy} -> for y <- a.start.y..a.finish.y//dy, do: {a.start.x, y} 411 - {dx, 0} -> for x <- a.start.x..a.finish.x//dx, do: {x, a.start.y} 412 - {dx, dy} -> Enum.zip(a.start.x..a.finish.x//dx, a.start.y..a.finish.y//dy) 413 - end 414 - end 415 - 416 - def orientation(a) do 417 - cond do 418 - horizontal?(a) -> :horizontal 419 - vertical?(a) -> :vertical 420 - true -> :diagonal 421 - end 422 - end 423 - 424 - defp sign(0), do: 0 425 - defp sign(x) when x < 0, do: -1 426 - defp sign(x) when x > 0, do: 1 427 - end 428 - end 429 - 430 - lines = 431 - File.stream!("day5.txt") 432 - |> Stream.map(&String.trim/1) 433 - |> Stream.map(fn input -> 434 - [a, b] = String.split(input, " -> ") 435 - 436 - pa = Day5.Point.parse(a) 437 - pb = Day5.Point.parse(b) 438 - 439 - Day5.Line.new(pa, pb) 440 - end) 441 - ``` 442 - 443 - ```output 444 - #Stream<[ 445 - enum: %File.Stream{ 446 - line_or_bytes: :line, 447 - modes: [:raw, :read_ahead, :binary], 448 - path: "day5.txt", 449 - raw: true 450 - }, 451 - funs: [#Function<47.58486609/1 in Stream.map/2>, #Function<47.58486609/1 in Stream.map/2>] 452 - ]> 453 - ``` 454 - 455 - ### Task 1 456 - 457 - ```elixir 458 - lines 459 - |> Stream.filter(&(Day5.Line.orientation(&1) != :diagonal)) 460 - |> Stream.flat_map(&Day5.Line.points/1) 461 - |> Enum.frequencies() 462 - |> Enum.count(fn {_k, v} -> v > 1 end) 463 - ``` 464 - 465 - ```output 466 - 5197 467 - ``` 468 - 469 - ### Task 2 470 - 471 - ```elixir 472 - lines 473 - |> Stream.flat_map(&Day5.Line.points/1) 474 - |> Enum.frequencies() 475 - |> Enum.count(fn {_k, v} -> v > 1 end) 476 - ``` 477 - 478 - ```output 479 - 18605 480 - ``` 481 - 482 - ## Day 6 483 - 484 - ```elixir 485 - initial = for i <- 0..8, into: %{}, do: {i, 0} 486 - 487 - counts = 488 - File.read!("day6.txt") 489 - |> String.trim() 490 - |> String.split(",") 491 - |> Enum.map(&String.to_integer/1) 492 - |> Enum.frequencies() 493 - |> Map.merge(initial, fn _, a, _ -> a end) 494 - 495 - defmodule Day6 do 496 - def next(%{0 => next} = population) do 497 - 1..8 498 - |> Map.new(&{&1 - 1, population[&1]}) 499 - |> Map.merge(%{6 => next, 8 => next}, fn _, v1, v2 -> v1 + v2 end) 500 - end 501 - end 502 - ``` 503 - 504 - ```output 505 - {:module, Day6, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:next, 1}} 506 - ``` 507 - 508 - ### Task 1 509 - 510 - ```elixir 511 - 1..80 512 - |> Enum.reduce(counts, fn _, acc -> Day6.next(acc) end) 513 - |> Map.values() 514 - |> Enum.sum() 515 - ``` 516 - 517 - ```output 518 - 343441 519 - ``` 520 - 521 - ### Task 2 522 - 523 - ```elixir 524 - 1..256 525 - |> Enum.reduce(counts, fn _, acc -> Day6.next(acc) end) 526 - |> Map.values() 527 - |> Enum.sum() 528 - ``` 529 - 530 - ```output 531 - 1569108373832 532 - ``` 533 - 534 - ## Day 7 535 - 536 - ```elixir 537 - input = 538 - File.read!("day7.txt") 539 - |> String.trim() 540 - |> String.split(",") 541 - |> Enum.map(&String.to_integer/1) 542 - ``` 543 - 544 - ```output 545 - [1101, 1, 29, 67, 1102, 0, 1, 65, 1008, 65, 35, 66, 1005, 66, 28, 1, 67, 65, 20, 4, 0, 1001, 65, 1, 546 - 65, 1106, 0, 8, 99, 35, 67, 101, 99, 105, 32, 110, 39, 101, 115, 116, 32, 112, 97, 115, 32, 117, 547 - 110, 101, 32, 105, ...] 548 - ``` 549 - 550 - ### Task 1 551 - 552 - ```elixir 553 - median = Enum.at(Enum.sort(input), div(length(input), 2)) 554 - 555 - input 556 - |> Enum.map(&abs(&1 - median)) 557 - |> Enum.sum() 558 - ``` 559 - 560 - ```output 561 - 336721 562 - ``` 563 - 564 - ### Task 2 565 - 566 - ```elixir 567 - arith_sum = fn n -> div(n * n + n, 2) end 568 - 569 - max = Enum.max(input) 570 - 571 - mean = Enum.sum(input) / length(input) 572 - 573 - [floor(mean), ceil(mean)] 574 - |> Enum.map(fn n -> 575 - input 576 - |> Enum.map(&arith_sum.(abs(&1 - n))) 577 - |> Enum.sum() 578 - end) 579 - |> Enum.min() 580 - ``` 581 - 582 - ```output 583 - 91638945 584 - ``` 585 - 586 - ## Day 8 587 - 588 - ```elixir 589 - input = 590 - File.stream!("day8.txt") 591 - |> Stream.map(fn line -> 592 - line 593 - |> String.split(" | ") 594 - |> Enum.map(fn part -> 595 - part 596 - |> String.trim() 597 - |> String.split(" ") 598 - |> Enum.map(fn disp -> 599 - # Sort characters in each entry to simplify later work 600 - disp 601 - |> String.to_charlist() 602 - |> Enum.sort() 603 - |> List.to_string() 604 - end) 605 - end) 606 - |> List.to_tuple() 607 - end) 608 - ``` 609 - 610 - ```output 611 - #Stream<[ 612 - enum: %File.Stream{ 613 - line_or_bytes: :line, 614 - modes: [:raw, :read_ahead, :binary], 615 - path: "day8.txt", 616 - raw: true 617 - }, 618 - funs: [#Function<47.58486609/1 in Stream.map/2>] 619 - ]> 620 - ``` 621 - 622 - ### Task 1 623 - 624 - We simply need to count all occurences of the values that have 2, 3, 4, or 7 highlighted 625 - segments. 626 - 627 - ```elixir 628 - input 629 - |> Enum.map(fn {_, output} -> 630 - Enum.count(output, &(byte_size(&1) in [2, 3, 4, 7])) 631 - end) 632 - |> Enum.sum() 633 - ``` 634 - 635 - ```output 636 - 390 637 - ``` 638 - 639 - ### Task 2 640 - 641 - ```elixir 642 - defmodule Day8.Task2 do 643 - defp a --- b, do: MapSet.difference(a, b) 644 - 645 - defp a +++ b, do: MapSet.union(a, b) 646 - 647 - defp a <~> b, do: MapSet.intersection(a, b) 648 - 649 - # 1. 7. 4. 2|3|5. 2|3|5. 2|3|5. 6|9|0. 6|9|0. 6|9|0. 8. 650 - def deduce([cf, acf, bcdf, acdeg, acdfg, abdfg, abdefg, abcdfg, abcefg, abcdefg]) do 651 - eg = abcdefg --- (acf +++ bcdf) 652 - bd = bcdf --- cf 653 - adg = acdeg <~> acdfg <~> abdfg 654 - abfg = abdefg <~> abcdfg <~> abcefg 655 - a = acf --- cf 656 - b = abfg <~> bd 657 - f = abfg <~> cf 658 - g = adg <~> eg 659 - d = adg <~> bd 660 - c = cf --- f 661 - e = eg --- g 662 - 663 - [a, b, c, d, e, f, g] = 664 - [a, b, c, d, e, f, g] 665 - |> Enum.map(&extract/1) 666 - 667 - [ 668 - # 0 669 - [a, b, c, e, f, g], 670 - # 1 671 - [c, f], 672 - # 2 673 - [a, c, d, e, g], 674 - # 3 675 - [a, c, d, f, g], 676 - # 4 677 - [b, c, d, f], 678 - # 5 679 - [a, b, d, f, g], 680 - # 6 681 - [a, b, d, e, f, g], 682 - # 7 683 - [a, c, f], 684 - # 8 685 - [a, b, c, d, e, f, g], 686 - # 9 687 - [a, b, c, d, f, g] 688 - ] 689 - |> Enum.map(&List.to_string(Enum.sort(&1))) 690 - |> Enum.with_index() 691 - |> Map.new() 692 - end 693 - 694 - defp extract(a) do 695 - # Just additional sanity check 696 - [v] = MapSet.to_list(a) 697 - 698 - v 699 - end 700 - 701 - def decode(matches, output) do 702 - output 703 - |> Enum.map(&matches[&1]) 704 - |> Integer.undigits() 705 - end 706 - end 707 - 708 - input 709 - |> Enum.map(fn {input, output} -> 710 - input 711 - |> Enum.sort_by(&byte_size/1) 712 - |> Enum.map(&MapSet.new(String.to_charlist(&1))) 713 - |> Day8.Task2.deduce() 714 - |> Day8.Task2.decode(output) 715 - end) 716 - |> Enum.sum() 717 - ``` 718 - 719 - ```output 720 - 1011785 721 - ``` 722 - 723 - ## Day 9 724 - 725 - ```elixir 726 - input = 727 - File.read!("day9.txt") 728 - |> String.split("\n", trim: true) 729 - |> Enum.map(&String.to_charlist(String.trim(&1))) 730 - |> Nx.tensor(names: [:y, :x]) 731 - |> Nx.subtract(?0) 732 - |> Nx.add(1) 733 - 734 - {width, height} = shape = Nx.shape(input) 735 - ``` 736 - 737 - ```output 738 - {100, 100} 739 - ``` 740 - 741 - ### Task 1 742 - 743 - ```elixir 744 - minima = fn padded, size, axis -> 745 - shifted = Nx.slice_axis(padded, 0, size, axis) 746 - x1 = Nx.less(input, shifted) 747 - 748 - shifted = Nx.slice_axis(padded, 2, size, axis) 749 - x2 = Nx.less(input, shifted) 750 - 751 - Nx.logical_and(x1, x2) 752 - end 753 - 754 - padded = Nx.pad(input, 99, [{0, 0, 0}, {1, 1, 0}]) 755 - 756 - x = minima.(padded, width, :x) 757 - 758 - padded = Nx.pad(input, 99, [{1, 1, 0}, {0, 0, 0}]) 759 - 760 - y = minima.(padded, height, :y) 761 - 762 - minimas = Nx.logical_and(x, y) 763 - 764 - input 765 - |> Nx.multiply(minimas) 766 - |> Nx.sum() 767 - |> Nx.to_number() 768 - ``` 769 - 770 - ```output 771 - 452 772 - ``` 773 - 774 - ### Task 2 775 - 776 - ```elixir 777 - input 778 - |> Nx.equal(10) 779 - |> Nx.logical_not() 780 - |> Nx.select(Nx.iota(shape), 9999) 781 - |> Nx.to_flat_list() 782 - |> Enum.reject(&(&1 == 9999)) 783 - |> Enum.map(fn point -> {div(point, width), rem(point, width)} end) 784 - |> Enum.reduce([], fn {y, x} = point, basins -> 785 - basin_left = Enum.find_index(basins, &({y, x - 1} in &1)) 786 - basin_up = Enum.find_index(basins, &({y - 1, x} in &1)) 787 - 788 - case {basin_left, basin_up} do 789 - {nil, nil} -> 790 - [MapSet.new([point]) | basins] 791 - 792 - {idx, nil} -> 793 - List.update_at(basins, idx, &MapSet.put(&1, point)) 794 - 795 - {nil, idx} -> 796 - List.update_at(basins, idx, &MapSet.put(&1, point)) 797 - 798 - {idx, idx} -> 799 - List.update_at(basins, idx, &MapSet.put(&1, point)) 800 - 801 - {idx1, idx2} -> 802 - {old, basins} = List.pop_at(basins, max(idx1, idx2)) 803 - 804 - List.update_at(basins, min(idx1, idx2), &(&1 |> MapSet.union(old) |> MapSet.put(point))) 805 - end 806 - end) 807 - |> Enum.map(&MapSet.size/1) 808 - |> Enum.sort(:desc) 809 - |> Enum.take(3) 810 - |> Enum.reduce(&*/2) 811 - ``` 812 - 813 - ```output 814 - 1263735 815 - ``` 816 - 817 - ## Day 10 818 - 819 - ```elixir 820 - input = 821 - File.stream!("day10.txt") 822 - |> Stream.map(&String.trim/1) 823 - 824 - defmodule Day10 do 825 - @parens %{?( => ?), ?[ => ?], ?< => ?>, ?{ => ?}} 826 - 827 - def parse(input), do: parse(input, []) 828 - 829 - defp parse(<<c>> <> rest, stack) when c in '([{<', do: parse(rest, [@parens[c] | stack]) 830 - defp parse(<<c>> <> rest, [c | stack]), do: parse(rest, stack) 831 - defp parse(<<>>, []), do: :ok 832 - defp parse(<<>>, rest), do: {:incomplete, rest} 833 - defp parse(<<c>> <> _, _), do: {:unexpected, [c]} 834 - end 835 - ``` 836 - 837 - ```output 838 - {:module, Day10, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:parse, 2}} 839 - ``` 840 - 841 - ### Task 1 842 - 843 - ```elixir 844 - points = %{ 845 - ?) => 3, 846 - ?] => 57, 847 - ?} => 1197, 848 - ?> => 25137 849 - } 850 - 851 - input 852 - |> Enum.map(&Day10.parse/1) 853 - |> Enum.map(fn 854 - {:unexpected, [c]} -> points[c] 855 - _ -> 0 856 - end) 857 - |> Enum.sum() 858 - ``` 859 - 860 - ```output 861 - 288291 862 - ``` 863 - 864 - ### Task 2 865 - 866 - ```elixir 867 - points = %{ 868 - ?) => 1, 869 - ?] => 2, 870 - ?} => 3, 871 - ?> => 4 872 - } 873 - 874 - median = fn list -> 875 - sorted = Enum.sort(list) 876 - middle = div(length(list), 2) 877 - 878 - Enum.at(sorted, middle) 879 - end 880 - 881 - input 882 - |> Enum.map(&Day10.parse/1) 883 - |> Enum.flat_map(fn 884 - {:incomplete, rest} -> 885 - [ 886 - Enum.reduce(rest, 0, fn c, acc -> 887 - acc * 5 + points[c] 888 - end) 889 - ] 890 - 891 - _ -> 892 - [] 893 - end) 894 - |> median.() 895 - ``` 896 - 897 - ```output 898 - 820045242 899 - ``` 900 - 901 - ## Day 11 902 - 903 - ```elixir 904 - input = 905 - File.read!("day11.txt") 906 - |> String.split("\n") 907 - |> Enum.map(&String.trim/1) 908 - |> Enum.map(fn line -> 909 - for <<c <- line>>, do: c - ?0 910 - end) 911 - |> Enum.with_index() 912 - |> Enum.flat_map(fn {row, y} -> 913 - for {v, x} <- Enum.with_index(row), do: {{x, y}, v} 914 - end) 915 - |> Map.new() 916 - 917 - defmodule Day11 do 918 - def step(map) do 919 - updated = Map.new(map, fn {k, v} -> {k, v + 1} end) 920 - 921 - lightup(updated, 0) 922 - end 923 - 924 - @diffs for dx <- -1..1, dy <- -1..1, dx != 0 or dy != 0, do: {dx, dy} 925 - 926 - def lightup(map, n) do 927 - map 928 - |> Enum.reduce({map, 0}, fn 929 - {_, v}, acc when v < 10 -> 930 - acc 931 - 932 - {{x, y} = k, _}, {map, count} -> 933 - new_map = 934 - @diffs 935 - |> Enum.reduce(map, fn {dx, dy}, acc -> 936 - point = {x + dx, y + dy} 937 - 938 - case Map.fetch(acc, point) do 939 - {:ok, value} when value != 0 -> %{acc | point => value + 1} 940 - _ -> acc 941 - end 942 - end) 943 - |> Map.put(k, 0) 944 - 945 - {new_map, count + 1} 946 - end) 947 - |> case do 948 - {map, 0} -> {map, n} 949 - {map, m} -> lightup(map, n + m) 950 - end 951 - end 952 - end 953 - ``` 954 - 955 - ```output 956 - {:module, Day11, <<70, 79, 82, 49, 0, 0, 11, ...>>, {:lightup, 2}} 957 - ``` 958 - 959 - ### Task 1 960 - 961 - ```elixir 962 - draw = fn map -> 963 - for x <- 0..9 do 964 - IO.puts(for y <- 0..9, do: ?0 + map[{x, y}]) 965 - end 966 - 967 - IO.puts("") 968 - end 969 - 970 - 1..100 971 - |> Enum.reduce({input, 0}, fn _, {map, n} -> 972 - {new_map, m} = Day11.step(map) 973 - {new_map, n + m} 974 - end) 975 - |> elem(1) 976 - ``` 977 - 978 - ```output 979 - 1688 980 - ``` 981 - 982 - ### Task 2 983 - 984 - ```elixir 985 - Stream.unfold(1, &{&1, &1 + 1}) 986 - |> Enum.reduce_while(input, fn idx, map -> 987 - case Day11.step(map) do 988 - {_, 100} -> {:halt, idx} 989 - {next, _} -> {:cont, next} 990 - end 991 - end) 992 - ``` 993 - 994 - ```output 995 - 403 996 - ``` 997 - 998 - ## Day 12 999 - 1000 - ```elixir 1001 - input = 1002 - File.read!("day12.txt") 1003 - |> String.split("\n") 1004 - |> Enum.map(&String.split(&1, "-")) 1005 - 1006 - graph = 1007 - Enum.reduce(input, %{}, fn [a, b], acc -> 1008 - acc 1009 - |> Map.update(a, [b], &[b | &1]) 1010 - |> Map.update(b, [a], &[a | &1]) 1011 - end) 1012 - 1013 - defmodule Day12 do 1014 - def dfs(graph, start, finish), do: dfs(graph, start, finish, [start]) 1015 - 1016 - defp dfs(_graph, vertex, vertex, _visited), do: 1 1017 - 1018 - defp dfs(graph, vertex, finish, visited) do 1019 - (graph[vertex] -- visited) 1020 - |> Enum.reduce(0, fn vertex, acc -> 1021 - visited = if small?(vertex), do: [vertex | visited], else: visited 1022 - 1023 - acc + dfs(graph, vertex, finish, visited) 1024 - end) 1025 - end 1026 - 1027 - def dfs2(graph, start, finish), do: dfs2(graph, start, finish, %{start => :inf}) 1028 - 1029 - defp dfs2(_graph, vertex, vertex, _visited), do: 1 1030 - 1031 - defp dfs2(graph, vertex, finish, visited) do 1032 - (graph[vertex] -- keys(visited)) 1033 - |> Enum.reduce(0, fn vertex, acc -> 1034 - visited = if small?(vertex), do: Map.update(visited, vertex, 1, &(&1 + 1)), else: visited 1035 - 1036 - acc + dfs2(graph, vertex, finish, visited) 1037 - end) 1038 - end 1039 - 1040 - defp keys(map) do 1041 - if Enum.any?(map, fn {_, v} -> v == 2 end) do 1042 - # there is already some vertex visited twice 1043 - Map.keys(map) 1044 - else 1045 - for {k, v} <- map, v > 1, do: k 1046 - end 1047 - end 1048 - 1049 - defp small?(<<c>> <> _), do: c in ?a..?z 1050 - end 1051 - ``` 1052 - 1053 - ```output 1054 - {:module, Day12, <<70, 79, 82, 49, 0, 0, 15, ...>>, {:small?, 1}} 1055 - ``` 1056 - 1057 - ### Task 1 1058 - 1059 - ```elixir 1060 - Day12.dfs(graph, "start", "end") 1061 - ``` 1062 - 1063 - ```output 1064 - 4167 1065 - ``` 1066 - 1067 - ### Task 2 1068 - 1069 - ```elixir 1070 - Day12.dfs2(graph, "start", "end") 1071 - ``` 1072 - 1073 - ```output 1074 - 98441 1075 - ``` 1076 - 1077 - ## Day 13 1078 - 1079 - ```elixir 1080 - [input, folds] = 1081 - File.read!("day13.txt") 1082 - |> String.trim() 1083 - |> String.split("\n\n") 1084 - 1085 - input = 1086 - input 1087 - |> String.split("\n") 1088 - |> Enum.map(fn line -> 1089 - [x, y] = String.split(line, ",") 1090 - 1091 - {String.to_integer(x), String.to_integer(y)} 1092 - end) 1093 - |> MapSet.new() 1094 - 1095 - folds = 1096 - folds 1097 - |> String.split("\n") 1098 - |> Enum.map(fn 1099 - "fold along " <> <<c>> <> "=" <> rest -> 1100 - {String.to_atom(<<c>>), String.to_integer(rest)} 1101 - end) 1102 - 1103 - defmodule Day13 do 1104 - def fold({orientation, pos}, set) do 1105 - Enum.reduce(set, MapSet.new(), fn point, acc -> 1106 - new_point = folded_coords(orientation, pos, point) 1107 - 1108 - MapSet.put(acc, new_point) 1109 - end) 1110 - end 1111 - 1112 - defp folded_coords(:x, col, {x, y}) when x > col, do: {abs(2 * col - x), y} 1113 - defp folded_coords(:y, row, {x, y}) when y > row, do: {x, abs(2 * row - y)} 1114 - defp folded_coords(_, _, point), do: point 1115 - 1116 - def draw(set) do 1117 - set 1118 - |> Enum.group_by(&elem(&1, 1)) 1119 - |> Enum.sort() 1120 - |> Enum.map(fn {_, points} -> 1121 - points 1122 - |> Enum.map(&elem(&1, 0)) 1123 - |> Enum.sort() 1124 - |> Enum.chunk_every(2, 1) 1125 - |> Enum.map(fn 1126 - [a, b] -> b - a 1127 - _ -> 0 1128 - end) 1129 - |> Enum.map(&String.pad_trailing("█", &1, " ")) 1130 - end) 1131 - |> Enum.join("\n") 1132 - end 1133 - end 1134 - ``` 1135 - 1136 - ```output 1137 - {:module, Day13, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:draw, 1}} 1138 - ``` 1139 - 1140 - ### Task 1 1141 - 1142 - ```elixir 1143 - Day13.fold(hd(folds), input) |> MapSet.size() 1144 - ``` 1145 - 1146 - ```output 1147 - 802 1148 - ``` 1149 - 1150 - ### Task 2 1151 - 1152 - ```elixir 1153 - Enum.reduce(folds, input, &Day13.fold/2) 1154 - |> Day13.draw() 1155 - |> IO.puts() 1156 - ``` 1157 - 1158 - ```output 1159 - ███ █ █ █ █ ████ ████ ██ █ █ ███ 1160 - █ █ █ █ █ █ █ █ █ █ █ █ █ █ 1161 - █ █ ██ ████ ███ █ █ █ █ ███ 1162 - ███ █ █ █ █ █ █ █ ██ █ █ █ █ 1163 - █ █ █ █ █ █ █ █ █ █ █ █ █ █ 1164 - █ █ █ █ █ █ █ ████ ███ ██ ███ 1165 - ``` 1166 - 1167 - ```output 1168 - :ok 1169 - ``` 1170 - 1171 - ## Day 14 1172 - 1173 - ```elixir 1174 - [polymer_raw, subs] = 1175 - File.read!("day14.txt") 1176 - |> String.split("\n\n") 1177 - 1178 - <<first, _::binary>> = polymer_raw 1179 - 1180 - polymer = 1181 - {first, 1182 - polymer_raw 1183 - |> String.to_charlist() 1184 - |> Enum.chunk_every(2, 1, :discard) 1185 - |> Enum.frequencies()} 1186 - 1187 - subs = 1188 - subs 1189 - |> String.trim() 1190 - |> String.split(["\n", " -> "]) 1191 - |> Enum.chunk_every(2) 1192 - |> Map.new(fn [pair, <<new>>] -> {String.to_charlist(pair), new} end) 1193 - 1194 - defmodule Day14 do 1195 - def expand({hd, polymer}, subs) do 1196 - new = 1197 - polymer 1198 - |> Enum.reduce(%{}, fn {[a, b] = pair, count}, acc -> 1199 - s = Map.fetch!(subs, pair) 1200 - 1201 - acc 1202 - |> Map.update([a, s], count, &(&1 + count)) 1203 - |> Map.update([s, b], count, &(&1 + count)) 1204 - end) 1205 - 1206 - {hd, new} 1207 - end 1208 - 1209 - def expand_naive(polymer, subs) do 1210 - polymer 1211 - |> to_charlist() 1212 - |> Enum.chunk_every(2, 1, :discard) 1213 - |> Enum.flat_map(fn [a, b] = pair -> 1214 - [a, subs[pair], b] 1215 - end) 1216 - |> List.to_string() 1217 - end 1218 - 1219 - def frequencies({hd, polymer}) do 1220 - polymer 1221 - |> Enum.reduce(%{hd => 1}, fn {[_, b], count}, acc -> 1222 - Map.update(acc, b, count, &(&1 + count)) 1223 - end) 1224 - end 1225 - end 1226 - ``` 1227 - 1228 - ```output 1229 - {:module, Day14, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:frequencies, 1}} 1230 - ``` 1231 - 1232 - ### Task 1 1233 - 1234 - ```elixir 1235 - {{_, min}, {_, max}} = 1236 - 1..10 1237 - |> Enum.reduce(polymer, fn _, acc -> 1238 - Day14.expand(acc, subs) 1239 - end) 1240 - |> Day14.frequencies() 1241 - |> Enum.min_max_by(&elem(&1, 1)) 1242 - 1243 - # 2768 1244 - max - min 1245 - ``` 1246 - 1247 - ```output 1248 - 2768 1249 - ``` 1250 - 1251 - ### Task 2 1252 - 1253 - ```elixir 1254 - {{_, min}, {_, max}} = 1255 - 1..40 1256 - |> Enum.reduce(polymer, fn _, acc -> 1257 - Day14.expand(acc, subs) 1258 - end) 1259 - |> Day14.frequencies() 1260 - |> Enum.min_max_by(&elem(&1, 1)) 1261 - 1262 - max - min 1263 - ``` 1264 - 1265 - ```output 1266 - 2914365137499 1267 - ``` 1268 - 1269 - ## Day 15 1270 - 1271 - ```elixir 1272 - input = 1273 - File.read!("day15.txt") 1274 - |> String.trim() 1275 - |> String.split("\n") 1276 - |> Enum.map(&String.to_charlist/1) 1277 - |> Enum.with_index() 1278 - |> Enum.flat_map(fn {row, y} -> 1279 - row 1280 - |> Enum.with_index() 1281 - |> Enum.map(fn {v, x} -> {{x, y}, v - ?0} end) 1282 - end) 1283 - |> Map.new() 1284 - 1285 - {width, height} = Enum.max(Map.keys(input)) 1286 - ``` 1287 - 1288 - ```output 1289 - {99, 99} 1290 - ``` 1291 - 1292 - ### Task 1 1293 - 1294 - ```elixir 1295 - shortest_paths = 1296 - for y <- height..0//-1, 1297 - x <- width..0//-1, 1298 - reduce: %{} do 1299 - acc -> 1300 - right = acc[{x + 1, y}] 1301 - bottom = acc[{x, y + 1}] 1302 - 1303 - value = 1304 - case {right, bottom} do 1305 - {nil, nil} -> input[{x, y}] 1306 - _ -> input[{x, y}] + min(right, bottom) 1307 - end 1308 - 1309 - Map.put(acc, {x, y}, value) 1310 - end 1311 - 1312 - shortest_paths[{0, 0}] - input[{0, 0}] 1313 - ``` 1314 - 1315 - ```output 1316 - 429 1317 - ``` 1318 - 1319 - ### Task 2 1320 - 1321 - ```elixir 1322 - defmodule Day15.Task2 do 1323 - def expand_grid(board) do 1324 - {width, height} = Enum.max(Map.keys(board)) 1325 - 1326 - board 1327 - |> Enum.flat_map(fn {{x, y}, v} -> 1328 - for rx <- 0..4, ry <- 0..4 do 1329 - {{x + (width + 1) * rx, y + (height + 1) * ry}, rem(v - 1 + rx + ry, 9) + 1} 1330 - end 1331 - end) 1332 - |> Map.new() 1333 - end 1334 - 1335 - def find_path(board, start, finish) do 1336 - dists = :gb_sets.singleton({0, start}) 1337 - 1338 - find_path(board, finish, dists, MapSet.new()) 1339 - end 1340 - 1341 - @surround for dx <- -1..1, dy <- -1..1, abs(dx) != abs(dy), do: {dx, dy} 1342 - 1343 - def find_path(board, finish, dists, visited) do 1344 - {{dist, {x, y} = curr}, dists} = :gb_sets.take_smallest(dists) 1345 - 1346 - if curr == finish do 1347 - dist 1348 - else 1349 - visited = MapSet.put(visited, curr) 1350 - 1351 - dists = 1352 - for {dx, dy} <- @surround, 1353 - next = {x + dx, y + dy}, 1354 - next not in visited, 1355 - is_map_key(board, next), 1356 - alt = dist + board[next], 1357 - reduce: dists do 1358 - acc -> 1359 - :gb_sets.add_element({alt, next}, acc) 1360 - end 1361 - 1362 - find_path(board, finish, dists, visited) 1363 - end 1364 - end 1365 - end 1366 - ``` 1367 - 1368 - ```output 1369 - {:module, Day15.Task2, <<70, 79, 82, 49, 0, 0, 16, ...>>, {:find_path, 4}} 1370 - ``` 1371 - 1372 - ```elixir 1373 - input 1374 - |> Day15.Task2.expand_grid() 1375 - |> Day15.Task2.find_path({0, 0}, {499, 499}) 1376 - ``` 1377 - 1378 - ```output 1379 - 2844 1380 - ``` 1381 - 1382 - ## Day 16 1383 - 1384 - ```elixir 1385 - defmodule Day16 do 1386 - defmodule Packet do 1387 - defstruct [:version, :type, :value] 1388 - end 1389 - 1390 - def decode(<<version::3, 4::3, rest::bitstring>>) do 1391 - {value, rest} = literal(rest, 0) 1392 - 1393 - {%Packet{type: 4, version: version, value: value}, rest} 1394 - end 1395 - 1396 - def decode(<<version::3, type::3, 0::1, length::15, rest::bitstring>>) do 1397 - <<subpackets::bitstring-size(length), rest::bitstring>> = rest 1398 - 1399 - {%Packet{type: type, version: version, value: decode_all(subpackets)}, rest} 1400 - end 1401 - 1402 - def decode(<<version::3, type::3, 1::1, length::11, rest::bitstring>>) do 1403 - {value, rest} = Enum.map_reduce(1..length, rest, fn _, acc -> decode(acc) end) 1404 - 1405 - {%Packet{type: type, version: version, value: value}, rest} 1406 - end 1407 - 1408 - def decode_all(input) do 1409 - case decode(input) do 1410 - {packet, <<>>} -> [packet] 1411 - {packet, rest} -> [packet | decode_all(rest)] 1412 - end 1413 - end 1414 - 1415 - defp literal(<<1::1, bits::4, rest::bitstring>>, acc) do 1416 - literal(rest, acc * 0x10 + bits) 1417 - end 1418 - 1419 - defp literal(<<0::1, bits::4, rest::bitstring>>, acc) do 1420 - {acc * 0x10 + bits, rest} 1421 - end 1422 - end 1423 - 1424 - input = 1425 - File.read!("day16.txt") 1426 - |> String.trim() 1427 - |> Base.decode16!() 1428 - |> Day16.decode() 1429 - |> elem(0) 1430 - ``` 1431 - 1432 - ```output 1433 - %Day16.Packet{ 1434 - type: 0, 1435 - value: [ 1436 - %Day16.Packet{ 1437 - type: 1, 1438 - value: [ 1439 - %Day16.Packet{type: 4, value: 20, version: 6}, 1440 - %Day16.Packet{ 1441 - type: 6, 1442 - value: [ 1443 - %Day16.Packet{type: 4, value: 14747, version: 1}, 1444 - %Day16.Packet{type: 4, value: 14747, version: 6} 1445 - ], 1446 - version: 2 1447 - } 1448 - ], 1449 - version: 1 1450 - }, 1451 - %Day16.Packet{ 1452 - type: 3, 1453 - value: [ 1454 - %Day16.Packet{type: 4, value: 15, version: 5}, 1455 - %Day16.Packet{type: 4, value: 10, version: 6} 1456 - ], 1457 - version: 7 1458 - }, 1459 - %Day16.Packet{ 1460 - type: 1, 1461 - value: [ 1462 - %Day16.Packet{ 1463 - type: 7, 1464 - value: [ 1465 - %Day16.Packet{type: 4, value: 2184, version: 1}, 1466 - %Day16.Packet{type: 4, value: 130250, version: 6} 1467 - ], 1468 - version: 6 1469 - }, 1470 - %Day16.Packet{type: 4, value: 5442981, version: 4} 1471 - ], 1472 - version: 6 1473 - }, 1474 - %Day16.Packet{type: 4, value: 8281083, version: 0}, 1475 - %Day16.Packet{ 1476 - type: 2, 1477 - value: [ 1478 - %Day16.Packet{type: 4, value: 102, version: 5}, 1479 - %Day16.Packet{type: 4, value: 647125, version: 7} 1480 - ], 1481 - version: 1 1482 - }, 1483 - %Day16.Packet{ 1484 - type: 1, 1485 - value: [ 1486 - %Day16.Packet{type: 4, value: 178, version: 1}, 1487 - %Day16.Packet{type: 4, value: 176, version: 6} 1488 - ], 1489 - version: 0 1490 - }, 1491 - %Day16.Packet{ 1492 - type: 1, 1493 - value: [ 1494 - %Day16.Packet{ 1495 - type: 6, 1496 - value: [ 1497 - %Day16.Packet{ 1498 - type: 0, 1499 - value: [ 1500 - %Day16.Packet{type: 4, value: 13, version: 1}, 1501 - %Day16.Packet{type: 4, value: 8, version: 4}, 1502 - %Day16.Packet{type: 4, value: 4, version: 3} 1503 - ], 1504 - version: 2 1505 - }, 1506 - %Day16.Packet{ 1507 - type: 0, 1508 - value: [ 1509 - %Day16.Packet{type: 4, value: 7, version: 7}, 1510 - %Day16.Packet{type: 4, value: 11, version: 3}, 1511 - %Day16.Packet{type: 4, value: 14, version: 2} 1512 - ], 1513 - version: 4 1514 - } 1515 - ], 1516 - version: 7 1517 - }, 1518 - %Day16.Packet{type: 4, value: 2724, version: 0} 1519 - ], 1520 - version: 1 1521 - }, 1522 - %Day16.Packet{type: 4, value: 9, version: 4}, 1523 - %Day16.Packet{ 1524 - type: 1, 1525 - value: [ 1526 - %Day16.Packet{ 1527 - type: 5, 1528 - value: [ 1529 - %Day16.Packet{type: 4, value: 7240238, version: 2}, 1530 - %Day16.Packet{type: 4, value: 233, version: 7} 1531 - ], 1532 - version: 1 1533 - }, 1534 - %Day16.Packet{type: 4, value: 37, version: 6} 1535 - ], 1536 - version: 4 1537 - }, 1538 - %Day16.Packet{type: 2, value: [%Day16.Packet{type: 4, value: 2, version: 5}], version: 5}, 1539 - %Day16.Packet{type: 4, value: 53749, version: 4}, 1540 - %Day16.Packet{type: 4, value: 11, version: 3}, 1541 - %Day16.Packet{ 1542 - type: 1, 1543 - value: [ 1544 - %Day16.Packet{type: 4, value: 382979, version: 4}, 1545 - %Day16.Packet{ 1546 - type: 5, 1547 - value: [ 1548 - %Day16.Packet{ 1549 - type: 0, 1550 - value: [ 1551 - %Day16.Packet{type: 4, value: 15, version: 1}, 1552 - %Day16.Packet{type: 4, value: 10, version: 0}, 1553 - %Day16.Packet{type: 4, value: 2, version: 6} 1554 - ], 1555 - version: 5 1556 - }, 1557 - %Day16.Packet{ 1558 - type: 0, 1559 - value: [ 1560 - %Day16.Packet{type: 4, value: 4, version: 7}, 1561 - %Day16.Packet{type: 4, value: 7, version: 4}, 1562 - %Day16.Packet{type: 4, value: 2, version: 5} 1563 - ], 1564 - version: 1 1565 - } 1566 - ], 1567 - version: 6 1568 - } 1569 - ], 1570 - version: 2 1571 - }, 1572 - %Day16.Packet{type: 4, value: 21251, version: 1}, 1573 - %Day16.Packet{ 1574 - type: 1, 1575 - value: [ 1576 - %Day16.Packet{type: 4, value: 163, version: 6}, 1577 - %Day16.Packet{ 1578 - type: 5, 1579 - value: [ 1580 - %Day16.Packet{type: 4, value: 59, version: 3}, 1581 - %Day16.Packet{type: 4, value: 836848134220, version: 1} 1582 - ], 1583 - version: 6 1584 - } 1585 - ], 1586 - version: 2 1587 - }, 1588 - %Day16.Packet{ 1589 - type: 2, 1590 - value: [ 1591 - %Day16.Packet{ 1592 - type: 0, 1593 - value: [ 1594 - %Day16.Packet{ 1595 - type: 0, 1596 - value: [ 1597 - %Day16.Packet{ 1598 - type: 2, 1599 - value: [ 1600 - %Day16.Packet{ 1601 - type: 2, 1602 - value: [ 1603 - %Day16.Packet{ 1604 - type: 0, 1605 - value: [ 1606 - %Day16.Packet{ 1607 - type: 3, 1608 - value: [ 1609 - %Day16.Packet{ 1610 - type: 2, 1611 - value: [ 1612 - %Day16.Packet{ 1613 - type: 2, 1614 - value: [ 1615 - %Day16.Packet{ 1616 - type: 3, 1617 - value: [%Day16.Packet{type: 0, value: [...], ...}], 1618 - version: 0 1619 - } 1620 - ], 1621 - version: 1 1622 - } 1623 - ], 1624 - version: 1 1625 - } 1626 - ], 1627 - version: 7 1628 - } 1629 - ], 1630 - version: 0 1631 - } 1632 - ], 1633 - version: 6 1634 - } 1635 - ], 1636 - version: 2 1637 - } 1638 - ], 1639 - version: 2 1640 - } 1641 - ], 1642 - version: 6 1643 - } 1644 - ], 1645 - version: 7 1646 - }, 1647 - %Day16.Packet{type: 1, value: [%Day16.Packet{type: 4, value: 44, version: 4}], version: 7}, 1648 - %Day16.Packet{ 1649 - type: 1, 1650 - value: [ 1651 - %Day16.Packet{type: 4, value: 255, version: 2}, 1652 - %Day16.Packet{type: 4, value: 91, version: 5}, 1653 - %Day16.Packet{type: 4, value: 176, version: 5}, 1654 - %Day16.Packet{type: 4, value: 23, version: 1} 1655 - ], 1656 - version: 7 1657 - }, 1658 - %Day16.Packet{ 1659 - type: 3, 1660 - value: [ 1661 - %Day16.Packet{type: 4, value: 11520, version: 4}, 1662 - %Day16.Packet{type: 4, value: 6069, version: 0}, 1663 - %Day16.Packet{type: 4, value: 1089149511401, version: 4}, 1664 - %Day16.Packet{type: 4, value: 158, version: 2}, 1665 - %Day16.Packet{type: 4, value: 620605, version: 0} 1666 - ], 1667 - version: 2 1668 - }, 1669 - %Day16.Packet{ 1670 - type: 0, 1671 - value: [ 1672 - %Day16.Packet{type: 4, value: 62788, version: 7}, 1673 - %Day16.Packet{type: 4, value: 9410622, version: 2}, 1674 - %Day16.Packet{type: 4, value: 15912821, version: 4} 1675 - ], 1676 - version: 4 1677 - }, 1678 - %Day16.Packet{ 1679 - type: 1, 1680 - value: [ 1681 - %Day16.Packet{type: 4, value: 22416, version: 5}, 1682 - %Day16.Packet{ 1683 - type: 5, 1684 - value: [ 1685 - %Day16.Packet{type: 4, value: 246, version: 1}, 1686 - %Day16.Packet{type: 4, value: 246, version: 4} 1687 - ], 1688 - version: 2 1689 - } 1690 - ], 1691 - version: 0 1692 - }, 1693 - %Day16.Packet{type: 3, value: [%Day16.Packet{type: 4, value: 13008601, version: 5}], version: 0}, 1694 - %Day16.Packet{ 1695 - type: 0, 1696 - value: [ 1697 - %Day16.Packet{ 1698 - type: 1, 1699 - value: [ 1700 - %Day16.Packet{type: 4, value: 3, version: 4}, 1701 - %Day16.Packet{type: 4, value: 14, version: 1}, 1702 - %Day16.Packet{type: 4, value: 5, version: 0} 1703 - ], 1704 - version: 5 1705 - }, 1706 - %Day16.Packet{ 1707 - type: 1, 1708 - value: [ 1709 - %Day16.Packet{type: 4, value: 2, version: 1}, 1710 - %Day16.Packet{type: 4, value: 14, version: 1}, 1711 - %Day16.Packet{type: 4, value: 10, version: 1} 1712 - ], 1713 - version: 6 1714 - }, 1715 - %Day16.Packet{ 1716 - type: 1, 1717 - value: [ 1718 - %Day16.Packet{type: 4, value: 8, version: 3}, 1719 - %Day16.Packet{type: 4, value: 6, version: 6}, 1720 - %Day16.Packet{type: 4, value: 11, version: 0} 1721 - ], 1722 - version: 1 1723 - } 1724 - ], 1725 - version: 5 1726 - }, 1727 - %Day16.Packet{ 1728 - type: 1, 1729 - value: [ 1730 - %Day16.Packet{type: 4, value: 32940592237, version: 2}, 1731 - %Day16.Packet{ 1732 - type: 5, 1733 - value: [ 1734 - %Day16.Packet{type: 4, value: 100, version: 1}, 1735 - %Day16.Packet{type: 4, value: 1393232728, version: 2} 1736 - ], 1737 - version: 2 1738 - } 1739 - ], 1740 - version: 0 1741 - }, 1742 - %Day16.Packet{type: 4, value: 89, version: 3}, 1743 - %Day16.Packet{ 1744 - type: 2, 1745 - value: [ 1746 - %Day16.Packet{type: 4, value: 204, version: 6}, 1747 - %Day16.Packet{type: 4, value: 260321821, version: 2}, 1748 - %Day16.Packet{type: 4, value: 225241983, version: 6} 1749 - ], 1750 - version: 0 1751 - }, 1752 - %Day16.Packet{ 1753 - type: 0, 1754 - value: [ 1755 - %Day16.Packet{type: 4, value: 960899, version: 3}, 1756 - %Day16.Packet{type: 4, value: 58997, version: 5}, 1757 - %Day16.Packet{type: 4, value: 54940, version: 6}, 1758 - %Day16.Packet{type: 4, value: 10974, version: 2}, 1759 - %Day16.Packet{type: 4, value: 882043, version: 2} 1760 - ], 1761 - version: 0 1762 - }, 1763 - %Day16.Packet{ 1764 - type: 1, 1765 - value: [ 1766 - %Day16.Packet{ 1767 - type: 6, 1768 - value: [ 1769 - %Day16.Packet{type: 4, value: 35633017255, version: 4}, 1770 - %Day16.Packet{type: 4, value: 35633017255, version: 2} 1771 - ], 1772 - version: 3 1773 - }, 1774 - %Day16.Packet{type: 4, value: 1359, version: 6} 1775 - ], 1776 - version: 6 1777 - }, 1778 - %Day16.Packet{ 1779 - type: 1, 1780 - value: [ 1781 - %Day16.Packet{type: 4, value: 92, version: 4}, 1782 - %Day16.Packet{type: 4, value: 38, version: 3}, 1783 - %Day16.Packet{type: 4, value: 160, version: 5}, 1784 - %Day16.Packet{type: 4, value: 111, version: 1}, 1785 - %Day16.Packet{type: 4, value: 64, version: 4} 1786 - ], 1787 - version: 4 1788 - }, 1789 - %Day16.Packet{ 1790 - type: 0, 1791 - value: [ 1792 - %Day16.Packet{type: 4, value: 2541, version: 3}, 1793 - %Day16.Packet{type: 4, value: 263947, version: 6}, 1794 - %Day16.Packet{type: 4, value: 7686705, version: 5}, 1795 - %Day16.Packet{type: 4, value: 31, version: 4} 1796 - ], 1797 - version: 2 1798 - }, 1799 - %Day16.Packet{ 1800 - type: 1, 1801 - value: [ 1802 - %Day16.Packet{ 1803 - type: 6, 1804 - value: [ 1805 - %Day16.Packet{type: 4, value: 3193865, version: 1}, 1806 - %Day16.Packet{type: 4, value: 20223, version: 7} 1807 - ], 1808 - version: 2 1809 - }, 1810 - %Day16.Packet{type: 4, value: 9328522, version: 5} 1811 - ], 1812 - version: 0 1813 - }, 1814 - %Day16.Packet{ 1815 - type: 2, 1816 - value: [ 1817 - %Day16.Packet{type: 4, value: 5, version: 4}, 1818 - %Day16.Packet{type: 4, value: 7, version: 3}, 1819 - %Day16.Packet{type: 4, value: 179420284, version: 4}, 1820 - %Day16.Packet{type: 4, value: 19890, version: 1}, 1821 - %Day16.Packet{type: 4, value: 2655, version: 0} 1822 - ], 1823 - version: 7 1824 - }, 1825 - %Day16.Packet{ 1826 - type: 1, 1827 - value: [ 1828 - %Day16.Packet{type: 4, value: 862089, version: 1}, 1829 - %Day16.Packet{ 1830 - type: 6, 1831 - value: [ 1832 - %Day16.Packet{type: 4, value: 248, version: 3}, 1833 - %Day16.Packet{type: 4, value: 3286, version: 5} 1834 - ], 1835 - version: 3 1836 - } 1837 - ], 1838 - version: 3 1839 - }, 1840 - %Day16.Packet{ 1841 - type: 1, 1842 - value: [ 1843 - %Day16.Packet{type: 4, value: 93, version: 6}, 1844 - %Day16.Packet{ 1845 - type: 5, 1846 - value: [ 1847 - %Day16.Packet{type: 4, value: 4269, version: 6}, 1848 - %Day16.Packet{type: 4, value: 240, version: 3} 1849 - ], 1850 - version: 4 1851 - } 1852 - ], 1853 - version: 5 1854 - }, 1855 - %Day16.Packet{ 1856 - type: 3, 1857 - value: [ 1858 - %Day16.Packet{type: 4, value: 2938, version: 6}, 1859 - %Day16.Packet{type: 4, value: 3, version: 6}, 1860 - %Day16.Packet{type: 4, value: 211, version: 7} 1861 - ], 1862 - version: 3 1863 - }, 1864 - %Day16.Packet{ 1865 - type: 1, 1866 - value: [ 1867 - %Day16.Packet{ 1868 - type: 7, 1869 - value: [ 1870 - %Day16.Packet{type: 4, value: 159, version: 0}, 1871 - %Day16.Packet{type: 4, value: 159, version: 5} 1872 - ], 1873 - version: 0 1874 - }, 1875 - %Day16.Packet{type: 4, value: 28, version: 1} 1876 - ], 1877 - version: 4 1878 - }, 1879 - %Day16.Packet{type: 4, value: 84, version: 4}, 1880 - %Day16.Packet{ 1881 - type: 1, 1882 - value: [ 1883 - %Day16.Packet{type: 4, value: 235, version: 4}, 1884 - %Day16.Packet{ 1885 - type: 6, 1886 - value: [ 1887 - %Day16.Packet{type: 0, value: [%Day16.Packet{...}, ...], version: 4}, 1888 - %Day16.Packet{type: 0, value: [...], ...} 1889 - ], 1890 - version: 3 1891 - } 1892 - ], 1893 - version: 6 1894 - }, 1895 - %Day16.Packet{type: 4, value: 1425, version: 4}, 1896 - %Day16.Packet{ 1897 - type: 1, 1898 - value: [ 1899 - %Day16.Packet{ 1900 - type: 7, 1901 - value: [%Day16.Packet{type: 0, value: [...], ...}, %Day16.Packet{type: 0, ...}], 1902 - version: 5 1903 - }, 1904 - %Day16.Packet{type: 4, value: 13, version: 2} 1905 - ], 1906 - version: 2 1907 - }, 1908 - %Day16.Packet{type: 0, value: [%Day16.Packet{type: 4, value: 3121, version: 6}], version: 5}, 1909 - %Day16.Packet{ 1910 - type: 1, 1911 - value: [ 1912 - %Day16.Packet{type: 4, value: 51, version: 2}, 1913 - %Day16.Packet{type: 4, value: 61, ...}, 1914 - %Day16.Packet{type: 4, ...} 1915 - ], 1916 - version: 4 1917 - }, 1918 - %Day16.Packet{ 1919 - type: 1, 1920 - value: [%Day16.Packet{type: 4, value: 1393, ...}, %Day16.Packet{type: 5, ...}], 1921 - version: 3 1922 - }, 1923 - %Day16.Packet{type: 1, value: [%Day16.Packet{type: 7, ...}, %Day16.Packet{...}], version: 3}, 1924 - %Day16.Packet{type: 1, value: [%Day16.Packet{...}, ...], version: 7}, 1925 - %Day16.Packet{type: 3, value: [...], ...}, 1926 - %Day16.Packet{type: 2, ...}, 1927 - %Day16.Packet{...}, 1928 - ... 1929 - ], 1930 - version: 3 1931 - } 1932 - ``` 1933 - 1934 - ### Task 1 1935 - 1936 - ```elixir 1937 - defmodule Day16.Task1 do 1938 - alias Day16.Packet 1939 - 1940 - def sum(%Packet{type: 4, version: version}), do: version 1941 - 1942 - def sum(%Packet{version: version, value: value}) do 1943 - Enum.reduce(value, version, &(sum(&1) + &2)) 1944 - end 1945 - end 1946 - 1947 - Day16.Task1.sum(input) 1948 - ``` 1949 - 1950 - ```output 1951 - 949 1952 - ``` 1953 - 1954 - ### Task 2 1955 - 1956 - ```elixir 1957 - defmodule Day16.Task2 do 1958 - alias Day16.Packet 1959 - 1960 - def evaluate(%Packet{type: 0} = packet), do: reduce(packet, 0, &+/2) 1961 - def evaluate(%Packet{type: 1} = packet), do: reduce(packet, 1, &*/2) 1962 - def evaluate(%Packet{type: 2} = packet), do: reduce(packet, :inf, &min/2) 1963 - def evaluate(%Packet{type: 3} = packet), do: reduce(packet, 0, &max/2) 1964 - 1965 - def evaluate(%Packet{type: 4, value: value}), do: value 1966 - 1967 - def evaluate(%Packet{type: 5} = packet), do: compare(packet, &>/2) 1968 - def evaluate(%Packet{type: 6} = packet), do: compare(packet, &</2) 1969 - def evaluate(%Packet{type: 7} = packet), do: compare(packet, &==/2) 1970 - 1971 - defp reduce(%Packet{value: value}, initial, op) do 1972 - Enum.reduce(value, initial, &op.(evaluate(&1), &2)) 1973 - end 1974 - 1975 - defp compare(%Packet{value: [a, b]}, op) do 1976 - if op.(evaluate(a), evaluate(b)), do: 1, else: 0 1977 - end 1978 - end 1979 - 1980 - Day16.Task2.evaluate(input) 1981 - ``` 1982 - 1983 - ```output 1984 - 1114600142730 1985 - ```