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

Advent of Code 2023 - Day 21

day21.livemd

Advent of Code 2023 - Day 21

Sample

sample = """
...........
.....###.#.
.###.##..#.
..#.#...#..
....#.#....
.##..S####.
.##..#...#.
.......##..
.##.#.####.
.##..##.##.
...........
"""
"...........\n.....###.#.\n.###.##..#.\n..#.#...#..\n....#.#....\n.##..S####.\n.##..#...#.\n.......##..\n.##.#.####.\n.##..##.##.\n...........\n"

Input

input = """
...................................................................................................................................
.............#......#.........#....#...#.##.........#.#.#...............#..#................#......#.....#.....###...........#.....
.#............#.#....#......#..#....#..##.........#...#...#.......................#.......#..##.....#......#...........#........#..
.#..##......#.#...##...............#..#....#.#........#...#.........................#.....#........#..#.......#...............#.#..
....#....##......#.#..#.#...#............#.#............#................###...##........#.....#....#..#.#.........................
...#.....#...#....#.#..#..#.#.....#...........#.........#.......#..................###..#.............#.........#......#.....#.....
....#...##..........#.##...#.......#..#..#....#.##....#..........................#.#.#..........#....#.................#...........
......#.....#...........#...#...#....#...........#............#.#.............#.........##.....#...#.##...#..#.................##..
.......#..#...........#........#...#.#........................#..............#........##............#.......#.#...#...........#....
........#.........#..........#.#.#.#.#.#.......##...............#....#.............................#......#..#.............##....#.
.#.##.................#..........##....##.#.#......#..............................##.#......#.......#...........#.#..#....###.#..#.
.#.#......#..........#........##...........#..#............##......#.............#..#...........#.............#..............#.....
....#.............#....#......#....#...........#...............#.............................#.#........#......#.##..#..#.#...###..
....#.............#.................#.............................................#.#....#.#.......#..##..#...........#..#.#.#..#..
...................................#.#...#.#.................#..#..#.....#...........................#....#..#...#.............##..
....##.#...........#.......#...............#..........#.............#.#.............#......##...#........#.........#.....##.##.....
............#..#.......#..................................##......#....................#..##.........#..#.....#...#................
.....###..#.##.#.......#.................................#.....##.........#............#......#......#........#..#.................
..#.#....##.......#.........###......#...#............##..#...........#..##.................##.....#.........###...#.......#.#.....
.................#.#.........##....#................#.............##.#.........................#...............................#...
............................#.#........#............#............................#........#.#..............##.#.#.#.....#..........
...#...#.....#..............#.#..................#.#......##..........#.........#....................##...#.#.....#..#..........#..
..........#...#........#....#.##................##................#.####...#..#.##...........#............#.##......#.#..#..#...#..
.#.....#........#.......#.......#..#...............#........#......#..#..#.###..............#.####....##........#....#.#.......#...
..##....#....................#...............#...............#...................#.................#.#..#........#............#....
...#..#....#........#...##..#.#..#.............................#.......#...#...#.....................#.##....##......#..#..#.....#.
.....#....#..............##..#.............#..#...#........##..#...#...#.........................##.....#....#......#..#...........
.##......#.#...................................#..........#.#.......#...#...##......#...........#..#.....#......#..#...............
.......#..##.........#.............................#.#.............#...##..#.####........#.............#......#.......##.......#...
...#.................#.##..##.#........................#.#..........##.....#......#....#.#.........#...............................
..............#......#.................##..#.........#....###...#........#......#.....#......................##.....#..........#...
......#.......##..#..#.......#..................#.......#..##........#....#..#...#.##...................#..........#......#........
..#..#.#.#.....#...#.........#..............#..#....#......#......#.#.....#......#......#.....................#.#..................
..................#.....................#.#.......#.#..........#.....#.........#....#.....#............##..#...#...#...........#...
.#...#......#.#.#.....................#............#.......#....#.............#..#....#..##.#..........#.......#..#...#....#.......
.#....#..#.#...........##............#.#....#.#..#......###.............#..#.....#..#.##.#..#......................#.........#.....
...#...#.......#.#..#..#............#..#....#..#....#..#.......#.........#......#.#.###...........................#.......###......
...#...........#.......##............#..#.....##..####.......#..........#....#...#.........................#....#..#...............
.........#.......#....#..............#...........#.#................#....#.....##......#......#.............................#..#...
..##....#.#.#....#.................#..#....#...#...#..........#...#...#...#....#.....#........................#......#.............
..#....##.........#.#...........#..#.##.#..........................#......##.....#...#...#.....#..#.............##.................
...#........#...##.#............#..#...#.#.#.#....#.#..#..............#.###.#.#..#......#..#.......#..........#....##.#.....##.....
..#.#..#......#............#.##.....#.....#.....##.....##.......#........#.#......#.....#.#.......#..............#....#...#.#..#...
..................#.........#..#.#.#.#..........#....#......#........#....................#.............#.....................#....
.......................................#..#.....#..#....##............#...........#...#.............#..#......................#....
..#.............#..........#..#........##..#.......................#..#......#...#.#.#......#..#...................#.....#.##......
...#..#................#.#........#.#.................#..#.....#........##.....#...........##......#..#..#......................#..
..###.....#..................#................#.#....................#..............#....#...........................#.#.##.....##.
.........#...#...........#.#...#....#.........#..##.###..............#......#..#....#....###.#.........................#...........
......#..##...........##......#..#..#.#................#..............#...#......#....#.....#...............#...............#...#..
.#......##.........##.......###..#.##.#......#...#.............#..#....#..#.................##...................................#.
...........................................##........#......#....................#.#...................##....#............##.....#.
..#..##..#........#.......###...#.....#............#.#............#..##....#............##..........#.##.......###.................
........#..................#...#.........#..........#.#.....#..............##......................................................
...............#...#......##.................#.......#...#................#..#.............#.....#...........#...#.................
....................#.......#.....#...#.#..#.......#........#......#...#.###........#....#....#.......#...#.#.....#.#..............
...#..............#.#......#.#.#..#.#....#.....#..#........#...............#...##..........................#.......................
...............#........#................#.#.....#....#..#......#......##....##....#.#........##.#.....#.........##.............#..
...#.......#....#......#.....#.#....#...........#.#..........#....#.......#..#............#.#.....#.###............................
.##........#..#...#..##.##..#.#.#.......#......#.#.........................#.....#...............#.................................
.#..............#......#.#.##.#.....##..#..............#....#.#..................##..#....#..#.#...#..#..........#..#..#.........#.
..........#..............#.............#....#...........##.#...#....#...#..#..#......#....#.#.#.....##..............##.............
.............#...#...#............#.....##..#......#.#.#........#.......#................#...........#............#.......#........
..............#...###.#.#.......##........#.#..##......#.#.#..#...........#..............#.......#....#.#.#........................
..........##...###........#........#..#...............##..#....##......##........##...#.......#.....###....#...#..#.#...#..#.......
.................................................................S.................................................................
..............#...##...........................#.....#..#...#......#...................#............#...........##.................
........#..###.........#...#........#..#...#...............#.........#..........#...#............#...#........##..##......#........
............#.....###.....##.....#.#..#..#..#.....#............#.......#.#....#.....#.#...#......##.........#...#....#.#...........
........#....#...##..##...........#.......#.....#........##.....#.......#......#.....................#.....#....#..#...............
...........#..##.#...#...#......#.#.......#............#.......#....#........#....#........##.....#...#....#....#.....#............
....................#........##........#..............#.##.#..##...#..#.....##.............#....#.........#.##..................#..
........................#.........#..................#..#...................#.#.............#...........##..#...#.#...#.........#..
...................##..#........#..............##....#...#.........................#....#....#.##...........##.#...................
.##.................#...#.....#.#..#.#..#.#...#....#..............#..#..#...........##.....................##..#...#...............
...............#.........#....#.###..........#......................##...##.......#..##.###..#.....#...............................
.##..............#.....#.#.#............#......#...............#..#.#.........#.......#..#...#....#.#.........#..#.................
......#.............#..........#................................#..........#...#......#.#...#.....#...........#............##......
..#....#..........#...#.....##......#........#................#.........##............#......#........#..##....#...................
..#...#...................................#..#...........#........#....##.....#....#....#.....###..#..#......#...........#.........
...#.#...#..........##...........#.................##...#.........#......#.....#....#.....#......#..............................#..
.#........#..............##.....#..#.....#...#...##.#........................................#.#....#.......................###....
..#....#.............#.....................#.......#.......#.##.....#............#.....#.....#...#...............................#.
.#...#.#...............#.#.........##.......#.###.....#...............#...#.....#......#..##.....#...#.#.#...............#..##..#..
......##...#................#...........#.#......#.................#....#...#...#..............#.#.......#.........#...#.##........
............#...#.......#.....##.#..#...#...................#.............#...........##.........#..#.....#............##.....#....
....#..###.......#............##...##........#.#....#...................###............#.#...#..#..#.#..............#.........#....
..........#......#........##............##....................#.#..#................#....##.#.#.#....##.#...........##....#........
............##.#...#..............##......#......#.......#...........#.........#..........##.#.................#............#...#..
...#.......#.......................#.......#...#...........................##..#..............#....##..........................#.#.
.#..#.#....#.#....#..............#.........#..........#.......#.#..............#....#.#..##.#....#.....................#..#.#......
..#....#.........#..............#...#...#..#.#..#..##....##..#.........#....................#.......#........##......#...#..#...#..
..##.........#..#.##....................##.#.#......#..#.#........#...........#...#.....#..####....................#...#...........
...#...............#..##...............#......#...##.........#.........#........##.............##..........#.#..#.........#........
....#............................#.#......#....#.#...#......#.......#.........#...........##..................#.#..................
...................#...................................#.....#.....#.#....#...........#.....##...............#...............#.#.#.
..#..#.......#.##.#..#...#................#..#.......#....#..#.......#...#........#...#....#.#..........#......#......###..#.......
.......#.................#..........#.......#..........................#..##...#.##..#..##.#..........#....#.......................
.......#........#.........#...........#.....#..#..............#.......#.#..##......#........#.............##................###....
.#.....#.#....##.....#................#..............#...............#..##..##.#.......#.#.#...........#......#......#..#.#........
.....#..#...............#..#.#..............#..#........................#.....#.#....###...........#......##......#..#.............
.....##..........#.#.#...................#..........#........##.......#....#......#....##.........#.#....#............#..#.........
........#.#........#.#..#.#...#.........................##.#.........#.............##...#.............#..#...##..#..#..............
....#...................#.....#.#.#.......##........#.#.#..#.........#....##......................#...#.#..#......#.........##.....
.....#.....#...........#.....#............................#..#........#............#.................#................##..#.#......
.###..#.......##..#.............#.....................#......##......#..............#..................#..#.........#........#.....
..#.#...#............#........................#............##..#...##....##....#..#......................#..#..........#.#.........
......#.........#..#......................................#.#.#.#.#..#......................#.##...#....#..#.#.....................
....#..........................................#.....##.........................#.................##...........#....##......#...##.
....................#.......#.#....##...#........#.....#...##......#.....#......................#..#.....#.#..#...#...#............
..#................#......#.#...#.......#....................##.#.......#.#...#...............##.#.....#......#.#..###....#..#.#...
........................#........#....#.#.#.......#.#...................#.##....#............#.......#...#....#..#....##....#..#...
..............#...#.#...####.......................#....##.....#...#...#.#.#...#..............#....#.#....#..................##....
.....#.....#..............#...#......#....#.............##................#..................................#..........#..........
......##.........#.......#...#....#...##....#..............#.#.#...........##................#..................#...#...#..........
.#..#.....#.......#.#..#...#......#.....#............................#.....................#..#..#..#....#.......#.........#.#...#.
......#.#..#.#.#..............#....#....#..#..............#............##................#......#......##.#..#....#................
...........#...................##.#..##.#.##...#.........#.##..#.........#............#.#.#.#...#.#.#..#..##.#......##.........##..
........##.......#.#..#........#..##.#..#.#.....#.........#.##.#..................#.##................###..##.....#.....#..........
.....................#...#........#.##.........#...........##..##.#.............#.............#....#.....##....#.#.....#.##........
...#...##...............#.##...........#.#.................#....#...#.#............#.#....##......#.........#..#....#.#.#.......#..
..#..#.#...........#..##....#...#...##..###..#...#................#............................#.........#.......#...#...#.#.#..##.
............#..........#.#.#...##...............#...#.............................###....###..........###......#.......#....#.#....
..#.#.##.........##....#.#...............#...#..#...................#........#.#.........#.#...#......#....#.#....##.....#....#....
...#.#.......#...#...#....#.....#...#..#.....#....#............#...#.......##.#................#...#......#....#.........##........
.................#.#.###........#..#...##............##...........#.............................#.#.#.......#.........#...#....##..
....#..........#.......##.......#..#.....#..#.......................................#..........#..............#.........#.##....#..
......#......#..##..#..##....#........#.#....##........#.#..................#.#.....#.............###.#...#...#........#.....#.....
......#.........##....#...................#...#..#..#..................#............#.....#..#.......#....#......#..#........#.....
..#.............#....#......#...###.......#..#....................................#.........##.........#.#..................#...#..
...................................................................................................................................
"""
"...................................................................................................................................\n.............#......#.........#....#...#.##.........#.#.#...............#..#................#......#.....#.....###...........#.....\n.#............#.#....#......#..#....#..##.........#...#...#.......................#.......#..##.....#......#...........#........#..\n.#..##......#.#...##...............#..#....#.#........#...#.........................#.....#........#..#.......#...............#.#..\n....#....##......#.#..#.#...#............#.#............#................###...##........#.....#....#..#.#.........................\n...#.....#...#....#.#..#..#.#.....#...........#.........#.......#..................###..#.............#.........#......#.....#.....\n....#...##..........#.##...#.......#..#..#....#.##....#..........................#.#.#..........#....#.................#...........\n......#.....#...........#...#...#....#...........#............#.#.............#.........##.....#...#.##...#..#.................##..\n.......#..#...........#........#...#.#........................#..............#........##............#.......#.#...#...........#....\n........#.........#..........#.#.#.#.#.#.......##...............#....#.............................#......#..#.............##....#.\n.#.##.................#..........##....##.#.#......#..............................##.#......#.......#...........#.#..#....###.#..#.\n.#.#......#..........#........##...........#..#............##......#.............#..#...........#.............#..............#.....\n....#.............#....#......#....#...........#...............#.............................#.#........#......#.##..#..#.#...###..\n....#.............#.................#.............................................#.#....#.#.......#..##..#...........#..#.#.#..#..\n...................................#.#...#.#.................#..#..#.....#...........................#....#..#...#.............##..\n....##.#...........#.......#...............#..........#.............#.#.............#......##...#........#.........#.....##.##.....\n............#..#.......#..................................##......#....................#..##.........#..#.....#...#................\n.....###..#.##.#.......#.................................#.....##.........#............#......#......#........#..#.................\n..#.#....##.......#.........###......#...#............##..#...........#..##.................##.....#.........###...#.......#.#.....\n.................#.#.........##....#................#.............##.#.........................#...............................#...\n............................#.#........#............#............................#........#.#..............##.#.#.#.....#..........\n...#...#.....#..............#.#..................#.#......##..........#.........#....................##...#.#.....#..#..........#..\n..........#...#........#....#.##................##................#.####...#..#.##...........#............#.##......#.#..#..#...#..\n.#.....#........#.......#.......#..#...............#........#......#..#..#.###..............#.####....##........#....#.#.......#...\n..##....#....................#...............#...............#...................#.................#.#..#........#............#....\n...#..#....#........#...##..#.#..#.............................#.......#...#...#.....................#.##....##......#..#..#.....#.\n.....#....#..............##..#.............#..#...#........##..#...#...#.........................##.....#....#......#..#...........\n.##......#.#...................................#..........#.#.......#...#...##......#...........#..#.....#......#..#...............\n.......#..##.........#.............................#.#.............#...##..#.####........#.............#......#.......##.......#...\n...#.................#.##..##.#........................#.#..........##.....#......#....#.#.........#...............................\n..............#......#.................##..#.........#....###...#........#......#.....#......................##.....#..........#...\n...." <> ...

