Powered by AppSignal & Oban Pro

Advent of code day 18

2023/livebooks/day-18.livemd

Advent of code day 18

Mix.install([
  {:kino, "~> 0.5.0"}
])

Setup input

example = Kino.Input.textarea("Please paste your input example:")
input = Kino.Input.textarea("Please paste your real input:")

Part 01

# This solution is based on shoelace forula and picks theorem 


dirs = %{"R" => {0, 1}, "L" => {0, -1}, "D" => {1, 0}, "U" => {-1, 0}}

{points, boundary_points} =
  example
  |> Kino.Input.read()
  |> String.split("\n", trim: true)
  |> Enum.reduce({[{0, 0}], 0}, fn line, {[{r, c} | _] = points, b} ->
    [d, n, _] = String.split(line, " ", trim: true)
    {dr, dc} = dirs[d]
    n = String.to_integer(n)

    {[{r + n * dr, c + n * dc} | points], b + n}
  end)

area =
  points
  |> Enum.with_index()
  |> Enum.map(fn {{x, _y}, i} ->
    len = length(points)
    {_x1, y1} = Enum.at(points, rem(i - 1, len))
    {_x2, y2} = Enum.at(points, rem(i + 1, len))
    x * (y1 - y2)
  end)
  |> Enum.sum()
  |> abs()
  |> Integer.floor_div(2)

i = area - div(boundary_points, 2) + 1

boundary_points + i

Part 02

dirs = %{"R" => {0, 1}, "L" => {0, -1}, "D" => {1, 0}, "U" => {-1, 0}}
dd = %{0 => "R", 1 => "D", 2 => "L", 3 => "U"}

{points, boundary_points} =
  example
  |> Kino.Input.read()
  |> String.split("\n", trim: true)
  |> Enum.reduce({[{0, 0}], 0}, fn line, {[{r, c} | _] = points, b} ->
    [_, _, code] = String.split(line, " ", trim: true)

    <> =
      code |> String.replace(["(", ")", "#"], "")

    n = String.to_integer(distance, 16)
    d = String.to_integer(direction, 16)

    {dr, dc} = dirs[dd[d]]

    {[{r + n * dr, c + n * dc} | points], b + n}
  end)

area =
  points
  |> Enum.with_index()
  |> Enum.map(fn {{x, _y}, i} ->
    len = length(points)
    {_x1, y1} = Enum.at(points, rem(i - 1, len))
    {_x2, y2} = Enum.at(points, rem(i + 1, len))
    x * (y1 - y2)
  end)
  |> Enum.sum()
  |> abs()
  |> Integer.floor_div(2)

i = area - div(boundary_points, 2) + 1

boundary_points + i