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

Advent of Code 2024 - Day 14

2024/14.livemd

Advent of Code 2024 - Day 14

Mix.install([
  {:req, "~> 0.5"},
  {:benchee, "~> 1.3"}
])

Input

opts = [headers: [{"cookie", "session=#{System.fetch_env!("LB_AOC_SESSION")}"}]]
puzzle_input = Req.get!("https://adventofcode.com/2024/day/14/input", opts).body
size_x = 101
size_y = 103

robots =
  puzzle_input
  |> String.split("\n", trim: true)
  |> Enum.map(fn robot ->
    [<<"p=", pos::binary>>, <<"v=", vel::binary>>] = String.split(robot, " ")

    [pos, vel]
    |> Enum.map(fn x ->
      String.split(x, ",") |> Enum.map(&amp;String.to_integer/1) |> List.to_tuple()
    end)
    |> List.to_tuple()
  end)

Puzzle 1

puzzle_1 = fn ->
  mid_x = div(size_x, 2)
  mid_y = div(size_y, 2)

  robots
  |> Enum.reduce({0, 0, 0, 0}, fn {{x, y}, {vx, vy}}, {tl, tr, bl, br} ->
    x = Integer.mod(x + vx * 100, size_x)
    y = Integer.mod(y + vy * 100, size_y)

    case {x, y} do
      {x, y} when x < mid_x and y < mid_y -> {tl + 1, tr, bl, br}
      {x, y} when x > mid_x and y < mid_y -> {tl, tr + 1, bl, br}
      {x, y} when x < mid_x and y > mid_y -> {tl, tr, bl + 1, br}
      {x, y} when x > mid_x and y > mid_y -> {tl, tr, bl, br + 1}
      _other -> {tl, tr, bl, br}
    end
  end)
  |> then(fn {tl, tr, bl, br} ->
    tl * tr * bl * br
  end)
end

puzzle_1.()

Puzzle 2

# solved manually by printing each grid
print_grid = fn points, size_x, size_y ->
  points_set = MapSet.new(points)

  for y <- 0..(size_y - 1) do
    for x <- 0..(size_x - 1) do
      if MapSet.member?(points_set, {x, y}) do
        IO.write("X")
      else
        IO.write(".")
      end
    end

    IO.puts("")
  end
end

puzzle_2 = fn ->
  for i <- Stream.iterate(0, &amp;(&amp;1 + 1)) do
    Enum.map(robots, fn {{x, y}, {vx, vy}} ->
      x = Integer.mod(x + vx * i, size_x)
      y = Integer.mod(y + vy * i, size_y)

      {x, y}
    end)
    |> print_grid.(size_x, size_y)

    IO.puts("Seconds: #{i}")

    Process.sleep(50)
  end
end

# puzzle_2.()

Benchmarks

Benchee.run(%{
  "puzzle_1" => fn -> puzzle_1.() end
})
Name ips average deviation median 99th %
puzzle_1 253.20 3.95 ms ±2.76% 3.93 ms 4.33 ms