Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Day9

livebook/day-09.livemd

Day9

Setup

Mix.install(
  [
    {:kino, "~> 0.4.1"}
  ],
  consolidate_protocols: false
)

input = Kino.Input.textarea("Please paste your input:")
parsed =
  input
  |> Kino.Input.read()
  |> String.split([" |\n", " | ", "\n"], trim: true)
  |> Enum.map(fn string -> "9#{string}9" end)
  |> (fn parsed -> ["999999999999"] ++ parsed ++ ["999999999999"] end).()
  |> Enum.map(&String.to_charlist/1)

parsed_x =
  parsed
  |> Enum.map(fn string -> Enum.zip(0..Enum.count(string), string) end)

parsed_y =
  parsed
  # transpose
  |> Enum.zip_with(fn x -> x end)
  |> Enum.map(fn string -> Enum.zip(0..Enum.count(string), string) end)

[string | rem] = parsed_x
[string | _] = rem
parsed

# string
# |> Enum.chunk_every(3)
# Enum.zip(0..Enum.count(string), string)
lines =
  input
  |> Kino.Input.read()
  |> String.split("\n", trim: true)

# |> Enum.map(fn string -> Enum.with_index(fn {index, letter} -> %{
#   index => letter
# }end)end)

grid =
  for {line, row} <- Enum.with_index(lines),
      {number, col} <- Enum.with_index(String.to_charlist(line)),
      into: %{} do
    {{col, row}, number - ?0}
  end

Part 1

lines = input |> Kino.Input.read() |> String.split("\n", trim: true)

grid =
  for {line, row} <- Enum.with_index(lines),
      {number, col} <- Enum.with_index(String.to_charlist(line)),
      into: %{} do
    {{row, col}, number - ?0}
  end

low_points =
  Enum.filter(grid, fn {{row, col}, value} ->
    up = grid[{row - 1, col}]
    down = grid[{row + 1, col}]
    left = grid[{row, col - 1}]
    right = grid[{row, col + 1}]
    value < up and value < down and value < left and value < right
  end)

low_points
|> Enum.map(fn {_, value} -> value + 1 end)
|> Enum.sum()

Part 2

defmodule Recursion do
  def basin(point, grid) do
    basin(MapSet.new(), point, grid)
  end

  defp basin(set, {row, col} = point, grid) do
    if grid[point] in [9, nil] or point in set do
      set
    else
      set
      |> MapSet.put(point)
      |> basin({row - 1, col}, grid)
      |> basin({row + 1, col}, grid)
      |> basin({row, col - 1}, grid)
      |> basin({row, col + 1}, grid)
    end
  end
end

low_points
|> Enum.map(fn {point, _} ->
  point
  |> Recursion.basin(grid)
  |> MapSet.size()
end)
|> Enum.sort(:desc)
|> Enum.take(3)
|> Enum.product()