Advent of Code 2021 - Day 9
Setup
Mix.install([
{:kino, "~> 0.4.1"}
])
:ok
example_input = Kino.Input.textarea("Please enter the example input:")
my_input = Kino.Input.textarea("Please enter your input:")
defmodule Parser do
def parse_input(input) do
input
|> String.split("\n", trim: true)
|> Enum.map(&String.to_charlist/1)
|> Enum.map(&Enum.map(&1, fn ch -> ch - ?0 end))
end
end
example_input =
example_input
|> Kino.Input.read()
|> Parser.parse_input()
my_input =
my_input
|> Kino.Input.read()
|> Parser.parse_input()
:ok
:ok
Part 1
defmodule Day9.Part1 do
def solve(input) do
input
|> low_points()
|> Enum.map(&height(input, &1))
|> Enum.map(&(&1 + 1))
|> Enum.sum()
end
def low_points(input) do
Enum.reduce(0..(Enum.count(input) - 1), [], fn x, low_points ->
row = Enum.at(input, x)
Enum.reduce(0..(Enum.count(row) - 1), low_points, fn y, low_points ->
height = height(input, {x, y})
min_neighbor_height =
neighbors({x, y}, Enum.count(input), Enum.count(row))
|> Enum.map(fn position -> height(input, position) end)
|> Enum.min()
if height < min_neighbor_height do
[{x, y} | low_points]
else
low_points
end
end)
end)
end
def height(input, {x, y}) do
input |> Enum.at(x) |> Enum.at(y)
end
def neighbors({x, y}, max_x, max_y) do
[{x - 1, y}, {x + 1, y}, {x, y - 1}, {x, y + 1}]
|> Enum.filter(fn {x, y} ->
# remove out of bounds neighbors
x >= 0 and y >= 0 and x < max_x and y < max_y
end)
end
end
Day9.Part1.solve(my_input)
452
Part 2
defmodule Day9.Part2 do
def solve(input) do
input
|> Day9.Part1.low_points()
|> Enum.map(&basin(&1, input))
|> Enum.map(&Enum.count/1)
|> Enum.sort()
|> Enum.reverse()
|> Enum.take(3)
|> Enum.product()
end
def basin(position, input, sofar \\ []) do
sofar = [position | sofar]
height = Day9.Part1.height(input, position)
max_x = Enum.count(input)
max_y = Enum.count(Enum.at(input, 0))
Day9.Part1.neighbors(position, max_x, max_y)
|> Enum.filter(fn neighbor ->
neighbor_height = Day9.Part1.height(input, neighbor)
neighbor_height > height and neighbor_height < 9
end)
|> Enum.reduce(sofar, &basin(&1, input, &2))
|> Enum.uniq()
end
end
Day9.Part2.solve(my_input)
1263735