Part 1

defmodule Part1 do
  def parse(input) do
    input
    |> String.split("\n", trim: true)
    |> Enum.with_index()
    |> Enum.reduce(
      {MapSet.new(), nil},
      fn {row, y}, acc ->
        row
        |> String.graphemes()
        |> Enum.with_index()
        |> Enum.reduce(
          acc,
          fn {cell, x}, {rocks, start} ->
            case cell do
              "#" -> {MapSet.put(rocks, {x, y}), start}
              "S" -> {rocks, {x, y}}
              _ -> {rocks, start}
            end
          end
        )
      end
    )
  end

  def move(_, starts, 0), do: starts

  def move(rocks, starts, count) do
    new_starts =
      starts
      |> Enum.map(fn {x, y} ->
        [
          {x + 1, y},
          {x - 1, y},
          {x, y + 1},
          {x, y - 1}
        ]
        |> Enum.filter(fn n ->
          !MapSet.member?(rocks, n)
        end)
      end)
      |> List.flatten()
      |> Enum.into(MapSet.new())

    move(rocks, new_starts, count - 1)
  end
end

{rocks, start} = Part1.parse(input)
Part1.move(rocks, [start], 64) |> MapSet.size()
3615

Part 2

defmodule Part2 do
  def parse(input) do
    input
    |> String.split("\n", trim: true)
    |> Enum.with_index()
    |> Enum.reduce(
      {MapSet.new(), nil, 0, 0},
      fn {row, y}, acc ->
        row
        |> String.graphemes()
        |> Enum.with_index()
        |> Enum.reduce(
          acc,
          fn {cell, x}, {rocks, start, width, height} ->
            case cell do
              "#" -> {MapSet.put(rocks, {x, y}), start, max(x + 1, width), max(y + 1, height)}
              "S" -> {rocks, {x, y}, max(x + 1, width), max(y + 1, height)}
              _ -> {rocks, start, max(x + 1, width), max(y + 1, height)}
            end
          end
        )
      end
    )
  end

  def move(rocks, frontier, dists, width, height) do
    new =
      frontier
      |> Stream.flat_map(fn {x, y} ->
        [
          {x + 1, y},
          {x - 1, y},
          {x, y + 1},
          {x, y - 1}
        ]
        |> Stream.filter(fn {nx, ny} ->
          !MapSet.member?(rocks, {Integer.mod(nx, width), Integer.mod(ny, height)}) &amp;&amp;
            !Map.has_key?(dists, {nx, ny})
        end)
        |> Stream.map(fn {nx, ny} ->
          {{nx, ny}, dists[{x, y}] + 1}
        end)
      end)
      |> Enum.into(Map.new())

    {Map.keys(new), Map.merge(dists, new)}
  end
end

# Let's look at some patterns:

# steps = 1000

# {rocks, start, width, height} = Part2.parse(input)
# 1..steps
# |> Enum.reduce(
#   {[start], %{start => 0}},
#   fn n, {frontier, dists} ->
#     {frontier, dists} = Part2.move(rocks, frontier, dists, width, height)
#     count = dists |>  Map.values |> Stream.filter(fn d -> rem(d, 2) == rem(n, 2) end) |> Enum.count
#     IO.puts("#{n}: #{count}")
#     {frontier, dists}
#   end)

# derived formula:
f = fn x ->
  trunc(3734 + 29551 + 29432 * (x * (x + 1) / 2 - 1) + 119 * (x - 1))
end

steps = 26_501_365
# (steps - 65) / 131 = 202300

f.((steps - 65) / 131)
602259568764234