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

Day 15

2024/day15.livemd

Day 15

Mix.install([:kino_aoc])

Section

{:ok, puzzle_input} =
  KinoAOC.download_puzzle("2024", "15", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
{:ok,
 "##################################################\n##...O...#OO...O.#....#....#O#O..O..O......O..O..#\n#OOOO.#.O.O.....OO#...O.OO.O....O.#..OO....O#OOO.#\n#...#.#O..O...OO......O.......#....O..O#.O..OO...#\n#.O.....O..#.........O......OO..O..OO.OO....O.O..#\n#.....O.OO.O.#.O...O..#.OOOO..#...#.O.OO.O.#.#OO##\n#...OO.#..O.O.#.O..OO..O....O...OO.OOO.......O...#\n##.O.....O..#O...........O..O.....O.......OO.....#\n#...O..O....O...O...O...O..O..O...O......O..OO...#\n#.O##.O.OO.....O.O.#....O#.....OO.O.O.#..O....#O.#\n#.............#.O........OOO.OO..#.............O.#\n#OOO..O.O.........OO....O.#......#.OO.......O..O.#\n#.......#...O..#O.OO...O..#O.O...##O#O......O##..#\n#O#.O..#........O....O.....O...#O..#......O.O..O.#\n#O..O..O#...#.......OO.OO..O.....O..O..O.O.O...O.#\n#...O.O...OO.......#O#O...O.##.....#..O.O.....O..#\n#.#OOOO..OO..O....O.O....OO.#.OO..O.......O....#.#\n#..O...#.....#.....OO..#O....O#.O....O..OOO.O...O#\n#.O.......OO.O.#........OO...O..O#..O.#..##...#.O#\n#.O..#..........OO.O.O..O..O.......O...O.O.OO....#\n#.O..##..........OO..O..O.....#OO#...#..O....O...#\n#O.OOOO.O..O........O#.#OO.OO...OO.#OO..OO#O.....#\n#..OO..........O...O....O.O.....O.....O...#..O..O#\n#.#O..O..O.....#.O...#........O.O.O..O.......#.O.#\n#..##..O.....O......O..O@........O....O#.O..OO..O#\n#...O..##O.#....#.......O..OO#..O.O.....##O....O.#\n#....O.O...O.OOO.O.O#..O..OOOOOOOOOO#.....O...#.O#\n#O.....#O..O..#..O....O.O..OOOO.#.O.O#....#.O.O#.#\n#..O.O..#O..............O....###..O#.O.....O.#O#O#\n#O...O.O.#.#..O......OO.OO#..O...O.O....O#.O...OO#\n#..OO.O#.....O##.O##....O..#..#..#O..O.....#....O#\n#....#..O..O....O.OO...O.......OO.OO...O.O.....O.#\n#....O.O.#O.#OO.......O......O........OOO..O.....#\n#..#...##.O......##.....O..O.O#.O...O....O..#.O..#\n#...O.O..O....O..O.OOOOOO...#.O...OO.#.....OO.O..#\n#O.......O....#.OO.OO...OO...##O......O.O........#\n##.O.OO.OO...O..O#......O.O....#.............O.#.#\n#O#O...O..O..OO.O.O...OO..O.O..OOOO..O..O...O..O.#\n#..OO.O#O..O..#.O..O.#...#..O.....OO..OOO..O...O.#\n#.O.O..OO.....O...O.....O..#..O..#.O.#.OOO...O.O.#\n#.O..O.......O...OO#.#..O....O...O....O..........#\n#....O..O.OO...OO..#....#O.OO.OO##.....O.........#\n#..O..O....O...O....OO#.#O..O.#.#O.O..O...#....O.#\n#.O.....O.#.O#.O..O.OO.O#............O..........O#\n#..O#O.O.........O.#.O#O..#O.O.........O....O..O.#\n#..O.....#OO..O..#.#.#....O.O.OO.O.O......O#.#O..#\n#.O.O..O.O.O.O...O..O..OO..................#OO...#\n#..O....O....O.....OOO...OO..OO.......O....OO....#\n#.O....OO.O................OO....O.O#O.O.........#\n##################################################\n\n>v>>>^>>v>vv^v^^v^^^^v^^^<v>v^^><>^<>>^>^<^^v>v<>^^v<><<^>v^v<<^>^>^>^>>vvv>^<<^^^^^>>^>^^>^vv>>^^<<<^^^vv^<^<<<>v<^v^<>v<^>>^v^<>><><<^<>v>^>^>v>>v>vv^>vv>><^^<<>>vv<<^vv>^^vv>>><^v^>>v<<<^<><>^>v^vv>v>><><^vvv>^><<>^<<^vv<<>v^^^>v<>^^vv>vv^<>^<>vvvvv<>><><><^>v<>v^v>^<>^v>>><^>>v<<^v>v>^^>^v<<^^>^v>>>>>v^>^v^>vv^v^><^^^<>^v^>><>>>^v<^vvvv<>^>><<^v^^v>^^>^<<<>v^^>><^v>>>^^^^>^>vvv^^^v^^>v^>><>^>^^v>>vvv>^>>>vv^><^v^^^<<<>v^vv^v>v<^^>vv>v<>>vv<>v<^^<<^>>v^<><^<>>v>v>v>v>v>>v<<^>>>>v^><^v^>>>^>^<<>>^^v><^<>>v^^>vv<>><<<<<>><<>vv><^^^>v^>v>>^^v^v^>vvv><<<^>vvv><^^v>v<>v><^v<^<<^<>v>>>>^<>^^^>v>>^<^>v^>^<><<^<>>>^v>><<>v^^v<^>v^v^>vvvv>vv<<>^^^^<>><<>>>vv^<^><><^^^>^v^<><>^^<\n<^>vv>v>^^>^vvvv<<^><^<>>^v>>^^<^<>><<<>^vv<>v>>^<<^<><<>^^vv^^<<>vv^>v><^>v^>>^^v<<<<^v>v>vv^^v>^^>>><>v<><^v>>^^v><>>vv^>v>v^>^>v<><^v>v^^<<>^v^>^>v<><^v<^^vv<>^^^v^>>><<><<<<><^<<^^^vv<^^<^v<>v<>>^<>^<^v^>^v>>>^v>>v^>^^v^>><>^^vvv^<>vv<^^<>v^v^>vv^v>><^>><>^^^<>v<^^^>vv<^^>vv^^^^<<^vvvv^^<>v>>v><^v^vv^v>vvv^>v>>>>^^v<<>^><>v^^^>^^>^>^^vvvv^v>^^^v>>^>><<>^^><<<^>v^^^v><>^>v" <> ...}
#puzzle_input =
  """
##########
#..O..O.O#
#......O.#
#.OO..O.O#
#..O@..O.#
#O#..O...#
#O..O..O.#
#.OO.O.OO#
#....O...#
##########

^v>^vv^v>v<>v^v<<><>>v^v^>^<<<><^
vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<^<^^>>>^<>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^v^^<^^vv<
<>^^^^>>>v^<>vvv^>^^^vv^^>v<^^^^v<>^>vvvv><>>v^<<^^^^^
^><^><>>><>^^<<^^v>>><^^>v>>>^v><>^v><<<>vvvv>^<><<>^><
^>><>^v<><^vvv<^^<><^v<<<><<<^^<^>>^<<<^>>^v^>>^v>vv>^<<^v<>><<><<>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^
<><^^>^^^<>^vv<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>
^^>vv<^v^v^<>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><
v^^>>><<^^<>>^v^v^<<>^<^v^v><^<<<><<^vv>>v>v^<<^
  """

#puzzle_input =
  """
########
#..O.O.#
##@.O..#
#...O..#
#.#.O..#
#...O..#
#......#
########

<^^>>>vv>v<<
  """
warning: outdented heredoc line. The contents inside the heredoc should be indented at the same level as the closing """. The following is forbidden:

    def text do
      """
    contents
      """
    end

Instead make sure the contents are indented as much as the heredoc closing:

    def text do
      """
      contents
      """
    end

The current heredoc line is indented too little
└─ Workspace/hauleth/advent-of-code/2024/day15.livemd#cell:7w6bq5lw7vctw7mk:3:3

warning: outdented heredoc line. The contents inside the heredoc should be indented at the same level as the closing """. The following is forbidden:

    def text do
      """
    contents
      """
    end

Instead make sure the contents are indented as much as the heredoc closing:

    def text do
      """
      contents
      """
    end

The current heredoc line is indented too little
└─ Workspace/hauleth/advent-of-code/2024/day15.livemd#cell:7w6bq5lw7vctw7mk:28:3

warning: code block contains unused literal "##########\n#..O..O.O#\n#......O.#\n#.OO..O.O#\n#..O@..O.#\n#O#..O...#\n#O..O..O.#\n#.OO.O.OO#\n#....O...#\n##########\n\n^v>^vv^v>v<>v^v<<><>>v^v^>^<<<><^\nvvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<^<^^>>>^<>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^v^^<^^vv<\n<>^^^^>>>v^<>vvv^>^^^vv^^>v<^^^^v<>^>vvvv><>>v^<<^^^^^\n^><^><>>><>^^<<^^v>>><^^>v>>>^v><>^v><<<>vvvv>^<><<>^><\n^>><>^v<><^vvv<^^<><^v<<<><<<^^<^>>^<<<^>>^v^>>^v>vv>^<<^v<>><<><<>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^\n<><^^>^^^<>^vv<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>\n^^>vv<^v^v^<>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><\nv^^>>><<^^<>>^v^v^<<>^<^v^v><^<<<><<^vv>>v>v^<<^\n" (remove the literal or assign it to _ to avoid warnings)
└─ Workspace/hauleth/advent-of-code/2024/day15.livemd#cell:7w6bq5lw7vctw7mk:1
"########\n#..O.O.#\n##@.O..#\n#...O..#\n#.#.O..#\n#...O..#\n#......#\n########\n\n<^^>>>vv>v<<\n"
[map, moves] = String.split(puzzle_input, "\n\n")
["##################################################\n##...O...#OO...O.#....#....#O#O..O..O......O..O..#\n#OOOO.#.O.O.....OO#...O.OO.O....O.#..OO....O#OOO.#\n#...#.#O..O...OO......O.......#....O..O#.O..OO...#\n#.O.....O..#.........O......OO..O..OO.OO....O.O..#\n#.....O.OO.O.#.O...O..#.OOOO..#...#.O.OO.O.#.#OO##\n#...OO.#..O.O.#.O..OO..O....O...OO.OOO.......O...#\n##.O.....O..#O...........O..O.....O.......OO.....#\n#...O..O....O...O...O...O..O..O...O......O..OO...#\n#.O##.O.OO.....O.O.#....O#.....OO.O.O.#..O....#O.#\n#.............#.O........OOO.OO..#.............O.#\n#OOO..O.O.........OO....O.#......#.OO.......O..O.#\n#.......#...O..#O.OO...O..#O.O...##O#O......O##..#\n#O#.O..#........O....O.....O...#O..#......O.O..O.#\n#O..O..O#...#.......OO.OO..O.....O..O..O.O.O...O.#\n#...O.O...OO.......#O#O...O.##.....#..O.O.....O..#\n#.#OOOO..OO..O....O.O....OO.#.OO..O.......O....#.#\n#..O...#.....#.....OO..#O....O#.O....O..OOO.O...O#\n#.O.......OO.O.#........OO...O..O#..O.#..##...#.O#\n#.O..#..........OO.O.O..O..O.......O...O.O.OO....#\n#.O..##..........OO..O..O.....#OO#...#..O....O...#\n#O.OOOO.O..O........O#.#OO.OO...OO.#OO..OO#O.....#\n#..OO..........O...O....O.O.....O.....O...#..O..O#\n#.#O..O..O.....#.O...#........O.O.O..O.......#.O.#\n#..##..O.....O......O..O@........O....O#.O..OO..O#\n#...O..##O.#....#.......O..OO#..O.O.....##O....O.#\n#....O.O...O.OOO.O.O#..O..OOOOOOOOOO#.....O...#.O#\n#O.....#O..O..#..O....O.O..OOOO.#.O.O#....#.O.O#.#\n#..O.O..#O..............O....###..O#.O.....O.#O#O#\n#O...O.O.#.#..O......OO.OO#..O...O.O....O#.O...OO#\n#..OO.O#.....O##.O##....O..#..#..#O..O.....#....O#\n#....#..O..O....O.OO...O.......OO.OO...O.O.....O.#\n#....O.O.#O.#OO.......O......O........OOO..O.....#\n#..#...##.O......##.....O..O.O#.O...O....O..#.O..#\n#...O.O..O....O..O.OOOOOO...#.O...OO.#.....OO.O..#\n#O.......O....#.OO.OO...OO...##O......O.O........#\n##.O.OO.OO...O..O#......O.O....#.............O.#.#\n#O#O...O..O..OO.O.O...OO..O.O..OOOO..O..O...O..O.#\n#..OO.O#O..O..#.O..O.#...#..O.....OO..OOO..O...O.#\n#.O.O..OO.....O...O.....O..#..O..#.O.#.OOO...O.O.#\n#.O..O.......O...OO#.#..O....O...O....O..........#\n#....O..O.OO...OO..#....#O.OO.OO##.....O.........#\n#..O..O....O...O....OO#.#O..O.#.#O.O..O...#....O.#\n#.O.....O.#.O#.O..O.OO.O#............O..........O#\n#..O#O.O.........O.#.O#O..#O.O.........O....O..O.#\n#..O.....#OO..O..#.#.#....O.O.OO.O.O......O#.#O..#\n#.O.O..O.O.O.O...O..O..OO..................#OO...#\n#..O....O....O.....OOO...OO..OO.......O....OO....#\n#.O....OO.O................OO....O.O#O.O.........#\n##################################################",
 ">v>>>^>>v>vv^v^^v^^^^v^^^<v>v^^><>^<>>^>^<^^v>v<>^^v<><<^>v^v<<^>^>^>^>>vvv>^<<^^^^^>>^>^^>^vv>>^^<<<^^^vv^<^<<<>v<^v^<>v<^>>^v^<>><><<^<>v>^>^>v>>v>vv^>vv>><^^<<>>vv<<^vv>^^vv>>><^v^>>v<<<^<><>^>v^vv>v>><><^vvv>^><<>^<<^vv<<>v^^^>v<>^^vv>vv^<>^<>vvvvv<>><><><^>v<>v^v>^<>^v>>><^>>v<<^v>v>^^>^v<<^^>^v>>>>>v^>^v^>vv^v^><^^^<>^v^>><>>>^v<^vvvv<>^>><<^v^^v>^^>^<<<>v^^>><^v>>>^^^^>^>vvv^^^v^^>v^>><>^>^^v>>vvv>^>>>vv^><^v^^^<<<>v^vv^v>v<^^>vv>v<>>vv<>v<^^<<^>>v^<><^<>>v>v>v>v>v>>v<<^>>>>v^><^v^>>>^>^<<>>^^v><^<>>v^^>vv<>><<<<<>><<>vv><^^^>v^>v>>^^v^v^>vvv><<<^>vvv><^^v>v<>v><^v<^<<^<>v>>>>^<>^^^>v>>^<^>v^>^<><<^<>>>^v>><<>v^^v<^>v^v^>vvvv>vv<<>^^^^<>><<>>>vv^<^><><^^^>^v^<><>^^<\n<^>vv>v>^^>^vvvv<<^><^<>>^v>>^^<^<>><<<>^vv<>v>>^<<^<><<>^^vv^^<<>vv^>v><^>v^>>^^v<<<<^v>v>vv^^v>^^>>><>v<><^v>>^^v><>>vv^>v>v^>^>v<><^v>v^^<<>^v^>^>v<><^v<^^vv<>^^^v^>>><<><<<<><^<<^^^vv<^^<^v<>v<>>^<>^<^v^>^v>>>^v>>v^>^^v^>><>^^vvv^<>vv<^^<>v^v^>vv^v>><^>><>^^^<>v<^^^>vv<^^>vv^^^^<<^vvvv^^<>v>>v><^v^vv^v>vvv^>v>>>>^^v<<>^><>v^^^>^^>^>^^vvvv^v>^^^v>>^>><<>^^><<<^>v^^^v><>^>v>>vv><<^>>><<^^^<<^<>v>^v^v><<<<<<>>vv^<<<><<><><<^<^>^>>^>v^>^v>^v^<^>^v>><<<^>v^^<>><<^^>>v<<<<<^>>><>v<<>>^v<><<^>>v<<<^<^>>^>v^>^v^v>>v<^>><<>><>vvv<<>vv^>v>><><<^>v><^>^<^v><>>v><^v^vv><>^^>>>v<^v^<^v>^v><>>>>v^^>>>vv>>v>^^v<<<>v>>^^><^<^^<>>^<^^<><^^^><>^>^v>vv^^<^v>><<>>>^>>><<<^vvv^^>vvv^v>>v><<>v><^>>vv^>>^\nvvv^v^><><><><<<^v>^v^><>^vvv<<^<>v>^>v^v^<>v>v^v^<^>^vv<^^v<^^>vv<<>^^<>><<<<^^>>>^<^^>vv<>>>^^^^vv^>^v^v^^>^<<<>v^^^^>v<^^<<^<^vvv>v>v>v<^>><^<^<>>>^^<<>><>>v><>^<>^^^>v>v^>>v^^^v<<>>^v><^<>^>^<^>^^>>>>^^>>^v^^^>>^v>v><^^^v<>>vv>>v^^<><^^v>v<^>>vv^vv>^v>vvvvv^^^^>>^>v>^^<>vv<>^^v><><><^v^^>>>^^vv>^v>^<>vvv^v<^vv^<<^<^^<>>^<<>^>^^v^><^^>><<><<<<<<^>^><^v>^v>>vvv>^^<^<<>v>>vv<^<<^<>v><><>^v>>vvv>^^>>>v><^^>><<^<<^>^vv<>v>^><><<<<>>v^^v>^<>^<>v^^>>^<>>v^>^<>>>><>>>v>^<<^v^><<>>^v>><>><>>>><>vv<<>>^>v^v^v<<<^^<>vvvv^<<>^v<>vvv>>^^v^^^v^^vv<^^^<<>^v^>>^^<<^^v^^v<>>v<>vvvvv>^v>^v<^^v<>^>^<>v^>v^v>><<><>>>>v^<^<^><>^v^<^><<>>^v^^^v^><>^v>v<<^v>>^>^><<^^><^^vvv^><^^<>^v^>\nvvvv^vv^>>^v^v<^v>v>vv>^>^><^vv>v<><>v^v^>vvvv<<>v<^^^vv<^v><>^>^>v<>^>^vvv<>^>^<^^v^<><<>^>^v>^v>v^>^^>^>v^>v>>^^<^<^vv>^vv^v^>v><^vv>^>v>^><>v>v^^>>v>^<>vv^^<>^v^vv^<^^>>v>>^v>vvv^^v^>vv>v<>^^v^^v>><><<>>v>^^<^^^^>^>v<^<^>v^^>v>^>>^><<<^vv>vv^v^>vv>^<>^vvvv^>vv>^>v^>v<>vvv<>>v^>^vv>^>^^vv<>^<<^^><>^^v>^v>>^vv^v<<^^>^vv<>>v<^^^><<^^>^v<>vv><<<<>>vv^>>^vvvv^>vvv>>vv^^^<><^v<>>vv<><<>^^>><<^>vvv^>^vvv<>v^^<<^>v>^>v>^^><<>v^<<<^>^>v<>>vv^><<><^><><^^vv>>^<^vv<^^v<><<><>vvvv^^^<>v>>v^<>^v^<<^>>vvvv^v<<^<^vv^v<^<^^>vv>^<^><^^v^^^v^v>^>^><^>>^v>^v>vv>^v<>^v^^^v^v^>v>><^^<^v^<>^vv^v<<><<<>^v><<<^>vvvvv^v^^^<>v^>>^^^>v^<<<^<>v><<^>^v^<^>><^<^^><>>^^v>vvv^<^>^^^^<^v<<>^<>^>>v>^<><><>>^^vv^<<>><^<>^v^vvv<<>>^<>^>v<<^><<^>^<^>^<<><\n<<^<^>><>v^>vv><>>vvvv<<^><<<>v<>v^v^<>v>v<^^<^<>^^vv<> ...]
%{robot: [robot], wall: walls, box: boxes} =
  map
  |> String.split("\n", trim: true)
  |> Enum.with_index()
  |> Enum.flat_map(fn {row, y} ->
    row
    |> String.to_charlist()
    |> Enum.with_index()
    |> Enum.reject(fn {kind, _} -> kind == ?. end)
    |> Enum.map(fn {kind, x} ->
      kind =
        case kind do
          ?# -> :wall
          ?O -> :box
          ?@ -> :robot
        end

      {{x, y}, kind}
    end)
  end)
  |> Enum.group_by(&amp;elem(&amp;1, 1), &amp;elem(&amp;1, 0))

walls = MapSet.new(walls)
boxes = MapSet.new(boxes)
MapSet.new([
  {38, 2},
  {29, 26},
  {9, 34},
  {47, 38},
  {47, 44},
  {22, 37},
  {19, 38},
  {27, 21},
  {19, 22},
  {16, 10},
  {16, 38},
  {35, 26},
  {10, 32},
  {36, 14},
  {28, 48},
  {17, 30},
  {32, 18},
  {40, 35},
  {6, 23},
  {28, 37},
  {29, 47},
  {29, 40},
  {29, 10},
  {6, 42},
  {23, 46},
  {10, 33},
  {4, 46},
  {43, 47},
  {12, 8},
  {3, 16},
  {15, 3},
  {20, 46},
  {33, 48},
  {35, 6},
  {41, 9},
  {25, 29},
  {1, 2},
  {3, 30},
  {8, 5},
  {18, 37},
  {37, 43},
  {3, 47},
  {30, 26},
  {41, 31},
  {4, 15},
  {33, 40},
  {6, 21},
  {5, 26},
  {1, ...},
  {...},
  ...
])
moves = moves |> String.to_charlist() |> Enum.reject(&amp; &amp;1 not in ~c"^>v<")
~c">v>>>^>>v>vv^v^^v^^^^v^^^<v>v^^><>^<>>^>^<^^v>v<>^^v<><<^>v^v<<^>^>^>^>>vvv>^<<^^^^^>>^>^^>^vv>>^^<<<^^^vv^<^<<<>v<^v^<>v<^>>^v^<>><><<^<>v>^>^>v>>v>vv^>vv>><^^<<>>vv<<^vv>^^vv>>><^v^>>v<<<^<><>^>v^vv>v>><><^vvv>^><<>^<<^vv<<>v^^^>v<>^^vv>vv^<>^<>vvvvv<>><><><^>v<>v^v>^<>^v>>><^>>v<<^v>v>^^>^v<<^^>^v>>>>>v^>^v^>vv^v^><^^^<>^v^>><>>>^v<^vvvv<>^>><<^v^^v>^^>^<<<>v^^>><^v>>>^^^^>^>vvv^^^v^^>v^>><>^>^^v>>vvv>^>>>vv^><^v^^^<<<>v^vv^v>v<^^>vv>v<>>vv<>v<^^<<^>>v^<><^<>>v>v>v>v>v>>v<<^>>>>v^><^v^>>>^>^<<>>^^v><^<>>v^^>vv<>><<<<<>><<>vv><^^^>v^>v>>^^v^v^>vvv><<<^>vvv><^^v>v<>v><^v<^<<^<>v>>>>^<>^^^>v>>^<^>v^>^<><<^<>>>^v>><<>v^^v<^>v^v^>vvvv>vv<<>^^^^<>><<>>>vv^<^><><^^^>^v^<><>^^<<^>vv>v>^^>^vvvv<<^><^<>>^v>>^^<^<>><<<>^vv<>v>>^<<^<><<>^^vv^^<<>vv^>v><^>v^>>^^v<<<<^v>v>vv^^v>^^>>><>v<><^v>>^^v><>>vv^>v>v^>^>v<><^v>v^^<<>^v^>^>v<><^v<^^vv<>^^^v^>>><<><<<<><^<<^^^vv<^^<^v<>v<>>^<>^<^v^>^v>>>^v>>v^>^^v^>><>^^vvv^<>vv<^^<>v^v^>vv^v>><^>><>^^^<>v<^^^>vv<^^>vv^^^^<<^vvvv^^<>v>>v><^v^vv^v>vvv^>v>>>>^^v<<>^><>v^^^>^^>^>^^vvvv^v>^^^v>>^>><<>^^><<<^>v^^^v><>^>v>>vv><<^>>><<^^^<<^<>v>^v^v><<<<<<>>vv^<<<><<><><<^<^>^>>^>v^>^v>^v^<^>^v>><<<^>v^^<>><<^^>>v<<<<<^>>><>v<<>>^v<><<^>>v<<<^<^>>^>v^>^v^v>>v<^>><<>><>vvv<<>vv^>v>><><<^>v><^>^<^v><>>v><^v^vv><>^^>>>v<^v^<^v>^v><>>>>v^^>>>vv>>v>^^v<<<>v>>^^><^<^^<>>^<^^<><^^^><>^>^v>vv^^<^v>><<>>>^>>><<<^vvv^^>vvv^v>>v><<>v><^>>vv^>>^vvv^v^><><><><<<^v>^v^><>^vvv<<^<>v>^>v^v^<>v>v^v^<^>^vv<^^v<^^>vv<<>^^<>><<<<^^>>>^<^^>vv<>>>^^^^vv^>^v^v^^>^<<<>v^^^^>v<^^<<^<^vvv>v>v>v<^>><^<^<>>>^^<<>><>>v><>^<>^^^>v>v^>>v^^^v<<>>^v><^<>^>^<^>^^>>>>^^>>^v^^^>>^v>v><^^^v<>>vv>>v^^<><^^v>v<^>>vv^vv>^v>vvvvv^^^^>>^>v>^^<>vv<>^^v><><><^v^^>>>^^vv>^v>^<>vvv^v<^vv^<<^<^^<>>^<<>^>^^v^><^^>><<><<<<<<^>^><^v>^v>>vvv>^^<^<<>v>>vv<^<<^<>v><><>^v>>vvv>^^>>>v><^^>><<^<<^>^vv<>v>^><><<<<>>v^^v>^<>^<>v^^>>^<>>v^>^<>>>><>>>v>^<<^v^><<>>^v>><>><>>>><>vv<<>>^>v^v^v<<<^^<>vvvv^<<>^v<>vvv>>^^v^^^v^^vv<^^^<<>^v^>>^^<<^^v^^v<>>v<>vvvvv>^v>^v<^^v<>^>^<>v^>v^v>><<><>>>>v^<^<^><>^v^<^><<>>^v^^^v^><>^v>v<<^v>>^>^><<^^><^^vvv^><^^<>^v^>vvvv^vv^>>^v^v<^v>v>vv>^>^><^vv>v<><>v^v^>vvvv<<>v<^^^vv<^v><>^>^>v<>^>^vvv<>^>^<^^v^<><<>^>^v>^v>v^>^^>^>v^>v>>^^<^<^vv>^vv^v^>v><^vv>^>v>^><>v>v^^>>v>^<>vv^^<>^v^vv^<^^>>v>>^v>vvv^^v^>vv>v<>^^v^^v>><><<>>v>^^<^^^^>^>v<^<^>v^^>v>^>>^><<<^vv>vv^v^>vv>^<>^vvvv^>vv>^>v^>v<>vvv<>>v^>^vv>^>^^vv<>^<<^^><>^^v>^v>>^vv^v<<^^>^vv<>>v<^^^><<^^>^v<>vv><<<<>>vv^>>^vvvv^>vvv>>vv^^^<><^v<>>vv<><<>^^>><<^>vvv^>^vvv<>v^^<<^>v>^>v>^^><<>v^<<<^>^>v<>>vv^><<><^><><^^vv>>^<^vv<^^v<><<><>vvvv^^^<>v>>v^<>^v^<<^>>vvvv^v<<^<^vv^v<^<^^>vv>^<^><^^v^^^v^v>^>^><^>>^v>^v>vv>^v<>^v^^^v^v^>v>><^^<^v^<>^vv^v<<><<<>^v><<<^>vvvvv^v^^^<>v^>>^^^>v^<<<^<>v><<^>^v^<^>><^<^^><>>^^v>vvv^<^>^^^^<^v<<>^<>^>>v>^<><><>>^^vv^<<>><^<>^v^vvv<<>>^<>^>v<<^><<^>^<^>^<<><<<^<^>><>v^>vv><>>vvvv<<^><<<>v<>v^v^<>v>v<^^<^<>^^vv<>>vv" ++ ...

Part 1

defmodule Warehouse.A do
  def walk(start, path, walls, boxes) do
    Enum.reduce(path, {start, boxes}, fn dir, {pos, boxes} ->
      move(pos, walls, boxes, dir)
    end)
    |> elem(1)
  end
  
  def move({x, y}, walls, boxes, dir) do
    next = next({x, y}, dir)

    cond do
      next in walls ->
        {{x, y}, boxes}

      next in boxes ->
        if new_boxes = move_box(next, boxes, walls, dir) do
          {next, new_boxes}
        else
          {{x, y}, boxes}
        end

      true ->
        {next, boxes}
    end
  end

  defp move_box(pos, boxes, walls, dir) do
    next = next(pos, dir)
    cond do
      next in walls -> nil
        
      next in boxes ->
        if new_boxes = move_box(next, boxes, walls, dir) do
          new_boxes |> MapSet.delete(pos) |> MapSet.put(next)
        end

      true ->
        boxes |> MapSet.delete(pos) |> MapSet.put(next)
    end
  end

  defp next({x, y}, ?^), do: {x, y - 1}
  defp next({x, y}, ?>), do: {x + 1, y}
  defp next({x, y}, ?v), do: {x, y + 1}
  defp next({x, y}, ?<), do: {x - 1, y}
end
{:module, Warehouse.A, <<70, 79, 82, 49, 0, 0, 14, ...>>, {:next, 2}}
robot
|> Warehouse.A.walk(moves, walls, boxes)
|> Enum.map(fn {x, y} -> x + y * 100 end)
|> Enum.sum()
1406628

Part 2

defmodule Warehouse.B do
  def resize({x, y}, walls, boxes) do
    start = {2 * x, y}

    walls =
      walls
      |> Enum.flat_map(fn {x, y} ->
        [{2 * x, y}, {2 * x + 1, y}]
      end)
      |> MapSet.new()

    boxes =
      boxes
      |> Enum.flat_map(fn {x, y} ->
        pos = [{2 * x, y}, {2 * x + 1, y}]
        box = %{p: pos}

        for p <- pos do
          {p, box}
        end
      end)

    {start, walls, boxes}
  end

  def walk(start, path, walls, boxes) do
    Enum.reduce(path, {start, boxes}, fn dir, {pos, boxes} ->
      move(pos, walls, boxes, dir)
    end)
    |> elem(1)
  end

  def move({x, y}, walls, boxes, dir) do
    next = next({x, y}, dir)

    cond do
      next in walls ->
        {{x, y}, boxes}

      box = boxes[next] ->
        if new_boxes = move_box(box, boxes, walls, dir) do
          {next, new_boxes}
        else
          {{x, y}, boxes}
        end

      true ->
        {next, boxes}
    end
  end

  defp move_box(%{p: pos}, boxes, walls, dir) do
    next = next(pos, dir)

    cond do
      Enum.any?(pos, &amp; &amp;1 in walls) ->
        throw(:wall)

      (next_boxes = select_boxes_at(pos, boxes)) != [] ->
        if new_boxes = move_box(next, boxes, walls, dir) do
          new_boxes |> MapSet.delete(pos) |> MapSet.put(next)
        end

      true ->
        boxes |> Map.drop(pos) |> MapSet.put(next)
    end
  catch
    :throw, :wall -> nil
  end

  defp select_boxes_at(pos, boxes) do
    boxes
    |> Map.take(pos)
    |> Enum.uniq()
  end

  defp next({x, y}, ?^), do: {x, y - 1}
  defp next({x, y}, ?>), do: {x + 1, y}
  defp next({x, y}, ?v), do: {x, y + 1}
  defp next({x, y}, ?<), do: {x - 1, y}
end
warning: variable "next_boxes" is unused (if the variable is not meant to be used, prefix it with an underscore)
└─ Workspace/hauleth/advent-of-code/2024/day15.livemd#cell:3ajets4kgmkyknvu:59: Warehouse.B.move_box/4
{:module, Warehouse.B, <<70, 79, 82, 49, 0, 0, 20, ...>>, {:next, 2}}