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

Advent of Code 2023 - Day 21

2023/21.livemd

Advent of Code 2023 - Day 21

Mix.install([
  {:req, "~> 0.4.0"}
])

Input

opts = [headers: [{"cookie", "session=#{System.fetch_env!("LB_AOC_SESSION")}"}]]
puzzle_input = Req.get!("https://adventofcode.com/2023/day/21/input", opts).body
input =
  for {row, r} <- String.split(puzzle_input, "\n", trim: true) |> Enum.with_index(1),
      {col, c} <- String.graphemes(row) |> Enum.with_index(1),
      into: %{},
      do: {{r, c}, col}

Part 1

{start, _v} = Enum.find(input, fn {_k, v} -> v == "S" end)
defmodule StepCounter do
  def positions_count(init_position, grid, steps) do
    {{size, size}, _} = Enum.max(grid)

    for _i <- 1..steps, reduce: [init_position] do
      acc -> StepCounter.step(acc, grid, size)
    end
    |> Enum.count()
  end

  def step(positions, grid, size) do
    positions
    |> Stream.flat_map(&amp;adjacents/1)
    |> Stream.reject(&amp;is_rock?(&amp;1, grid, size))
    |> Enum.uniq()
  end

  defp adjacents({r, c}) do
    [
      {r + 1, c},
      {r - 1, c},
      {r, c + 1},
      {r, c - 1}
    ]
  end

  defp is_rock?({r, c}, grid, size) do
    r = Integer.mod(r, size)
    c = Integer.mod(c, size)
    grid[{r, c}] == "#"
  end
end

StepCounter.positions_count(start, input, 64)

Part 2

Run in Livebook