this repo has no description
1<!-- vim:set ft=markdown: -->
2
3<!-- livebook:{"persist_outputs":true} -->
4
5
6# Day 9
7
8## Setup
9
10```elixir
11Mix.install([
12 {:nx, github: "elixir-nx/nx", sparse: "nx"},
13 {:kino, github: "livebook-dev/kino"}
14])
15```
16
17```output
18:ok
19```
20
21## Input
22
23```elixir
24input =
25 File.read!("day9.txt")
26 |> String.split("\n", trim: true)
27 |> Enum.map(&String.to_charlist(String.trim(&1)))
28 |> Nx.tensor(names: [:y, :x])
29 |> Nx.subtract(?0)
30 |> Nx.add(1)
31
32{width, height} = shape = Nx.shape(input)
33```
34
35```output
36{100, 100}
37```
38
39## Task 1
40
41```elixir
42minima = fn padded, size, axis ->
43 shifted = Nx.slice_axis(padded, 0, size, axis)
44 x1 = Nx.less(input, shifted)
45
46 shifted = Nx.slice_axis(padded, 2, size, axis)
47 x2 = Nx.less(input, shifted)
48
49 Nx.logical_and(x1, x2)
50end
51
52padded = Nx.pad(input, 99, [{0, 0, 0}, {1, 1, 0}])
53
54x = minima.(padded, width, :x)
55
56padded = Nx.pad(input, 99, [{1, 1, 0}, {0, 0, 0}])
57
58y = minima.(padded, height, :y)
59
60minimas = Nx.logical_and(x, y)
61
62input
63|> Nx.multiply(minimas)
64|> Nx.sum()
65|> Nx.to_number()
66```
67
68```output
69452
70```
71
72## Task 2
73
74```elixir
75input
76|> Nx.equal(10)
77|> Nx.logical_not()
78|> Nx.select(Nx.iota(shape), 9999)
79|> Nx.to_flat_list()
80|> Enum.reject(&(&1 == 9999))
81|> Enum.map(fn point -> {div(point, width), rem(point, width)} end)
82|> Enum.reduce([], fn {y, x} = point, basins ->
83 basin_left = Enum.find_index(basins, &({y, x - 1} in &1))
84 basin_up = Enum.find_index(basins, &({y - 1, x} in &1))
85
86 case {basin_left, basin_up} do
87 {nil, nil} ->
88 [MapSet.new([point]) | basins]
89
90 {idx, nil} ->
91 List.update_at(basins, idx, &MapSet.put(&1, point))
92
93 {nil, idx} ->
94 List.update_at(basins, idx, &MapSet.put(&1, point))
95
96 {idx, idx} ->
97 List.update_at(basins, idx, &MapSet.put(&1, point))
98
99 {idx1, idx2} ->
100 {old, basins} = List.pop_at(basins, max(idx1, idx2))
101
102 List.update_at(basins, min(idx1, idx2), &(&1 |> MapSet.union(old) |> MapSet.put(point)))
103 end
104end)
105|> Enum.map(&MapSet.size/1)
106|> Enum.sort(:desc)
107|> Enum.take(3)
108|> Enum.reduce(&*/2)
109```
110
111```output
1121263735
113```