this repo has no description

2024 day 15-23

hauleth.dev 89e91428 6dce628d

verified
+11 -3
2024/day14.livemd
···
```elixir
{tree, steps} =
-
0..10_000
+
Stream.from_index()
|> Task.async_stream(
fn step ->
robots = Robot.walk(robots, room, step)
···
Image.new!(w, h)
|> Image.mutate(fn img ->
for %{pos: {x, y}} <- tree do
-
Image.Draw.point(img, x, y, color: :white)
+
# Add some festivity
+
color =
+
if abs(:math.sin(x + y)) < 0.5 do
+
:red
+
else
+
:green
+
end
+
+
Image.Draw.point(img, x, y, color: color)
end
{:ok, img}
···
|> Image.resize!(4, interpolate: :nearest)
```
-
<!-- livebook:{"offset":9077,"stamp":{"token":"XCP.gUbmyoJABRufOfOt0ZeaLvsGKeSMKLrJo_tuzD9IPlUw8bA8QTK0V6_qDCVmNX02724bl4wTSGMbDl9LH4-qrXfejoCDaxokcatvdIiDcPrwE0PpJ7V34ORcoI0URmYd_Mo","version":2}} -->
+
<!-- livebook:{"offset":9213,"stamp":{"token":"XCP.bbViODF6Z4_TcNSzpaXWzuFflurdyZ5JsvKHJZr6NjgJ4MQaH2OorTxA-YR5uDBN5HxiB0uC5hX0vi-Kgdm26HMcOubYpE_c39bjuPfPH_BH4SVxLeEac5c8aaRtPdt7CJk","version":2}} -->
+395
2024/day15.livemd
···
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 15
+
+
```elixir
+
Mix.install([:kino_aoc])
+
```
+
+
## Section
+
+
<!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIxNSIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
+
+
```elixir
+
{:ok, puzzle_input} =
+
KinoAOC.download_puzzle("2024", "15", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{: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^vv^vv<<>^v^^^<<<vv<>vv^^>v>v^^><>^<v<v><>>^>^<^^v>v<>^^v<><<^><v>v^v<<^>^>^>^>>vvv>^<<^^^^^><vv>>^>^^>^vv>><v^^v^<<<>^^<<<^^^vv^<^<<<>v<^v<v>^<>v<^>>^v^<>><><<^<>v>^>^>v>>v>vv^><v<v^v>vv>><^^<<>>vv<<^vv>^^vv>>><^v^>>v<<<<v>^<><>^>v^vv>v>><><^vvv>^><<>^<<<vvv^>^vv<<>v^^^>v<>^^vv>vv^<>^<>vvv<vvvv^^^<^vv^<v^<<vv^v<><vvvv^>vv<>><><<v>><^>v<>v<v<v>^v>^<>^v>>><^>>v<<<v^>^v>v>^^>^v<v^v^^<vv^v^><<^^<v^v>>^v>>>>>v<v^>^>^v^>vv^v^><^<v>^^<>^v^>><>>><vv<<>^v<^vvv<v^vvv^>v<<v>>^>><<^v^^v>^^>^<<<>v^^>><<v>^<v^<^>v>>>^^^<<vvv^>vvv>^><v>^>vvv^^^v^^>v^><v>><>^<v<<vv^^>>^^v>><vv>vvv>^>>>vv^><^<v<<<^^v>v^<v^^>^^<<<>v^vv<vvv>^v>v<^^>vv>v<>>vv<><v>v<^^<<^>>v<v^<>^<<v>><<vv^<<<<v^^^v^^<^<^<>v><^<>>v>v>v>v>v><v>>v<<^>>><v^v<v>>v^><^v^>>>^>^<<>>^^v><^<v^vv^<><>>v^^>v<vvv>v<>><<<<<>><<><v<>vv><^^^><vv<v<<>v^>v>>^^v^v^>vvv<v^<>><<<^>vvv><^^v>v<>v><^<v>v<^<<^<>v>>>>^<>^^^>v<v<<vv><v>>>^<^>v^><vv>^<<v<>><<^<>>>^v>><<>v^^v<^>v^v^>vvvv>vv<<>^^^<v>^<<v>>><<>>>vv^<^><><^^^>^v^<><>^<vv<^vv^^v>^<\n<^>vv>v>^^>^vvvv<<^><^<>>^<v>v>>^^<v><^<>><<<>^vv<>v<v^>>>^<<^<><<>^^vv^^<<><<vvv>v^^>vv^<v<<>>v><^>v^>>^^v<<<<^v<v<<>>v><v^>vv^<vv^>^v>^^>>><>v<><^v><vvvv^v<<>>^^v><>>vv^>v>v^>^>v<><^v>v^^<<>^v^>^>v<><^v<^^vv<>^^^v^>>><<><<<<v^v^><v<v<^^^><><^<<^^^vv<^^<^<v>v<<v^>>v<>>^<vv<^<v><>^<^v^>^v>>>^v>>v^>^^v^>><<v>>^<v>^vvv<v<<<v>^<>vv<^<v<>^<>v^v^>vv^v>><^>><>^^^<<v<vv^<vv>>v<^^^>vv<^^>vv^^^^<<^<v^>v<v>vvv<v<<^^><v<<^>^^<>v>>v><^v^<v>vv^<v<<v>v>vvv^>v<vv>>>>>^^v<<>^><>v^^^>^^>^>^^vvvv^v<v>>^^^v>>^<v<^^v>>><<>^^><<<^>v^^^v><v<v<v^v^><>^>v<v<^^^>" <> ...}
+
```
+
+
```elixir
+
#puzzle_input =
+
"""
+
##########
+
#..O..O.O#
+
#......O.#
+
#.OO..O.O#
+
#..O@..O.#
+
#O#..O...#
+
#O..O..O.#
+
#.OO.O.OO#
+
#....O...#
+
##########
+
+
<vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^
+
vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v
+
><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv<
+
<<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^
+
^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^><
+
^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^
+
>^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^
+
<><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>
+
^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v>
+
v^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^
+
"""
+
+
#puzzle_input =
+
"""
+
########
+
#..O.O.#
+
##@.O..#
+
#...O..#
+
#.#.O..#
+
#...O..#
+
#......#
+
########
+
+
<^^>>>vv<v>>v<<
+
"""
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
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<vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^\nvvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v\n><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv<\n<<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^\n^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^><\n^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^\n>^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^\n<><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>\n^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v>\nv^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^\n" (remove the literal or assign it to _ to avoid warnings)
+
└─ Workspace/hauleth/advent-of-code/2024/day15.livemd#cell:7w6bq5lw7vctw7mk:1
+
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
"########\n#..O.O.#\n##@.O..#\n#...O..#\n#.#.O..#\n#...O..#\n#......#\n########\n\n<^^>>>vv<v>>v<<\n"
+
```
+
+
```elixir
+
[map, moves] = String.split(puzzle_input, "\n\n")
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
["##################################################\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^vv^vv<<>^v^^^<<<vv<>vv^^>v>v^^><>^<v<v><>>^>^<^^v>v<>^^v<><<^><v>v^v<<^>^>^>^>>vvv>^<<^^^^^><vv>>^>^^>^vv>><v^^v^<<<>^^<<<^^^vv^<^<<<>v<^v<v>^<>v<^>>^v^<>><><<^<>v>^>^>v>>v>vv^><v<v^v>vv>><^^<<>>vv<<^vv>^^vv>>><^v^>>v<<<<v>^<><>^>v^vv>v>><><^vvv>^><<>^<<<vvv^>^vv<<>v^^^>v<>^^vv>vv^<>^<>vvv<vvvv^^^<^vv^<v^<<vv^v<><vvvv^>vv<>><><<v>><^>v<>v<v<v>^v>^<>^v>>><^>>v<<<v^>^v>v>^^>^v<v^v^^<vv^v^><<^^<v^v>>^v>>>>>v<v^>^>^v^>vv^v^><^<v>^^<>^v^>><>>><vv<<>^v<^vvv<v^vvv^>v<<v>>^>><<^v^^v>^^>^<<<>v^^>><<v>^<v^<^>v>>>^^^<<vvv^>vvv>^><v>^>vvv^^^v^^>v^><v>><>^<v<<vv^^>>^^v>><vv>vvv>^>>>vv^><^<v<<<^^v>v^<v^^>^^<<<>v^vv<vvv>^v>v<^^>vv>v<>>vv<><v>v<^^<<^>>v<v^<>^<<v>><<vv^<<<<v^^^v^^<^<^<>v><^<>>v>v>v>v>v><v>>v<<^>>><v^v<v>>v^><^v^>>>^>^<<>>^^v><^<v^vv^<><>>v^^>v<vvv>v<>><<<<<>><<><v<>vv><^^^><vv<v<<>v^>v>>^^v^v^>vvv<v^<>><<<^>vvv><^^v>v<>v><^<v>v<^<<^<>v>>>>^<>^^^>v<v<<vv><v>>>^<^>v^><vv>^<<v<>><<^<>>>^v>><<>v^^v<^>v^v^>vvvv>vv<<>^^^<v>^<<v>>><<>>>vv^<^><><^^^>^v^<><>^<vv<^vv^^v>^<\n<^>vv>v>^^>^vvvv<<^><^<>>^<v>v>>^^<v><^<>><<<>^vv<>v<v^>>>^<<^<><<>^^vv^^<<><<vvv>v^^>vv^<v<<>>v><^>v^>>^^v<<<<^v<v<<>>v><v^>vv^<vv^>^v>^^>>><>v<><^v><vvvv^v<<>>^^v><>>vv^>v>v^>^>v<><^v>v^^<<>^v^>^>v<><^v<^^vv<>^^^v^>>><<><<<<v^v^><v<v<^^^><><^<<^^^vv<^^<^<v>v<<v^>>v<>>^<vv<^<v><>^<^v^>^v>>>^v>>v^>^^v^>><<v>>^<v>^vvv<v<<<v>^<>vv<^<v<>^<>v^v^>vv^v>><^>><>^^^<<v<vv^<vv>>v<^^^>vv<^^>vv^^^^<<^<v^>v<v>vvv<v<<^^><v<<^>^^<>v>>v><^v^<v>vv^<v<<v>v>vvv^>v<vv>>>>>^^v<<>^><>v^^^>^^>^>^^vvvv^v<v>>^^^v>>^<v<^^v>>><<>^^><<<^>v^^^v><v<v<v^v^><>^>v<v<^^^>>>vv><<^>><v>><<v<<vv><^^^<<^<>v>^v^v><<<<<<>>vv^<<<><<><><<^<^>^<v<^v>>>^>v^>^v>^v^<^>^v>><<<v>v^^vvv><<^>v^^<><v^>><<v><^^>>v<<<<<^>>><><vv>v<<>>^v<><<^>>v<<<^<^>>^>v^>^v<v>^v>>v<^>><<>><>vvv<<>vv^>v>><><<^><vvv>v><^>^<^v><>>v><v><^v^vv><>^^>>>v<^v^<^v>^v><vv<<v<<v><>>><v<vv<>>v^^>>>vv><v<<<<><v^^>>v>^<v^^>^v<<<><v>v>>^^<vv<v^v>><^<^^<>><v>^<^^<><^^^><>^<v^^^<v<^>>^v>vv^^<^v>><<vv><<v>><v>>>^>>><<<v<<><^vvv^<v>^>vvv^v>>v><<>v><<v<vvvvv^>^>><v^>vv^>>^\nvvv^v^><<v<>><><><<<^v>^v^><>^vvv<<^<<v^v<>>v<v^^>>^>v<v>^v<v^v>^<<vvv<^^v<<<<>v^v<<<v<^>><v^vv^vvvv^v><><v<<^>v>v^v^<v<v<^<><^>^vv<^^v<^^>vv<<>^^<>><<<<^^>>>^<^^>vv<>>>^^^^vv^>^v^v^^>^<<<>v^<v>^^^>v<^^<<^<v><^vvv>v>v>v<^>><^<^<>>>^^<<<vv^>>><>>v><>^<>^^<v^><<vv>vv^v<<>^>v><vvv>v^>>v^^^v<<>>^v><^<>^>^<^>^^<vv<>>><v^v^>>>^^>>^v^^^>>^v>v><^^^v<>>vv>>v^^<><^^v>v<^>>v<v^v^v^v^vv^vvv>v^vv>^v>vv<vv<^<<<v^v><<v>v<<^>vvv^^^^>>^>v>^^<>vv<>^^v><v<<^v><><><^<vv^>v^^>>>^^vv>^v>^<>vvv^v<^vv^<<^<^^<>>^<<><vv^>^>^^v^<v><v^>><^^>><<><<<<<<^>^><^v>^v>><v><v<>vvv>^^<^<<>v>>vv<v<><^<<^<>v<v>><><>^v><v<^^^<>>vvv>^^>>>v><v><^^>><<^<v><<^<v<<vv>>^vv<>v>^><><<<<<v>>>v^^v>^<>^<>v^^>>^<>>v^>^<>>>><>><v^v>>v>^<<^v^><<>>^v>><>><>>>><>vv<<>>^>v^v^<vvvvvvv^>v<<<^^<>vvvv^<<><<v^<<vv^^^v^^<<><v>v^^<^^v^^<>^v<>vvv>>^^v^^^<v>v^^vv<^^^<<>^v^>>^^<<^^v^^v<<vv^<<>>>v<>vv<v^v<<>vvv>^<v>v>^v<^^v<>^>^<><<v>v<>v^>v^v>><<><v><>>>>v^<^<^><>^v^<^><<v<^v><>>^v^^^v^><>^v>v<<^v>>^<<v<>v<^<<<<>>^><<<vv<^v^<^>^^><^^vvv^><v<><^^<>^v^>\nvvvv^vv^>>^v^v<^<vvv<>v>v>vv>^>^><^vv><v^v>v<><>v^v^>vvvv<<>v<^^^vv<^v><>^>^>v<>^>^vvv<>^>^<^^v^<><<>^>^v><v>^v>v^<v^<>>^^>^>v^>v>>^^<v><^<^vv>^vv^v^>v><^vv>^>v>^><>v>v^^>>v>^<<v^<vvv>>v<v>v^^<>^v^vv^<^^<v>>>v>>^v>vvv^^v^>v<vvv^<><v>v>v<>^^v^^<vv<>v<vvv>>><><<>>v>^^<^^^^><v>^>v<^<^>v^^>v>^>>^><<<^vv>vv^v^><v^<v>vv>^<>^vvvv^>vv>^>v^>v<<v^^<v^<v>>vvv<<v<>>>v^>^vv>^<v<>>^^v<vv<^>v<>^<<^^><>^^v>^v>>^<v>vv^v<<^^>^<v<><v>vv<><vv<>>v<^^^><<^^>^v<>vv<v>><<<v><<>>vv^>>^vvvv^><<v<vv^v<vv<>v<><v<<><v>vvv>>vv^^^<><^v<><v<^<v<v<^>>vv<><<>^^>><<v><^>vvv^>^vvv<>v^^<<^<vv>>v>^>v>^^><<>v<v^>^<<<<vv<<^^^>^>^>v<>>vv^><v<><<><^><><^^vv>>^<^vv<^^v<><<><>vvvv^^^<>v>>v^<vvv<v<vv><<v^v<v>>^v^<<^>>vvvv^v<<^<^vv<v<v>^v<^<^^>vv<v^^^>>^<^><^^v<v^v^>^^^v^v>^>^><^>>^v<v<^^^v^>>^v>vv>^v<>^v^^^v^v^>v>><^^<^v<<v<^v<>v^<>^<>^v<v^^v<^>v<v>^v<<><<<>^v><<<^>vvvvv^v^^^<<v>>v^>>^^<<v^^>vv^^vvvv>^>v^<<<^<>v><<^>^v^<^>><<<v<vv>vv<<^>^<^^><>>^^v>vvv^<^>^^^^<^v<<>^<>^>>v>^<><><>>^^vv^<<>><^<v><>^v^vvv<<>>^<>^>v<<^><<^>^<^>^<<><\n<<^<^>><<<vv>v<v<^<>>>v^>vv><>>vvvv<<^><<<>v<>v^v^<>v>v<^^<<v<vv^<<<vv>^<>^^vv<><v<<^v^v<^<v" <> ...]
+
```
+
+
```elixir
+
%{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(&elem(&1, 1), &elem(&1, 0))
+
+
walls = MapSet.new(walls)
+
boxes = MapSet.new(boxes)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
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, ...},
+
{...},
+
...
+
])
+
```
+
+
```elixir
+
moves = moves |> String.to_charlist() |> Enum.reject(& &1 not in ~c"^>v<")
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
~c">v>>>^>>v>vv^v^^v^^^<v^vv^vv<<>^v^^^<<<vv<>vv^^>v>v^^><>^<v<v><>>^>^<^^v>v<>^^v<><<^><v>v^v<<^>^>^>^>>vvv>^<<^^^^^><vv>>^>^^>^vv>><v^^v^<<<>^^<<<^^^vv^<^<<<>v<^v<v>^<>v<^>>^v^<>><><<^<>v>^>^>v>>v>vv^><v<v^v>vv>><^^<<>>vv<<^vv>^^vv>>><^v^>>v<<<<v>^<><>^>v^vv>v>><><^vvv>^><<>^<<<vvv^>^vv<<>v^^^>v<>^^vv>vv^<>^<>vvv<vvvv^^^<^vv^<v^<<vv^v<><vvvv^>vv<>><><<v>><^>v<>v<v<v>^v>^<>^v>>><^>>v<<<v^>^v>v>^^>^v<v^v^^<vv^v^><<^^<v^v>>^v>>>>>v<v^>^>^v^>vv^v^><^<v>^^<>^v^>><>>><vv<<>^v<^vvv<v^vvv^>v<<v>>^>><<^v^^v>^^>^<<<>v^^>><<v>^<v^<^>v>>>^^^<<vvv^>vvv>^><v>^>vvv^^^v^^>v^><v>><>^<v<<vv^^>>^^v>><vv>vvv>^>>>vv^><^<v<<<^^v>v^<v^^>^^<<<>v^vv<vvv>^v>v<^^>vv>v<>>vv<><v>v<^^<<^>>v<v^<>^<<v>><<vv^<<<<v^^^v^^<^<^<>v><^<>>v>v>v>v>v><v>>v<<^>>><v^v<v>>v^><^v^>>>^>^<<>>^^v><^<v^vv^<><>>v^^>v<vvv>v<>><<<<<>><<><v<>vv><^^^><vv<v<<>v^>v>>^^v^v^>vvv<v^<>><<<^>vvv><^^v>v<>v><^<v>v<^<<^<>v>>>>^<>^^^>v<v<<vv><v>>>^<^>v^><vv>^<<v<>><<^<>>>^v>><<>v^^v<^>v^v^>vvvv>vv<<>^^^<v>^<<v>>><<>>>vv^<^><><^^^>^v^<><>^<vv<^vv^^v>^<<^>vv>v>^^>^vvvv<<^><^<>>^<v>v>>^^<v><^<>><<<>^vv<>v<v^>>>^<<^<><<>^^vv^^<<><<vvv>v^^>vv^<v<<>>v><^>v^>>^^v<<<<^v<v<<>>v><v^>vv^<vv^>^v>^^>>><>v<><^v><vvvv^v<<>>^^v><>>vv^>v>v^>^>v<><^v>v^^<<>^v^>^>v<><^v<^^vv<>^^^v^>>><<><<<<v^v^><v<v<^^^><><^<<^^^vv<^^<^<v>v<<v^>>v<>>^<vv<^<v><>^<^v^>^v>>>^v>>v^>^^v^>><<v>>^<v>^vvv<v<<<v>^<>vv<^<v<>^<>v^v^>vv^v>><^>><>^^^<<v<vv^<vv>>v<^^^>vv<^^>vv^^^^<<^<v^>v<v>vvv<v<<^^><v<<^>^^<>v>>v><^v^<v>vv^<v<<v>v>vvv^>v<vv>>>>>^^v<<>^><>v^^^>^^>^>^^vvvv^v<v>>^^^v>>^<v<^^v>>><<>^^><<<^>v^^^v><v<v<v^v^><>^>v<v<^^^>>>vv><<^>><v>><<v<<vv><^^^<<^<>v>^v^v><<<<<<>>vv^<<<><<><><<^<^>^<v<^v>>>^>v^>^v>^v^<^>^v>><<<v>v^^vvv><<^>v^^<><v^>><<v><^^>>v<<<<<^>>><><vv>v<<>>^v<><<^>>v<<<^<^>>^>v^>^v<v>^v>>v<^>><<>><>vvv<<>vv^>v>><><<^><vvv>v><^>^<^v><>>v><v><^v^vv><>^^>>>v<^v^<^v>^v><vv<<v<<v><>>><v<vv<>>v^^>>>vv><v<<<<><v^^>>v>^<v^^>^v<<<><v>v>>^^<vv<v^v>><^<^^<>><v>^<^^<><^^^><>^<v^^^<v<^>>^v>vv^^<^v>><<vv><<v>><v>>>^>>><<<v<<><^vvv^<v>^>vvv^v>>v><<>v><<v<vvvvv^>^>><v^>vv^>>^vvv^v^><<v<>><><><<<^v>^v^><>^vvv<<^<<v^v<>>v<v^^>>^>v<v>^v<v^v>^<<vvv<^^v<<<<>v^v<<<v<^>><v^vv^vvvv^v><><v<<^>v>v^v^<v<v<^<><^>^vv<^^v<^^>vv<<>^^<>><<<<^^>>>^<^^>vv<>>>^^^^vv^>^v^v^^>^<<<>v^<v>^^^>v<^^<<^<v><^vvv>v>v>v<^>><^<^<>>>^^<<<vv^>>><>>v><>^<>^^<v^><<vv>vv^v<<>^>v><vvv>v^>>v^^^v<<>>^v><^<>^>^<^>^^<vv<>>><v^v^>>>^^>>^v^^^>>^v>v><^^^v<>>vv>>v^^<><^^v>v<^>>v<v^v^v^v^vv^vvv>v^vv>^v>vv<vv<^<<<v^v><<v>v<<^>vvv^^^^>>^>v>^^<>vv<>^^v><v<<^v><><><^<vv^>v^^>>>^^vv>^v>^<>vvv^v<^vv^<<^<^^<>>^<<><vv^>^>^^v^<v><v^>><^^>><<><<<<<<^>^><^v>^v>><v><v<>vvv>^^<^<<>v>>vv<v<><^<<^<>v<v>><><>^v><v<^^^<>>vvv>^^>>>v><v><^^>><<^<v><<^<v<<vv>>^vv<>v>^><><<<<<v>>>v^^v>^<>^<>v^^>>^<>>v^>^<>>>><>><v^v>>v>^<<^v^><<>>^v>><>><>>>><>vv<<>>^>v^v^<vvvvvvv^>v<<<^^<>vvvv^<<><<v^<<vv^^^v^^<<><v>v^^<^^v^^<>^v<>vvv>>^^v^^^<v>v^^vv<^^^<<>^v^>>^^<<^^v^^v<<vv^<<>>>v<>vv<v^v<<>vvv>^<v>v>^v<^^v<>^>^<><<v>v<>v^>v^v>><<><v><>>>>v^<^<^><>^v^<^><<v<^v><>>^v^^^v^><>^v>v<<^v>>^<<v<>v<^<<<<>>^><<<vv<^v^<^>^^><^^vvv^><v<><^^<>^v^>vvvv^vv^>>^v^v<^<vvv<>v>v>vv>^>^><^vv><v^v>v<><>v^v^>vvvv<<>v<^^^vv<^v><>^>^>v<>^>^vvv<>^>^<^^v^<><<>^>^v><v>^v>v^<v^<>>^^>^>v^>v>>^^<v><^<^vv>^vv^v^>v><^vv>^>v>^><>v>v^^>>v>^<<v^<vvv>>v<v>v^^<>^v^vv^<^^<v>>>v>>^v>vvv^^v^>v<vvv^<><v>v>v<>^^v^^<vv<>v<vvv>>><><<>>v>^^<^^^^><v>^>v<^<^>v^^>v>^>>^><<<^vv>vv^v^><v^<v>vv>^<>^vvvv^>vv>^>v^>v<<v^^<v^<v>>vvv<<v<>>>v^>^vv>^<v<>>^^v<vv<^>v<>^<<^^><>^^v>^v>>^<v>vv^v<<^^>^<v<><v>vv<><vv<>>v<^^^><<^^>^v<>vv<v>><<<v><<>>vv^>>^vvvv^><<v<vv^v<vv<>v<><v<<><v>vvv>>vv^^^<><^v<><v<^<v<v<^>>vv<><<>^^>><<v><^>vvv^>^vvv<>v^^<<^<vv>>v>^>v>^^><<>v<v^>^<<<<vv<<^^^>^>^>v<>>vv^><v<><<><^><><^^vv>>^<^vv<^^v<><<><>vvvv^^^<>v>>v^<vvv<v<vv><<v^v<v>>^v^<<^>>vvvv^v<<^<^vv<v<v>^v<^<^^>vv<v^^^>>^<^><^^v<v^v^>^^^v^v>^>^><^>>^v<v<^^^v^>>^v>vv>^v<>^v^^^v^v^>v>><^^<^v<<v<^v<>v^<>^<>^v<v^^v<^>v<v>^v<<><<<>^v><<<^>vvvvv^v^^^<<v>>v^>>^^<<v^^>vv^^vvvv>^>v^<<<^<>v><<^>^v^<^>><<<v<vv>vv<<^>^<^^><>>^^v>vvv^<^>^^^^<^v<<>^<>^>>v>^<><><>>^^vv^<<>><^<v><>^v^vvv<<>>^<>^>v<<^><<^>^<^>^<<><<<^<^>><<<vv>v<v<^<>>>v^>vv><>>vvvv<<^><<<>v<>v^v^<>v>v<^^<<v<vv^<<<vv>^<>^^vv<><v<<^v^v<^<v>>vv" ++ ...
+
```
+
+
## Part 1
+
+
```elixir
+
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
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:module, Warehouse.A, <<70, 79, 82, 49, 0, 0, 14, ...>>, {:next, 2}}
+
```
+
+
```elixir
+
robot
+
|> Warehouse.A.walk(moves, walls, boxes)
+
|> Enum.map(fn {x, y} -> x + y * 100 end)
+
|> Enum.sum()
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
1406628
+
```
+
+
## Part 2
+
+
```elixir
+
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, & &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
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
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
+
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:module, Warehouse.B, <<70, 79, 82, 49, 0, 0, 20, ...>>, {:next, 2}}
+
```
+
+
<!-- livebook:{"offset":23559,"stamp":{"token":"XCP.GtnzBtRKuk3dCuG1gVPqYVHJwR27FPAQixvDel9XY7YKKtIR-fLOYjYE9q5s_RDyt_V8hQtSWHWE0pTlg7ukiaTmklnlkowdbH-y0AJ21EtpRoXXQ3C48_7vRp_64BdLpHY","version":2}} -->
+303
2024/day16.livemd
···
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 16
+
+
```elixir
+
Mix.install([:kino_aoc, :image])
+
```
+
+
## Setup
+
+
<!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIxNiIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
+
+
```elixir
+
{:ok, puzzle_input} =
+
KinoAOC.download_puzzle("2024", "16", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:ok,
+
"#############################################################################################################################################\n#.....#.......#.............#.........#.......................#.......#...#...............#.....#.#.................................#.#....E#\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#.#.#########.#######.#.#.#.###.###.###.#.###########.###.#.###.#.###.#.###.#####.#.#########.#.#.###.#.#.###.#.#.#.#.#." <> ...}
+
```
+
+
```elixir
+
%{?# => walls, ?S => [start], ?E => [finish]} =
+
puzzle_input
+
|> String.trim()
+
|> String.split("\n", trim: true)
+
|> Enum.with_index()
+
|> Enum.flat_map(fn {row, y} ->
+
row
+
|> String.trim()
+
|> String.to_charlist()
+
|> Enum.with_index()
+
|> Enum.map(fn {char, x} ->
+
{{x, y}, char}
+
end)
+
end)
+
|> Enum.group_by(&elem(&1, 1), &elem(&1, 0))
+
+
walls = MapSet.new(walls)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
MapSet.new([
+
{76, 13},
+
{112, 138},
+
{38, 2},
+
{124, 56},
+
{83, 76},
+
{140, 11},
+
{100, 134},
+
{75, 140},
+
{103, 106},
+
{68, 134},
+
{124, 60},
+
{35, 30},
+
{2, 132},
+
{8, 50},
+
{78, 98},
+
{101, 62},
+
{98, 136},
+
{95, 56},
+
{74, 12},
+
{102, 74},
+
{22, 38},
+
{14, 86},
+
{12, 135},
+
{86, 10},
+
{29, 26},
+
{4, 81},
+
{31, 42},
+
{9, 34},
+
{137, 16},
+
{86, 138},
+
{90, 0},
+
{14, 122},
+
{120, 42},
+
{102, 57},
+
{84, 102},
+
{138, 124},
+
{0, 101},
+
{116, 96},
+
{54, 138},
+
{18, 134},
+
{82, 60},
+
{15, 92},
+
{58, 58},
+
{78, 75},
+
{75, 0},
+
{16, 73},
+
{76, 2},
+
{58, 84},
+
{138, ...},
+
{...},
+
...
+
])
+
```
+
+
```elixir
+
{_, {w, h}} = Enum.min_max(walls)
+
+
w = w + 1
+
h = h + 1
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
141
+
```
+
+
```elixir
+
put_in(%{}, [Access.key(:a, %{}), :b], 10)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
%{a: %{b: 10}}
+
```
+
+
```elixir
+
defmodule Race.B do
+
@turns ~w'^ > v <'a
+
+
defguardp score(elements, pos, dir) when :erlang.map_get({pos, dir}, elements).score
+
+
def search_paths(start, finish, dir \\ :>, walls) when dir in @turns do
+
result = do_search([{0, [{start, dir}]}], walls, %{})
+
+
%{paths: visited, score: score} = result[{finish, :>}]
+
+
all = get_all(visited, result)
+
+
{score, all}
+
end
+
+
def get_all(path, seen) do
+
Enum.reduce(path, MapSet.new(), fn p, acc ->
+
path = MapSet.new(seen[p].paths, fn {p, _} -> p end)
+
MapSet.union(acc, path)
+
end)
+
end
+
+
def do_search([], _, visited), do: visited
+
+
def do_search([{cost, [{curr, dir} | _] = path} | rest], walls, visited)
+
when cost == score(visited, curr, dir) do
+
visited = Map.update!(visited, {curr, dir}, &%{&1 | paths: path})
+
+
do_search(rest, walls, visited)
+
end
+
+
def do_search([{cost, [{curr, prev} | _] = path} | rest], walls, visited)
+
when not is_map_key(visited, {curr, prev})
+
when cost < score(visited, curr, prev) do
+
visited = Map.put(visited, {curr, prev}, %{score: cost, paths: path})
+
+
@turns
+
|> Enum.map(fn dir -> {cost + cost(prev, dir), [{step(curr, dir), dir} | path]} end)
+
|> Enum.reject(fn {_cost, [{pos, _} | _]} -> pos in walls end)
+
|> sort_merge(rest)
+
|> do_search(walls, visited)
+
end
+
+
def do_search([{_, [_curr | _]} | rest], walls, visited),
+
do: do_search(rest, walls, visited)
+
+
# Going straight is cheap and turning is costly
+
defp cost(a, a), do: 1
+
defp cost(_, _), do: 1001
+
+
defp step({x, y}, :^), do: {x, y - 1}
+
defp step({x, y}, :>), do: {x + 1, y}
+
defp step({x, y}, :v), do: {x, y + 1}
+
defp step({x, y}, :<), do: {x - 1, y}
+
+
defp sort_merge([], bs), do: bs
+
defp sort_merge(as, []), do: as
+
+
defp sort_merge([a | as], [b | bs]) do
+
if a < b do
+
[a | sort_merge(as, [b | bs])]
+
else
+
[b | sort_merge([a | as], bs)]
+
end
+
end
+
end
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:module, Race.B, <<70, 79, 82, 49, 0, 0, 23, ...>>, {:sort_merge, 2}}
+
```
+
+
```elixir
+
{score, paths} = Race.B.search_paths(start, finish, walls)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{134588,
+
MapSet.new([
+
{77, 129},
+
{17, 138},
+
{17, 137},
+
{37, 139},
+
{19, 137},
+
{100, 131},
+
{139, 68},
+
{14, 139},
+
{79, 128},
+
{19, 138},
+
{50, 137},
+
{139, 67},
+
{137, 104},
+
{137, 117},
+
{131, 49},
+
{107, 125},
+
{3, 127},
+
{135, 64},
+
{4, 131},
+
{21, 134},
+
{63, 127},
+
{101, 124},
+
{5, 139},
+
{125, 14},
+
{129, 48},
+
{139, 70},
+
{21, 119},
+
{17, 129},
+
{137, 120},
+
{17, 136},
+
{131, 120},
+
{32, 139},
+
{133, 21},
+
{102, 123},
+
{12, 111},
+
{123, 19},
+
{112, 127},
+
{73, 129},
+
{7, 116},
+
{127, 22},
+
{7, 137},
+
{9, 131},
+
{24, 133},
+
{137, 95},
+
{8, 133},
+
{134, 7},
+
{129, ...},
+
{...},
+
...
+
])}
+
```
+
+
## Part 1
+
+
```elixir
+
score
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
134588
+
```
+
+
```elixir
+
Image.new!(w, h)
+
|> Image.mutate(fn img ->
+
for {x, y} <- walls do
+
Image.Draw.point(img, x, y, color: [128, 0, 0])
+
end
+
+
for {x, y} <- paths do
+
Image.Draw.point(img, x, y, color: [0, 255, 0])
+
end
+
+
img
+
end)
+
|> elem(1)
+
|> Image.resize!(6, interpolate: :nearest)
+
```
+
+
## Part 2
+
+
```elixir
+
MapSet.size(paths)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
625
+
```
+
+
<!-- livebook:{"offset":9337,"stamp":{"token":"XCP.AVI7h-Nq9jZKx9YmL5qYerJkeKKqddhzKrKUkab-HwNDUM8nQItD1O_rd2ROsJxc96gwIzwrMAixlIdLeZAgOVhtCs22LZM44Wl1VwcpYbg3RNCdgwIjqGheO5YrCGrEGJc","version":2}} -->
+206
2024/day17.livemd
···
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 17
+
+
```elixir
+
Mix.install([:kino_aoc])
+
```
+
+
## Section
+
+
<!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIxNyIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
+
+
```elixir
+
{:ok, puzzle_input} =
+
KinoAOC.download_puzzle("2024", "17", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:ok,
+
"Register A: 66245665\nRegister B: 0\nRegister C: 0\n\nProgram: 2,4,1,7,7,5,1,7,4,6,0,3,5,5,3,0"}
+
```
+
+
```elixir
+
defmodule Computer do
+
@instructions ~w[adv bxl bst jnz bxc out bdv cdv]a
+
|> Enum.with_index()
+
|> Map.new(fn {name, ins} -> {ins, name} end)
+
+
def load(opcodes) do
+
opcodes
+
|> Enum.chunk_every(2)
+
|> Enum.map(fn [opcode, op] ->
+
{@instructions[opcode], op}
+
end)
+
|> List.to_tuple()
+
end
+
+
def process(program, reg) do
+
reg = Map.merge(%{a: 0, b: 0, c: 0}, Map.new(reg))
+
do_process(program, 0, reg, [])
+
end
+
+
defp do_process(program, idx, _reg, out) when idx >= tuple_size(program) do
+
Enum.reverse(out)
+
end
+
+
defp do_process(program, idx, reg, out) do
+
ins = elem(program, idx)
+
+
case compute(ins, reg) do
+
new_reg when is_map(new_reg) ->
+
do_process(program, idx + 1, new_reg, out)
+
+
{:out, op} ->
+
do_process(program, idx + 1, reg, [op | out])
+
+
{:jump, op} ->
+
do_process(program, op, reg, out)
+
end
+
end
+
+
def compute({:adv, op}, reg),
+
do: %{reg | a: div(reg.a, 2 ** combo(op, reg))}
+
+
def compute({:bdv, op}, reg),
+
do: %{reg | b: div(reg.a, 2 ** combo(op, reg))}
+
+
def compute({:cdv, op}, reg),
+
do: %{reg | c: div(reg.a, 2 ** combo(op, reg))}
+
+
def compute({:bxl, op}, reg),
+
do: %{reg | b: Bitwise.bxor(reg.b, op)}
+
+
def compute({:bxc, _op}, reg),
+
do: %{reg | b: Bitwise.bxor(reg.b, reg.c)}
+
+
def compute({:bst, op}, reg),
+
do: %{reg | b: Bitwise.band(combo(op, reg), 0b111)}
+
+
def compute({:out, op}, reg),
+
do: {:out, Bitwise.band(combo(op, reg), 0b111)}
+
+
def compute({:jnz, op}, reg) do
+
if reg.a != 0 do
+
{:jump, op}
+
else
+
reg
+
end
+
end
+
+
defp combo(v, _) when v in 0..3, do: v
+
defp combo(4, %{a: a}), do: a
+
defp combo(5, %{b: b}), do: b
+
defp combo(6, %{c: c}), do: c
+
end
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:module, Computer, <<70, 79, 82, 49, 0, 0, 21, ...>>, {:combo, 2}}
+
```
+
+
```elixir
+
[
+
"Register A: " <> a,
+
"Register B: " <> b,
+
"Register C: " <> c,
+
"Program: " <> raw_code
+
] = String.split(puzzle_input, "\n", trim: true)
+
+
reg = %{
+
a: String.to_integer(a),
+
b: String.to_integer(b),
+
c: String.to_integer(c)
+
} |> dbg()
+
+
code =
+
raw_code
+
|> String.split(",")
+
|> Enum.map(&String.to_integer/1)
+
+
program = Computer.load(code)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
%{a: 66245665, b: 0, c: 0}
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{{:bst, 4}, {:bxl, 7}, {:cdv, 5}, {:bxl, 7}, {:bxc, 6}, {:adv, 3}, {:out, 5}, {:jnz, 0}}
+
```
+
+
## Part 1
+
+
```elixir
+
out = Computer.process(program, reg)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
[1, 4, 6, 1, 6, 4, 3, 0, 3]
+
```
+
+
```elixir
+
IO.puts(Enum.join(out, ","))
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
1,4,6,1,6,4,3,0,3
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
:ok
+
```
+
+
## Part 2
+
+
```elixir
+
defmodule Quine do
+
def find(program, target) do
+
do_find(program, Enum.reverse(target), Enum.to_list(0..7))
+
end
+
+
def do_find(_program, [], out), do: out
+
+
def do_find(program, [n | rest], out) do
+
potential =
+
for a <- out,
+
i <- 0..7,
+
hd(Computer.process(program, a: a * 8 + i)) == n,
+
do: a * 8 + i
+
+
do_find(program, rest, potential)
+
end
+
end
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:module, Quine, <<70, 79, 82, 49, 0, 0, 10, ...>>, {:do_find, 3}}
+
```
+
+
```elixir
+
Quine.find(program, code) |> Enum.min()
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
265061364597659
+
```
+
+
<!-- livebook:{"offset":4021,"stamp":{"token":"XCP.PwUWTErrjClVJj6ZS87ZLrfbzleELwxqD__HBvfB1y_Yc633Wj72_Jigo2Z3T7V2ONi1nVguQ_AE_NSyLCF5sjSmWldUKuW294o_wsQqiM_gKhXOjSLzJOnslN9iIEFIEww","version":2}} -->
+194
2024/day18.livemd
···
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 18
+
+
```elixir
+
Mix.install([:kino_aoc, :image])
+
```
+
+
## Section
+
+
<!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIxOCIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
+
+
```elixir
+
{:ok, puzzle_input} =
+
KinoAOC.download_puzzle("2024", "18", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:ok,
+
"21,9\n69,53\n31,24\n2,9\n50,53\n2,5\n3,44\n69,49\n25,26\n50,31\n68,41\n54,67\n19,8\n11,9\n9,29\n1,31\n13,12\n28,5\n69,41\n51,66\n53,43\n65,35\n40,67\n43,13\n21,34\n49,3\n65,61\n25,9\n39,21\n59,37\n11,24\n9,30\n63,62\n41,69\n6,29\n68,47\n45,1\n9,1\n11,14\n59,19\n67,54\n12,5\n41,44\n59,45\n3,28\n57,42\n7,25\n43,11\n31,19\n9,6\n53,60\n29,8\n53,67\n17,1\n11,17\n31,3\n55,35\n2,21\n67,61\n37,5\n6,1\n51,24\n39,1\n31,1\n69,58\n61,19\n49,63\n40,21\n28,25\n59,59\n66,69\n30,1\n7,5\n53,49\n4,17\n39,23\n23,20\n62,67\n51,36\n55,39\n41,3\n57,30\n18,7\n6,37\n29,25\n55,48\n37,16\n65,69\n21,5\n43,48\n3,11\n3,9\n63,39\n23,23\n43,67\n47,3\n69,47\n67,53\n65,24\n67,52\n35,20\n46,45\n57,26\n15,32\n35,68\n15,16\n41,1\n63,29\n15,3\n15,18\n51,50\n60,43\n50,1\n35,12\n41,10\n58,39\n27,18\n50,69\n55,40\n2,3\n51,47\n1,11\n16,9\n23,9\n19,7\n29,12\n37,3\n1,15\n11,1\n25,11\n65,56\n37,70\n60,41\n48,69\n62,29\n53,38\n12,35\n67,42\n49,67\n31,5\n39,7\n65,43\n5,25\n23,24\n43,68\n11,11\n9,32\n62,39\n69,39\n51,46\n38,21\n67,37\n5,26\n62,19\n27,21\n48,51\n55,62\n11,33\n25,4\n13,20\n61,58\n62,55\n41,66\n11,40\n16,7\n9,17\n67,65\n1,1\n9,33\n7,35\n1,3\n11,4\n29,21\n47,47\n61,67\n41,70\n42,65\n55,47\n54,49\n36,13\n61,36\n18,23\n26,23\n45,5\n9,18\n61,27\n36,21\n59,32\n4,9\n6,35\n51,23\n1,17\n12,11\n65,67\n41,65\n37,65\n1,24\n21,8\n59,28\n17,14\n63,68\n20,19\n17,10\n63,69\n57,44\n55,56\n45,64\n25,27\n27,4\n22,23\n5,13\n19,14\n47,46\n49,4\n21,15\n63,58\n60,31\n25,28\n6,3\n61,38\n33,5\n58,37\n11,32\n21,7\n44,61\n55,45\n55,37\n35,22\n10,15\n36,5\n19,11\n59,31\n33,19\n30,5\n69,69\n69,63\n57,69\n5,33\n60,27\n29,7\n57,43\n61,61\n3,26\n13,33\n57,59\n66,39\n63,27\n33,11\n51,1\n52,67\n5,29\n35,3\n17,2\n9,31\n37,24\n61,23\n9,5\n68,35\n21,28\n2,25\n51,48\n68,49\n4,19\n43,66\n7,34\n13,15\n36,1\n42,63\n13,0\n23,7\n48,47\n56,31\n55,43\n47,45\n18,15\n56,45\n61,64\n48,45\n69,65\n40,11\n51,68\n51,51\n53,46\n3,30\n49,62\n4,13\n17,27\n38,69\n41,0\n5,23\n65,32\n9,35\n55,21\n65,55\n51,39\n67,51\n5,9\n39,5\n58,49\n21,17\n63,41\n21,18\n57,65\n53,51\n2,13\n53,0\n53,6\n27,17\n55,59\n61,42\n27,7\n25,25\n39,13\n62,53\n51,44\n2,27\n19,17\n58,65\n8,1\n30,23\n14,5\n33,3\n43,65\n18,27\n35,7\n11,35\n12,29\n57,68\n59,63\n44,19\n36,25\n68,37\n15,19\n53,39\n62,69\n35,4\n61,55\n59,43\n23,17\n69,45\n18,5\n50,59\n39,6\n69,32\n17,5\n11,8\n21,2\n39,4\n64,65\n33,2\n17,22\n33,50\n25,24\n44,51\n31,7\n11,38\n11,25\n63,59\n25,21\n42,7\n8,11\n33,9\n45,63\n62,63\n33,4\n66,59\n61,29\n5,27\n59,27\n55,20\n38,9\n8,7\n51,3\n23,1\n53,65\n69,55\n1,34\n70,49\n61,57\n22,9\n17,26\n17,12\n61,69\n49,43\n9,28\n33,26\n15,35\n13,34\n55,27\n68,45\n45,61\n59,47\n13,29\n59,33\n65,53\n10,1\n35,21\n13,27\n28,1\n23,10\n61,37\n69,57\n23,21\n5,28\n57,48\n41,21\n11,13\n20,11\n1,21\n61,66\n66,47\n63,26\n5,15\n3,20\n17,4\n43,5\n16,29\n63,44\n63,55\n55,69\n5,22\n37,11\n50,39\n59,39\n25,16\n48,1\n43,60\n13,6\n49,37\n3,32\n57,23\n46,69\n2,35\n37,1\n53,27\n31,22\n63,36\n46,43\n68,57\n45,67\n32,9\n48,65\n15,15\n8,29\n13,1\n55,41\n65,65\n13,31\n49,69\n19,6\n29,19\n32,23\n49,41\n15,24\n65,22\n15,33\n6,21\n7,9\n69,64\n63,23\n5,21\n15,1\n44,1\n11,27\n63,34\n15,13\n39,9\n63,20\n58,29\n28,21\n7,37\n39,65\n41,16\n21,6\n49,47\n47,61\n50,63\n23,15\n68,67\n64,57\n19,13\n69,61\n1,22\n27,3\n28,13\n19,31\n23,2\n3,31\n25,6\n61,47\n51,63\n59,64\n27,2\n7,33\n63,63\n65,42\n5,12\n12,15\n27,9\n15,7\n6,17\n17,17\n15,2\n59,61\n63,47\n57,33\n13,17\n47,67\n11,26\n20,3\n13,7\n17,33\n10,5\n57,32\n58,53\n7,18\n66,65\n6,5\n11,5\n41,9\n21,21\n69,43\n11,20\n41,14\n38,3\n67,69\n15,17\n45,58\n51,61\n54,23\n49,39\n59,29\n53,63\n45,69\n16,1\n55,51\n21,13\n56,47\n63,40\n63,37\n37,19\n43,3\n7,17\n27,5\n14,25\n17,3\n44,69\n31,8\n14,9\n14,7\n63,45\n4,1\n49,34\n19,44\n46,53\n38,17\n33,0\n50,55\n27,25\n63,21\n19,12\n35,10\n54,3\n65,50\n47,62\n38,65\n61,39\n33,1\n65,52\n5,5\n0,3\n63,33\n30,27\n29,27\n29,1\n48,67\n33,23\n46,5\n60,35\n39,14\n59,46\n51,49\n64,21\n69,60\n3,3\n59,58\n9,36\n9,37\n48,41\n23,5\n7,3\n61,65\n61,22\n3,15\n4,37\n43,20\n66,45\n69,66\n43,12\n54,43\n52,49\n15,23\n33,21\n36,67\n61,24\n5,7\n37,7\n60,55\n53,70\n52,1\n21,33\n53,69\n67,43\n61,34\n6,31\n55,55\n59,40\n16,17\n65,25\n24,29\n59,21\n66,63\n61,41\n17,24\n0,15\n17,19\n1,13\n23,3\n49,45\n39,2\n59,49\n31,25\n65,40\n7,7\n70,43\n57,63\n65,54\n18,1\n41,15\n25,19\n33,18\n5,24\n13,3\n64,37\n43,7\n31,9\n30,11\n56,63\n65,34\n67,39\n17,18\n65,37\n49,56\n59,25\n7,11\n65,38\n37,18\n5,3\n21,22\n47,69\n19,9\n70,39\n15,14\n40,3\n5,31\n19,21\n55,34\n67,49\n45,11\n17,23\n41,5\n33,6\n37,10\n55,2\n17,9\n57,39\n5,1\n9,10\n17,7\n60,23\n55,68\n5,11\n63,67\n59,65\n7,19\n51,56\n26,1\n30,3\n15,20\n19,15\n3,21\n59,51\n11,7\n61,26\n19,23\n22,11\n25,8\n18,17\n27,26\n17,29\n7,13\n65,33\n44,5\n22,13\n56,65\n24,19\n25,17\n55,66\n65,39\n32,19\n3,19\n9,15\n54,63\n55,23\n61,59\n21,11\n46,39\n57,40\n65,19\n65,59\n65,48\n64,47\n32,21\n1,5\n15,11\n65,23\n4,2" <> ...}
+
```
+
+
```elixir
+
bytes =
+
puzzle_input
+
|> String.split("\n", trim: true)
+
|> Enum.map(fn row ->
+
[x, y] = String.split(row, ",")
+
+
{String.to_integer(x), String.to_integer(y)}
+
end)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
[
+
{21, 9},
+
{69, 53},
+
{31, 24},
+
{2, 9},
+
{50, 53},
+
{2, 5},
+
{3, 44},
+
{69, 49},
+
{25, 26},
+
{50, 31},
+
{68, 41},
+
{54, 67},
+
{19, 8},
+
{11, 9},
+
{9, 29},
+
{1, 31},
+
{13, 12},
+
{28, 5},
+
{69, 41},
+
{51, 66},
+
{53, 43},
+
{65, 35},
+
{40, 67},
+
{43, 13},
+
{21, 34},
+
{49, 3},
+
{65, 61},
+
{25, 9},
+
{39, 21},
+
{59, 37},
+
{11, 24},
+
{9, 30},
+
{63, 62},
+
{41, 69},
+
{6, 29},
+
{68, 47},
+
{45, 1},
+
{9, 1},
+
{11, 14},
+
{59, 19},
+
{67, 54},
+
{12, 5},
+
{41, 44},
+
{59, 45},
+
{3, 28},
+
{57, 42},
+
{7, 25},
+
{43, 11},
+
{31, ...},
+
{...},
+
...
+
]
+
```
+
+
```elixir
+
Image.new!(71, 71, color: :forestgreen)
+
|> Image.mutate(fn img ->
+
for x <- 0..70, y <- 0..70, {x, y} in Enum.take(bytes, 1024) do
+
Image.Draw.point(img, x, y, color: :firebrick)
+
end
+
+
img
+
end)
+
|> elem(1)
+
|> Image.resize!(4, interpolate: :nearest)
+
```
+
+
```elixir
+
defmodule Memory do
+
@d [{-1, 0}, {1, 0}, {0, -1}, {0, 1}]
+
def find_path(from, to, bytes), do: do_find([{0, from}], to, MapSet.new(bytes), %{})
+
+
def do_find([], _, _, _), do: :none
+
+
def do_find([{dist, to} | _], to, _, _visited), do: dist
+
+
def do_find([{dist, {x, y} = p} | rest], {w, h} = to, bytes, visited)
+
when not is_map_key(visited, p)
+
when dist < :erlang.map_get(p, visited)
+
do
+
visited = Map.put(visited, p, dist)
+
+
next =
+
for {dx, dy} <- @d,
+
(x + dx) in 0..w,
+
(y + dy) in 0..h,
+
p = {x + dx, y + dy},
+
p not in bytes,
+
not is_map_key(visited, p),
+
do: {dist + 1, p}
+
+
next
+
|> Enum.concat(rest)
+
|> Enum.sort()
+
|> do_find(to, bytes, visited)
+
end
+
+
def do_find([_ | rest], to, bytes, visited), do: do_find(rest, to, bytes, visited)
+
end
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:module, Memory, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:do_find, 4}}
+
```
+
+
## Part 1
+
+
## Part 1
+
+
```elixir
+
Memory.find_path({0, 0}, {70, 70}, Enum.take(bytes, 1024))
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
250
+
```
+
+
## Part 2
+
+
```elixir
+
{x, y} =
+
bytes
+
|> Enum.reverse()
+
|> Stream.unfold(fn
+
[] -> nil
+
[_ | rest] = curr -> {curr, rest}
+
end)
+
|> Enum.find_value(fn [pos | fallen] ->
+
path = Memory.find_path({0, 0}, {70, 70}, fallen)
+
+
if path != :none do
+
pos
+
end
+
end)
+
+
IO.puts("#{x},#{y}")
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
56,8
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
:ok
+
```
+
+
<!-- livebook:{"offset":7984,"stamp":{"token":"XCP.CPT4l_BNbZGxGbR_fK_dYfzmCSPzRQfyiJPfaGWsNChhlNQI36bgn8XXEOmsc56qlDi2H-j-H4aYpxwTYXzlirEAyckZaTUuHdujjNaTLq1pQEjB3uTTMbVmMkdf1KvN3g0","version":2}} -->
+126
2024/day19.livemd
···
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 19
+
+
```elixir
+
Mix.install([:kino_aoc])
+
```
+
+
## Section
+
+
<!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIxOSIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
+
+
```elixir
+
{:ok, puzzle_input} =
+
KinoAOC.download_puzzle("2024", "19", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:ok,
+
"rrbb, rgrb, rbbwbw, ruw, grwb, wbg, rrggu, wugbb, gwr, rrgu, wbbb, bwrgugb, rgww, brrw, gwwg, brgbb, ubbbu, rbgruw, bwub, rru, grbu, grw, bwrbr, wrwbwu, bgbr, urrb, bbb, guggb, gwuwuw, ubu, wbr, bb, ubwwrb, bruuwu, buw, wrr, gbgrr, ggw, ru, wub, uub, gbrw, uwrwrb, uwuu, wbbu, gwu, brrr, grggur, wugrbrw, rwuurgg, wrbg, wuugrgw, brr, wrgwu, rwwuur, wgug, guu, brru, bgr, buwruw, bbg, bw, brwuwbb, buwbrgrb, wrwuw, ubb, rgu, wru, ugw, rruubrr, bwur, rrb, uwg, wwbbuwu, rbw, uwrgbr, ubuw, uurwr, uggw, uuguur, guuww, bbrgw, ubuwbuu, buwgg, gru, uuu, u, wgguw, bruu, bu, gwurrw, rbgwur, gubg, ubgrubw, buwrgw, uu, rwgw, rrw, wgru, gwrb, bgguu, gwugwu, urrbg, ruwwb, wuw, wwgg, wwbbu, gggb, rgrruwrw, uugr, rwb, rggw, gbr, guuurru, wurubggw, gww, wuugb, rbbww, urwgb, wrruurr, guuurgg, bwbgbg, bubwb, ggrwwg, gugr, uwrrr, guurbu, uruw, gbguruu, grb, bwr, wrubggr, rbu, wgwgru, buuww, gub, wu, uw, rrbrb, ur, wrgbb, gbbu, wgw, ggwbgwb, wb, urwr, uggwbwu, wwwg, rbru, bwbw, brb, wbugw, r, gbb, rw, bru, wbbwbr, gwww, wgrr, rugg, bgrbrub, w, gwwb, wrwgu, wwgb, uwgbgwwb, wrrwb, ubw, rr, gbbuug, bbr, wugb, rbuww, uur, wgur, ugg, wwu, wwrww, uuwur, rwbbww, gbu, bgbuur, rrbugguw, ugrgwg, wurruu, rrrgww, ggbbgbb, bgbb, brrb, rwwr, brwwr, ubrbru, uburwwb, ggwu, rwbgrbu, bbwuwbr, urwggbwr, bbrgu, wbbuww, rbwwuwr, gu, brbb, wbwgu, ugbrrguw, urbu, gbgbbrub, gbuuuww, rww, gwwgwwg, buwu, bur, uubrw, rur, rgurr, rwbgrg, urr, wugw, wuur, wuub, wbgb, bgb, uubrbur, rrbugbu, ugru, guwr, uwu, uru, wbw, wugrwgb, ggwg, guw, ubbbg, grbuwg, gw, wgb, bbrbwgub, gr, rbruu, urwwu, gbuwbw, bug, rgrgb, uwr, wrw, urb, wgbw, rbbgr, rwww, wbubur, buubw, ruwgwbug, wwwgggub, uuwrwbww, burr, rubg, wgub, bww, urbuubb, bubugrb, rgwbbw, rb, ggu, gwg, rgw, ruwggbg, wrrwbg, gur, wwbgugb, ruu, rrgg, rwrr, uwb, bwbbwbg, rbgg, rwgwg, rrgrwg, gb, bgbg, urubwugb, ruww, grbbg, gwb, bugrr, wgwr, wuug, b, gbwgr, uugw, wwr, wuu, ggr, bbwb, ubbbwrg, wugbw, gguuw, bbw, ugr, wbbrrbu, grbub, ubuwuw, bwgw, bggw, bwu, ub, bwubw, rgru, brg, uruwr, rug, wrwwuubg, brw, wggurb, br, wgr, gug, wrww, gg, uuw, bguwbru, rrrw, uubgb, gbww, buu, rbbuw, bgru, ubbwr, bg, gbgrww, wrg, ugubw, rgrg, bwbbgw, ggubrwbg, uurgwg, gbw, ww, wr, wbgu, bbu, brrwb, wug, uurug, rgb, gwbwbgg, uuubg, ugub, bruw, rub, rgggrr, ruubrwuw, brguru, wbrbg, rrwr, bgrwbbr, ugu, grwbb, rgg, wwg, rgbuwr, wuwur, bbgub, ubg, rrg, wrur, bggbr, wgg, bbwbbru, bwwbrgu, rugrr, rgwbu, ugubwbgu, wwb, ggg, bwwu, gwuguu, rrwgwg, uuwu, rrug, bgwruw, brrgrb, rurg, bugb, grwbg, rwr, urug, rwg, bgg, gbggr, rrr, gbbrw, wgu, bwbg, bbgurggg, wuwguw, wwwuru, grg, grggbw, rubu, burw, grr, bgbbw, wgrbgg, rwrww, gwurgr, bruww, bub, wbu, rbb, uwgbb, rgr, ugb, buubb, wg, wwwgr, bgw, wbwr, wuwruu, wrgrrrw, rbr, wuwwr, wrwb, ggwgwbrw, urw, uwrubb, wuwg, wguu, ugwwuw, ggb, rrggr, wrb, urwgub, bgwwrw, rwu, wurug, gbgu, brrwbb, wwbub, uwrgw, bwb, ubr, uww, gbg, wgrugwbb, bwg, wbb, bbwwgr, www\n\nbgrwwwbuugwrruurrwgbgrbwrrruurgbuwbgbwuuruubwuubruwgubw\nugguwugrwrgwruwguuwurubggwgwbrwwwubburwrburg\nrbbbgwgbbbrrrubguwggubwburbrrwgbbuwgbwwuwrbwugurbbwuubruu\nwuuuwbwuwuwgbugwggwwuwurrgwubbugbbuuubbrwbgbubr\nubbrubwuurgbuwgguubgbrguwbguuwbwruguubwbbgguwrrgwwbubwb\nrbbwuwrrrgwrwwbwgwrruubggrrggbbgwuwbrgubgwwrbwwbggwwrwrwgb\nbgggbruguuguwwwurruwgubrwrruubgbrbwwwgrrgurb\ngubugrguurwgwwubrwguggbgbbuubbubuwurgbgugrubgrgggruugw\ngwrggrbrrrbwwrrggwrwggrwuguubgggrrwwrggubruwrrgbubg\nbgubggrrbuwwwggbwbrbguwuwwbburgururuguwuwgbguuwwwub\nuuggggggurgrgugugrwbrbrwururwurburrurggwgwbrwrwwwuuugwu\nuuubwrurwwrbbgrbrrbuwbrbwrurgrrwwwgugugrbugwu\nwbbbwrgbwrbgggwgbbwbbwrwbbbwwbbwbgbwuwubbrrggurbugwrgwbuug\nuruwrwugbbwruugrguuwrrbbguwwrrrruubrwgwrruug\nbguurwugrrgurubbuwbrgrbwggrrgrwguwgrwubgbubbw\nwwgubbbbgggrgrwwwuwwwbbbbbbrwwwguggrwurgwbguwgwubww\nwgbrwgbbgwuuwbwwuwwrruruwururwbwbguuwgbrgw\nwbrgwrrurwuubrruruwwbgwrgwrbbrwrbbbrwwbwwrgwbr\nggwgwrrwwruubruwgbwwuwrbwbgurubwugbbwurwbwrbuggubwwww\nbuurbrbwrgbgbgwgwbruwubbbgwgguruggrrwwgwgwuruwggrbbbbbugw\nbubgwugwubwwwgrurgurbubwbguurrwbubuubggbgbrbuwgrwbbgbuwr\ngggbbwgugrguguwubrbwbrgwwbubwuwwgbwrbrgbuugwrrb\nbgguuuwwbrubgrubwrwugbbwwrruwrgrrubwwuubgwrwwrgrgbgbg\nw" <> ...}
+
```
+
+
```elixir
+
[towels | patterns] = String.split(puzzle_input, "\n", trim: true)
+
+
towels =
+
towels
+
|> String.split(", ")
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
["rrbb", "rgrb", "rbbwbw", "ruw", "grwb", "wbg", "rrggu", "wugbb", "gwr", "rrgu", "wbbb", "bwrgugb",
+
"rgww", "brrw", "gwwg", "brgbb", "ubbbu", "rbgruw", "bwub", "rru", "grbu", "grw", "bwrbr",
+
"wrwbwu", "bgbr", "urrb", "bbb", "guggb", "gwuwuw", "ubu", "wbr", "bb", "ubwwrb", "bruuwu", "buw",
+
"wrr", "gbgrr", "ggw", "ru", "wub", "uub", "gbrw", "uwrwrb", "uwuu", "wbbu", "gwu", "brrr",
+
"grggur", "wugrbrw", "rwuurgg", ...]
+
```
+
+
```elixir
+
defmodule Towels do
+
def count(target, towels) do
+
possible =
+
towels
+
|> Enum.filter(&String.contains?(target, &1))
+
|> Enum.sort()
+
+
do_count([{target, 1}], possible)
+
end
+
+
defp do_count([], _), do: 0
+
defp do_count([{"", count} | _], _), do: count
+
+
defp do_count([{target, score} | rest], towels) do
+
towels
+
|> Enum.reduce(rest, fn h, acc ->
+
case target do
+
^h <> rest -> insert(acc, {rest, score})
+
_ -> acc
+
end
+
end)
+
|> do_count(towels)
+
end
+
+
defp insert([{longest, _} = top | t], {text, _} = new)
+
when byte_size(text) < byte_size(longest) do
+
[top | insert(t, new)]
+
end
+
+
defp insert([{same, count} | t], {same, add}),
+
do: [{same, count + add} | t]
+
+
defp insert(t, new), do: [new | t]
+
end
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:module, Towels, <<70, 79, 82, 49, 0, 0, 12, ...>>, {:insert, 2}}
+
```
+
+
```elixir
+
ways = Enum.map(patterns, &Towels.count(&1, towels))
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
[6620974293119, 0, 35074418436970, 51307147748, 1695253946038, 12806406135744, 4413048272,
+
52744440529, 21533960420, 189633269638, 308662314336, 28930988196, 0, 0, 2335754782, 105920229640,
+
6464319032, 87075196587, 3720984622862, 2177845982468, 5546717284590, 8535586138, 834112091460,
+
6647844832, 21252082644, 5923960105816, 22344301329, 0, 0, 582455705324, 5162034941182,
+
368835846080, 30797645913, 0, 5315701730, 1953742172864, 910841596, 5512526952, 673582370688,
+
2029241325402, 13227054560, 81761616492, 0, 184404641300, 19196318323832, 773246829645,
+
97032877104, 0, 0, 0, ...]
+
```
+
+
## Part 1
+
+
```elixir
+
Enum.count(ways, & &1 > 0)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
306
+
```
+
+
## Part 2
+
+
```elixir
+
Enum.sum(ways)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
604622004681855
+
```
+
+
<!-- livebook:{"offset":7059,"stamp":{"token":"XCP.002DySFes8xjfbs_CVpc_QP75dkQcDFc5l37WdKhIJnRNctYjy9B2s3kTIev5coTlF4OCw1O-s8QuxIAU1HRaVoeZUHdw248FBapl1Ki5EyAYF1LHsn0MfuWbSukOOamT4I","version":2}} -->
+420
2024/day20.livemd
···
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 20
+
+
```elixir
+
Mix.install([:kino_aoc])
+
```
+
+
## Section
+
+
<!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIyMCIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
+
+
```elixir
+
{:ok, puzzle_input} =
+
KinoAOC.download_puzzle("2024", "20", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:ok,
+
"#############################################################################################################################################\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#.#####.#.#################.###.#.#.#.#.#.###.#.###.###.#.#.#.###.#.#.###.#.#.#.#.#####.###.#.###.#.###.#.#.#.#.#.###.#." <> ...}
+
```
+
+
```elixir
+
#puzzle_input =
+
"""
+
###############
+
#...#...#.....#
+
#.#.#.#.#.###.#
+
#S#...#.#.#...#
+
#######.#.#.###
+
#######.#.#...#
+
#######.#.###.#
+
###..E#...#...#
+
###.#######.###
+
#...###...#...#
+
#.#####.#.###.#
+
#.#...#.#.#...#
+
#.#.#.#.#.#.###
+
#...#...#...###
+
###############
+
"""
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
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/day20.livemd#cell:iyjl3w4kz3srtwoq:3:3
+
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
"###############\n#...#...#.....#\n#.#.#.#.#.###.#\n#S#...#.#.#...#\n#######.#.#.###\n#######.#.#...#\n#######.#.###.#\n###..E#...#...#\n###.#######.###\n#...###...#...#\n#.#####.#.###.#\n#.#...#.#.#...#\n#.#.#.#.#.#.###\n#...#...#...###\n###############\n"
+
```
+
+
```elixir
+
map =
+
puzzle_input
+
|> String.split("\n")
+
|> Enum.with_index()
+
|> Enum.flat_map(fn {row, y} ->
+
row
+
|> String.split("", trim: true)
+
|> Enum.with_index()
+
|> Enum.map(fn {c, x} ->
+
{{x, y}, c}
+
end)
+
end)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
[
+
{{0, 0}, "#"},
+
{{1, 0}, "#"},
+
{{2, 0}, "#"},
+
{{3, 0}, "#"},
+
{{4, 0}, "#"},
+
{{5, 0}, "#"},
+
{{6, 0}, "#"},
+
{{7, 0}, "#"},
+
{{8, 0}, "#"},
+
{{9, 0}, "#"},
+
{{10, 0}, "#"},
+
{{11, 0}, "#"},
+
{{12, 0}, "#"},
+
{{13, 0}, "#"},
+
{{14, 0}, "#"},
+
{{15, 0}, "#"},
+
{{16, 0}, "#"},
+
{{17, 0}, "#"},
+
{{18, 0}, "#"},
+
{{19, 0}, "#"},
+
{{20, 0}, "#"},
+
{{21, 0}, "#"},
+
{{22, 0}, "#"},
+
{{23, 0}, "#"},
+
{{24, 0}, "#"},
+
{{25, 0}, "#"},
+
{{26, 0}, "#"},
+
{{27, 0}, "#"},
+
{{28, 0}, "#"},
+
{{29, 0}, "#"},
+
{{30, 0}, "#"},
+
{{31, 0}, "#"},
+
{{32, 0}, "#"},
+
{{33, 0}, "#"},
+
{{34, 0}, "#"},
+
{{35, 0}, "#"},
+
{{36, 0}, "#"},
+
{{37, 0}, "#"},
+
{{38, 0}, "#"},
+
{{39, 0}, "#"},
+
{{40, 0}, "#"},
+
{{41, 0}, "#"},
+
{{42, 0}, "#"},
+
{{43, 0}, "#"},
+
{{44, 0}, "#"},
+
{{45, 0}, "#"},
+
{{46, 0}, "#"},
+
{{47, ...}, "#"},
+
{{...}, ...},
+
{...},
+
...
+
]
+
```
+
+
```elixir
+
%{"#" => walls, "." => road, "S" => [start], "E" => [finish]} =
+
Enum.group_by(map, &elem(&1, 1), &elem(&1, 0))
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
%{
+
"#" => [
+
{0, 0},
+
{1, 0},
+
{2, 0},
+
{3, 0},
+
{4, 0},
+
{5, 0},
+
{6, 0},
+
{7, 0},
+
{8, 0},
+
{9, 0},
+
{10, 0},
+
{11, 0},
+
{12, 0},
+
{13, 0},
+
{14, 0},
+
{15, 0},
+
{16, 0},
+
{17, 0},
+
{18, 0},
+
{19, 0},
+
{20, 0},
+
{21, 0},
+
{22, 0},
+
{23, 0},
+
{24, 0},
+
{25, 0},
+
{26, 0},
+
{27, 0},
+
{28, 0},
+
{29, 0},
+
{30, 0},
+
{31, 0},
+
{32, 0},
+
{33, 0},
+
{34, 0},
+
{35, 0},
+
{36, 0},
+
{37, 0},
+
{38, 0},
+
{39, 0},
+
{40, 0},
+
{41, 0},
+
{42, 0},
+
{43, 0},
+
{44, 0},
+
{45, 0},
+
{46, 0},
+
{47, ...},
+
{...},
+
...
+
],
+
"." => [
+
{1, 1},
+
{2, 1},
+
{3, 1},
+
{5, 1},
+
{6, 1},
+
{7, 1},
+
{9, 1},
+
{10, 1},
+
{11, 1},
+
{13, 1},
+
{14, 1},
+
{15, 1},
+
{17, 1},
+
{18, 1},
+
{19, 1},
+
{20, 1},
+
{21, 1},
+
{22, 1},
+
{23, 1},
+
{24, 1},
+
{25, 1},
+
{27, 1},
+
{28, 1},
+
{29, 1},
+
{30, 1},
+
{31, 1},
+
{32, 1},
+
{33, 1},
+
{34, 1},
+
{35, 1},
+
{39, 1},
+
{40, 1},
+
{41, 1},
+
{43, 1},
+
{44, 1},
+
{45, 1},
+
{46, 1},
+
{47, 1},
+
{49, 1},
+
{50, 1},
+
{51, 1},
+
{53, 1},
+
{54, 1},
+
{55, 1},
+
{56, 1},
+
{57, 1},
+
{59, ...},
+
{...},
+
...
+
],
+
"E" => [{27, 59}],
+
"S" => [{49, 53}]
+
}
+
```
+
+
```elixir
+
defmodule Race do
+
def distances(start, finish, walls) do
+
do_distances(start, finish, 0, MapSet.new(walls), %{})
+
end
+
+
defp do_distances(finish, finish, n, _, acc),
+
do: Map.put(acc, finish, n)
+
+
defp do_distances(current, finish, n, walls, acc) do
+
acc = Map.put(acc, current, n)
+
+
current
+
|> neigh()
+
|> Enum.reject(&(&1 in walls or Map.has_key?(acc, &1)))
+
|> hd()
+
|> do_distances(finish, n + 1, walls, acc)
+
end
+
+
def neigh({x, y}, d \\ 1) do
+
for {dx, dy} <- [{0, d}, {0, -d}, {d, 0}, {-d, 0}], do: {x + dx, y + dy}
+
end
+
+
def neighbours({x, y}, r \\ 1) do
+
for dx <- -r..r,
+
dy <- -r..r,
+
{dx, dy} != {0, 0},
+
d = abs(dx) + abs(dy),
+
d <= r,
+
do: {x + dx, y + dy}
+
end
+
+
def d({xa, ya}, {xb, yb}) do
+
abs(xa - xb) + abs(ya - yb)
+
end
+
end
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:module, Race, <<70, 79, 82, 49, 0, 0, 17, ...>>, {:d, 2}}
+
```
+
+
```elixir
+
steps = Race.distances(start, finish, walls)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
%{
+
{18, 103} => 8261,
+
{61, 121} => 7060,
+
{65, 63} => 2098,
+
{77, 129} => 6964,
+
{1, 26} => 695,
+
{116, 69} => 4441,
+
{83, 76} => 4281,
+
{117, 125} => 5656,
+
{103, 106} => 5785,
+
{30, 113} => 8041,
+
{89, 14} => 2511,
+
{35, 30} => 1133,
+
{37, 53} => 32,
+
{11, 39} => 384,
+
{131, 5} => 2998,
+
{65, 43} => 1754,
+
{139, 46} => 3615,
+
{12, 135} => 7871,
+
{65, 131} => 7046,
+
{49, 117} => 7412,
+
{29, 25} => 1108,
+
{83, 36} => 2319,
+
{47, 27} => 1556,
+
{4, 81} => 8645,
+
{13, 124} => 8295,
+
{121, 77} => 4608,
+
{103, 39} => 3756,
+
{119, 60} => 4389,
+
{13, 85} => 8604,
+
{63, 81} => 6682,
+
{111, 108} => 5755,
+
{111, 103} => 5764,
+
{15, 92} => 8587,
+
{1, 101} => 8500,
+
{20, 3} => 939,
+
{61, 95} => 6878,
+
{23, 67} => 9208,
+
{78, 75} => 6545,
+
{79, 17} => 2358,
+
{17, 137} => 7852,
+
{124, 93} => 4933,
+
{138, 9} => 3283,
+
{58, 33} => 1667,
+
{67, 105} => 6818,
+
{47, 44} => 1195,
+
{122, 137} => 5595,
+
{13, 55} => 154,
+
{97, 138} => 6129,
+
{75, ...} => 2165,
+
{...} => 1616,
+
...
+
}
+
```
+
+
## Part 1
+
+
```elixir
+
Enum.reduce(steps, 0, fn {pos, start}, acc ->
+
count =
+
steps
+
|> Map.take(Race.neighbours(pos, 2))
+
|> Enum.count(fn {last, finish} ->
+
finish - start - Race.d(pos, last) >= 100
+
end)
+
+
count + acc
+
end)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
1393
+
```
+
+
## Part 2
+
+
We can notice that we are looking for shortcuts in circle of radius $r$ defined in Taxicab metric ($d(a, b) = \sum_{i} |a_i - b_i|$). That makes code pretty simple and allows us to reuse ideas from Part 1.
+
+
```elixir
+
steps
+
|> Task.async_stream(
+
fn {pos, start} ->
+
steps
+
|> Map.take(Race.neighbours(pos, 20))
+
|> Enum.count(fn {last, finish} ->
+
finish - start - Race.d(pos, last) >= 100
+
end)
+
end,
+
ordered: false
+
)
+
|> Enum.reduce(0, fn {:ok, count}, acc ->
+
count + acc
+
end)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
990096
+
```
+
+
<!-- livebook:{"offset":11400,"stamp":{"token":"XCP.ONwDp6zRpWXsXASH95Q0puANk15Li1hG2FDCrv6Gqu42Q7k9pb_Te_6RDoUE0dp3yYbG7jry8-6iHGJvcZtsDFstlznyVHk9HVhXRZiC2uQczaOfF4K8HQL9QuzNguTht7A","version":2}} -->
+182
2024/day21.livemd
···
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 21
+
+
```elixir
+
Mix.install([:kino_aoc])
+
```
+
+
## Section
+
+
<!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIyMSIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
+
+
```elixir
+
{:ok, puzzle_input} =
+
KinoAOC.download_puzzle("2024", "21", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:ok, "638A\n965A\n780A\n803A\n246A"}
+
```
+
+
```elixir
+
codes =
+
puzzle_input
+
|> String.split("\n", trim: true)
+
|> Enum.map(fn <<num::3-binary>> <> "A" = code ->
+
{String.to_charlist(code), String.to_integer(num)}
+
end)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
[{~c"638A", 638}, {~c"965A", 965}, {~c"780A", 780}, {~c"803A", 803}, {~c"246A", 246}]
+
```
+
+
```elixir
+
dirpad = %{
+
[?A, ?>] => ~c[vA],
+
[?A, ?^] => ~c[<A],
+
[?A, ?v] => ~c[<vA],
+
[?A, ?<] => ~c[v<<A],
+
+
[?>, ?A] => ~c[^A],
+
[?>, ?^] => ~c[<^A],
+
[?>, ?v] => ~c[<A],
+
[?>, ?<] => ~c[<<A],
+
+
[?^, ?A] => ~c[>A],
+
[?^, ?>] => ~c[v>A],
+
[?^, ?v] => ~c[vA],
+
[?^, ?<] => ~c[v<A],
+
+
[?<, ?A] => ~c[>>^A],
+
[?<, ?^] => ~c[>^A],
+
[?<, ?v] => ~c[>A],
+
[?<, ?>] => ~c[>>A],
+
+
[?v, ?A] => ~c[>^A],
+
[?v, ?^] => ~c[^A],
+
[?v, ?<] => ~c[<A],
+
[?v, ?>] => ~c[>A]
+
}
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
%{
+
~c"<>" => ~c">>A",
+
~c"<A" => ~c">>^A",
+
~c"<^" => ~c">^A",
+
~c"<v" => ~c">A",
+
~c"><" => ~c"<<A",
+
~c">A" => ~c"^A",
+
~c">^" => ~c"<^A",
+
~c">v" => ~c"<A",
+
~c"A<" => ~c"v<<A",
+
~c"A>" => ~c"vA",
+
~c"A^" => ~c"<A",
+
~c"Av" => ~c"<vA",
+
~c"^<" => ~c"v<A",
+
~c"^>" => ~c"v>A",
+
~c"^A" => ~c">A",
+
~c"^v" => ~c"vA",
+
~c"v<" => ~c"<A",
+
~c"v>" => ~c">A",
+
~c"vA" => ~c">^A",
+
~c"v^" => ~c"^A"
+
}
+
```
+
+
```elixir
+
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
nil
+
```
+
+
```elixir
+
defmodule Keypad do
+
def naive(input, lut) do
+
[?A | input]
+
|> Enum.chunk_every(2, 1, :discard)
+
|> Enum.flat_map(&Map.get(lut, &1, [?A]))
+
end
+
+
def expand(input, lut) do
+
Stream.concat([?A], input)
+
|> Stream.chunk_every(2, 1, :discard)
+
|> Stream.flat_map(&Map.get(lut, &1, [?A]))
+
end
+
end
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:module, Keypad, <<70, 79, 82, 49, 0, 0, 9, ...>>, {:expand, 2}}
+
```
+
+
```elixir
+
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
nil
+
```
+
+
```elixir
+
Keypad.expand(~c[<A^A>^^AvvvA], dirpad)
+
|> Enum.count()
+
+
#|> Enum.map(fn {k, v} ->
+
# [?A | Map.get(dirpad, k, [?A])]
+
# |> Enum.chunk_every(2, 1, :discard)
+
# |> Enum.map()
+
#end)
+
#|> Enum.group_by(&elem(&1, 0), &elem(&1, 1))
+
#|> Map.new(fn {k, v} -> {k, Enum.sum(v)} end)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
28
+
```
+
+
```elixir
+
Keypad.naive(~c[<A^A>^^AvvvA], dirpad)
+
|> Keypad.naive(dirpad)
+
|> Enum.chunk_every(2, 1, [?A])
+
|> Enum.frequencies()
+
|> Map.values()
+
|> Enum.sum()
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
68
+
```
+
+
```elixir
+
~c"<vA<AA>>^AvAA<^A>Av<<A>>^AvA^A<vA>^Av<<A>^A>AAvA^Av<<A>A>^AAAvA<^A>A"
+
~c"<vA<AA>>^AvAA<^A>A<v<A>>^AvA^A<vA>^A<v<A>^A>AAvA^A<v<A>A>^AAAvA<^A>A" |> length
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
68
+
```
+
+
<!-- livebook:{"offset":3144,"stamp":{"token":"XCP.rEBKR0PbENlE02mf_Mo6R3RTWsHU-tFuA9VTPd907vq3-8e37LytxC6qWBmZAHZHLc_e1t3ZaG85X5KBWsYq0WGEzo7HC0U9-oE0dpPKGKeF7oBGgFeiEoDsX6GDKTwp76o","version":2}} -->
+198
2024/day22.livemd
···
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 22
+
+
```elixir
+
Mix.install([:kino_aoc])
+
```
+
+
## Section
+
+
<!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIyMiIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
+
+
```elixir
+
{:ok, puzzle_input} =
+
KinoAOC.download_puzzle("2024", "22", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:ok,
+
"4832674\n14802956\n7210529\n7709095\n6063251\n12294789\n15666951\n12074106\n15427686\n1214891\n15165649\n3609602\n10200989\n16451437\n10915511\n3479515\n173864\n1238342\n3381843\n14767788\n16088065\n15637051\n15981887\n15854806\n4988920\n7980791\n11263142\n8044640\n4572291\n328777\n11851557\n13706949\n16451719\n15991644\n14668984\n8852039\n1685443\n13814197\n14117797\n6281998\n12395020\n1681090\n16476099\n2171296\n10155667\n15490827\n6723206\n7272972\n1788575\n2950054\n10917267\n6862495\n8153949\n16559239\n8572595\n1821668\n3417901\n11375457\n3878450\n10863466\n10890116\n13055126\n7451580\n5815531\n8335506\n431487\n201975\n5841753\n11744013\n4498615\n9261071\n9953929\n4630027\n2227105\n6260342\n10375281\n3015284\n3789175\n15843612\n14432075\n14847622\n11501912\n9079366\n2550341\n6931972\n13371306\n9601571\n14504463\n6162939\n5361897\n14900517\n12748562\n7519640\n14694035\n5566950\n7688680\n13810532\n5654369\n10957671\n6886767\n13114128\n9355299\n14808826\n11001280\n4983663\n9915373\n3356476\n16519750\n15826279\n11122172\n12902904\n1010762\n16214923\n9519057\n15931832\n15664252\n12750269\n1110882\n7854151\n3509827\n10328167\n1494530\n8712493\n396534\n15995697\n7396815\n3419574\n14789278\n14099072\n15389372\n6910648\n649063\n3609071\n6004556\n5054128\n13730203\n3554012\n2766085\n7133343\n7566747\n1194302\n10446649\n1529903\n9036124\n11725198\n6479244\n10287711\n2219155\n2360315\n8169407\n7841353\n7486466\n15297309\n9336789\n7225072\n6248515\n16154198\n11100038\n8584563\n3753173\n7371112\n2481160\n10954049\n8009781\n7381801\n280810\n11001420\n14114713\n4242475\n1237360\n6496866\n15267044\n1880781\n8798544\n5033766\n5079684\n11633848\n16509688\n8226900\n15858455\n16041151\n5334220\n15421957\n2633967\n8343560\n14729378\n9702409\n5482505\n2041087\n9712582\n3430735\n10644043\n9195957\n1784419\n14046333\n2031279\n12766582\n12165573\n14207224\n14929506\n11436548\n13623882\n12370036\n7592923\n228169\n8988171\n6688080\n5492092\n8212636\n3736928\n15352784\n2612376\n14843761\n12308540\n8404032\n11632730\n4404470\n2599992\n6807809\n12044159\n9795957\n5307557\n13144362\n13941181\n9362743\n4957570\n9950852\n4069207\n699043\n13667685\n12869414\n5834836\n8434557\n13512362\n5446646\n16663243\n10059682\n231185\n14405863\n10532295\n13752653\n3266523\n12926376\n9013886\n15683001\n10524950\n325867\n15226063\n15175724\n15991383\n13961546\n15823957\n9310375\n5534565\n2674761\n13444598\n9915920\n1755544\n1429896\n14788650\n5453166\n10081466\n2149840\n16613385\n2519989\n7555351\n7295534\n12099546\n3223009\n2684428\n8436395\n5406395\n836225\n9962036\n2847179\n12880336\n13215841\n3498334\n5985622\n7700379\n5785351\n9938722\n15810882\n2349820\n906893\n2513825\n10432278\n13789913\n2913486\n9683268\n2862417\n4807276\n16264545\n6607564\n10222512\n2190055\n11839341\n2132714\n153996\n10874457\n12023939\n7748310\n13452955\n3246986\n2892967\n9561561\n3280827\n991231\n13105708\n16641479\n273523\n4832864\n13832855\n7903624\n13242917\n13379831\n9085055\n1473661\n11031255\n4126827\n12754058\n456062\n14316218\n6580848\n11147440\n1828704\n15262845\n557484\n2406569\n10393027\n3363996\n15821838\n16365523\n5566374\n3723957\n5186897\n501767\n10639559\n3256585\n2354615\n1888438\n11574106\n11798800\n12629659\n6316600\n3119025\n14801938\n7025953\n14949782\n7577552\n14785389\n8868837\n11642113\n14574465\n8689963\n16223594\n14705685\n16363438\n1393194\n5961465\n16603208\n8121071\n15143692\n7531645\n6777163\n8168251\n15905711\n2373414\n1269213\n2506356\n1080789\n2154403\n11578189\n6232867\n10065427\n15116084\n15449140\n12675436\n14126594\n8470014\n2106625\n12556109\n12771090\n1437370\n16145074\n6244539\n6832665\n13217078\n5152936\n15205635\n12092447\n15115231\n2112929\n13215959\n11124896\n14598714\n15256810\n9994507\n11687859\n11599901\n5330801\n13829820\n1720133\n11040068\n4351948\n9597919\n10673331\n6148104\n12360792\n9687192\n11668420\n10272257\n7823976\n6113203\n8827921\n5600165\n6950138\n9581746\n15917691\n6453798\n11788226\n15057269\n9639028\n5073513\n15459362\n14118507\n7979569\n4210224\n5726357\n10649449\n14645020\n3062620\n14613306\n13963982\n14770179\n15097265\n1789308\n12405157\n7360698\n6983540\n9752726\n8200080\n5784060\n13456865\n4677699\n3783161\n13650051\n9865655\n13066800\n1868022\n5855823\n15061710\n11742417\n2116233\n15002417\n904747\n9455335\n5203086\n704685\n902384\n15284593\n8328120\n13587250\n11550241\n10950646\n14876694\n11393724\n14576237\n898540\n8874901\n5548732\n11351523\n2315166\n9532824\n11462685\n1297628\n3862586\n16331382\n9291789\n2887008\n2582973\n4861709\n15301133\n8978897\n533818\n1565155\n3829639\n8438476\n11901529" <> ...}
+
```
+
+
```elixir
+
inits =
+
puzzle_input
+
|> String.split("\n", trim: true)
+
|> Enum.map(&String.to_integer/1)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
[4832674, 14802956, 7210529, 7709095, 6063251, 12294789, 15666951, 12074106, 15427686, 1214891,
+
15165649, 3609602, 10200989, 16451437, 10915511, 3479515, 173864, 1238342, 3381843, 14767788,
+
16088065, 15637051, 15981887, 15854806, 4988920, 7980791, 11263142, 8044640, 4572291, 328777,
+
11851557, 13706949, 16451719, 15991644, 14668984, 8852039, 1685443, 13814197, 14117797, 6281998,
+
12395020, 1681090, 16476099, 2171296, 10155667, 15490827, 6723206, 7272972, 1788575, 2950054, ...]
+
```
+
+
```elixir
+
defmodule Buyer do
+
def hash(number, rounds \\ 2000) do
+
Enum.map_reduce(1..rounds//1, number, fn _, acc ->
+
r = do_round(acc)
+
{rem(r, 10), r}
+
end)
+
end
+
+
defp do_round(num) do
+
num = subround(num, num * 64)
+
num = subround(num, div(num, 32))
+
subround(num, num * 2048)
+
end
+
+
defp subround(a, b), do: rem(Bitwise.bxor(a, b), 16_777_216)
+
+
def sequences(prices) do
+
prices
+
|> Enum.chunk_every(5, 1, :discard)
+
|> Enum.reduce(%{}, fn seq, map ->
+
Map.put_new(map, diffs(seq), List.last(seq))
+
end)
+
end
+
+
defp diffs(vals) do
+
vals
+
|> Enum.chunk_every(2, 1, :discard)
+
|> Enum.map(fn [a, b] -> b - a end)
+
|> Integer.undigits(256)
+
end
+
end
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:module, Buyer, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:diffs, 1}}
+
```
+
+
```elixir
+
hashes = Enum.map(inits, &Buyer.hash(&1))
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
[
+
{[5, 9, 7, 9, 4, 6, 2, 9, 4, 3, 6, 5, 0, 6, 5, 7, 2, 7, 9, 7, 0, 2, 5, 8, 8, 2, 0, 8, 4, 8, 3, 1,
+
4, 3, 3, 8, 0, 5, 2, 1, 2, 8, 6, 2, 2, 3, 6, 9, ...], 8186085},
+
{[8, 6, 8, 8, 3, 4, 6, 9, 0, 1, 1, 5, 4, 9, 5, 4, 1, 2, 5, 2, 6, 7, 8, 7, 5, 4, 4, 2, 5, 6, 4, 6,
+
2, 4, 5, 9, 5, 8, 5, 0, 6, 9, 3, 2, 3, 4, 4, ...], 16060909},
+
{[6, 0, 5, 8, 8, 7, 3, 6, 0, 9, 1, 0, 7, 2, 7, 5, 6, 4, 0, 5, 4, 0, 1, 9, 6, 5, 7, 1, 7, 9, 9, 9,
+
5, 6, 0, 7, 3, 0, 9, 4, 8, 4, 0, 2, 2, 7, ...], 3581487},
+
{[6, 3, 1, 0, 2, 6, 8, 9, 1, 6, 7, 4, 5, 0, 9, 9, 8, 9, 1, 0, 6, 4, 9, 0, 1, 0, 9, 3, 0, 0, 9, 1,
+
9, 6, 6, 7, 2, 1, 7, 2, 7, 3, 2, 7, 3, ...], 14331752},
+
{[3, 5, 1, 7, 1, 4, 6, 0, 4, 9, 8, 3, 7, 3, 3, 2, 2, 9, 1, 3, 3, 4, 9, 2, 3, 2, 5, 6, 9, 4, 3, 8,
+
1, 6, 7, 3, 8, 8, 7, 5, 3, 3, 2, 3, ...], 11096256},
+
{[9, 5, 4, 8, 1, 3, 9, 8, 2, 6, 7, 9, 0, 8, 6, 3, 4, 8, 7, 0, 0, 2, 2, 7, 2, 2, 0, 9, 7, 4, 9, 5,
+
7, 1, 3, 1, 7, 9, 3, 3, 6, 2, 4, ...], 8119288},
+
{[3, 0, 8, 6, 0, 0, 3, 4, 2, 0, 0, 8, 7, 6, 3, 7, 5, 2, 4, 8, 4, 4, 5, 4, 8, 9, 2, 1, 6, 8, 3, 9,
+
2, 8, 0, 5, 0, 9, 7, 2, 5, 9, ...], 4175670},
+
{[9, 6, 3, 2, 9, 6, 8, 1, 7, 8, 0, 7, 2, 2, 0, 8, 6, 5, 5, 3, 9, 6, 5, 7, 1, 4, 6, 7, 9, 7, 2, 4,
+
6, 2, 0, 2, 9, 7, 8, 0, 9, ...], 9128738},
+
{[5, 8, 5, 2, 2, 9, 4, 4, 8, 8, 9, 9, 8, 3, 4, 9, 2, 2, 9, 1, 2, 2, 0, 8, 1, 2, 3, 4, 0, 4, 6, 4,
+
3, 6, 8, 1, 9, 6, 1, 5, ...], 13899897},
+
{[0, 9, 4, 3, 5, 9, 1, 2, 1, 1, 8, 1, 8, 8, 3, 8, 4, 4, 3, 7, 7, 2, 9, 8, 5, 8, 8, 4, 4, 8, 4, 0,
+
5, 9, 7, 0, 3, 3, 6, ...], 12087848},
+
{[5, 6, 7, 3, 2, 0, 5, 4, 8, 8, 2, 6, 8, 4, 9, 7, 2, 0, 9, 3, 4, 1, 3, 0, 6, 5, 2, 6, 4, 6, 9, 4,
+
3, 9, 9, 9, 7, 2, ...], 11514818},
+
{[0, 9, 7, 9, 2, 6, 4, 9, 7, 0, 3, 1, 6, 4, 3, 2, 0, 2, 8, 4, 7, 6, 7, 7, 1, 1, 5, 2, 6, 6, 1, 4,
+
9, 5, 6, 9, 3, ...], 4150418},
+
{[5, 5, 0, 8, 5, 6, 2, 7, 0, 5, 4, 2, 1, 0, 5, 6, 6, 3, 6, 2, 4, 3, 9, 4, 3, 0, 8, 0, 6, 7, 1, 8,
+
0, 2, 7, 1, ...], 2679493},
+
{[4, 0, 8, 1, 5, 9, 0, 3, 6, 0, 2, 8, 5, 7, 1, 1, 9, 1, 5, 1, 5, 0, 7, 3, 5, 5, 4, 3, 9, 4, 3, 9,
+
6, 9, 6, ...], 84072},
+
{[0, 5, 2, 6, 6, 4, 1, 2, 5, 2, 3, 8, 4, 1, 2, 4, 7, 5, 2, 7, 7, 0, 8, 0, 6, 0, 6, 3, 4, 3, 7, 0,
+
5, 8, ...], 3938870},
+
{[5, 5, 5, 5, 6, 0, 6, 9, 2, 0, 0, 5, 3, 0, 3, 3, 0, 7, 7, 0, 1, 5, 8, 8, 6, 5, 3, 3, 2, 5, 8, 8,
+
8, ...], 15186439},
+
{[5, 1, 6, 4, 5, 2, 2, 2, 0, 9, 6, 3, 2, 1, 5, 6, 2, 6, 0, 4, 2, 8, 9, 2, 8, 7, 8, 7, 9, 2, 5, 1,
+
...], 4224277},
+
{[8, 7, 6, 6, 8, 0, 1, 8, 9, 1, 7, 5, 0, 6, 4, 4, 9, 2, 1, 6, 1, 5, 4, 1, 9, 9, 9, 4, 7, 3, 0,
+
...], 6637814},
+
{[7, 4, 4, 8, 3, 9, 5, 6, 1, 1, 7, 4, 7, 2, 5, 3, 8, 5, 3, 4, 7, 7, 0, 0, 4, 1, 7, 1, 4, 5, ...],
+
15335578},
+
{[1, 3, 9, 5, 1, 4, 9, 6, 9, 0, 6, 7, 7, 5, 4, 8, 8, 4, 4, 0, 3, 0, 0, 2, 8, 8, 8, 7, 5, ...],
+
14808063},
+
{[3, 8, 6, 7, 8, 8, 1, 5, 4, 2, 3, 3, 6, 0, 4, 4, 6, 3, 6, 3, 5, 3, 3, 7, 4, 7, 1, 8, ...],
+
2236221},
+
{[4, 2, 4, 3, 0, 3, 6, 2, 7, 9, 6, 6, 9, 3, 2, 0, 1, 8, 1, 5, 7, 7, 3, 8, 8, 1, 9, ...], 9777274},
+
{[8, 5, 1, 6, 9, 9, 1, 6, 3, 9, 9, 4, 5, 9, 4, 2, 8, 5, 7, 9, 2, 1, 6, 9, 0, 9, ...], 14777742},
+
{[4, 6, 0, 4, 6, 3, 2, 3, 8, 0, 2, 3, 2, 2, 0, 7, 7, 4, 5, 8, 8, 2, 8, 9, 4, ...], 3528684},
+
{[3, 6, 3, 3, 3, 2, 5, 2, 8, 8, 8, 0, 3, 1, 2, 2, 6, 2, 3, 1, 2, 6, 1, 9, ...], 15225220},
+
{[2, 1, 2, 4, 0, 6, 0, 8, 6, 5, 9, 5, 1, 7, 1, 3, 9, 3, 2, 8, 5, 4, 8, ...], 4484251},
+
{[1, 5, 9, 2, 0, 5, 7, 4, 6, 2, 3, 4, 7, 9, 9, 7, 9, 8, 3, 4, 2, 3, ...], 12505941},
+
{[3, 2, 8, 0, 7, 6, 7, 8, 6, 2, 0, 4, 7, 6, 2, 8, 2, 7, 3, 0, 3, ...], 12324709},
+
{[3, 6, 3, 2, 2, 5, 4, 5, 3, 2, 2, 8, 5, 8, 7, 6, 5, 9, 3, 0, ...], 12840916},
+
{[7, 4, 1, 3, 5, 7, 1, 9, 4, 8, 2, 0, 2, 6, 7, 1, 7, 8, 4, ...], 13939301},
+
{[0, 4, 4, 4, 6, 9, 8, 0, 2, 3, 9, 9, 4, 0, 6, 0, 4, 2, ...], 7392065},
+
{[7, 8, 0, 0, 4, 1, 6, 1, 5, 9, 0, 3, 1, 4, 5, 8, 9, ...], 13395486},
+
{[5, 5, 1, 7, 9, 8, 0, 1, 5, 5, 6, 2, 1, 6, 6, 5, ...], 14846825},
+
{[4, 1, 5, 9, 7, 1, 3, 6, 6, 5, 8, 9, 1, 0, 7, ...], 15647415},
+
{[5, 0, 0, 5, 4, 4, 9, 3, 4, 0, 4, 9, 0, 0, ...], 15491670},
+
{[5, 3, 1, 3, 6, 7, 3, 2, 8, 6, 2, 5, 0, ...], 12602693},
+
{[9, 6, 3, 2, 6, 3, 9, 6, 6, 5, 2, 6, ...], 16470307},
+
{[8, 4, 3, 6, 0, 4, 0, 8, 5, 5, 9, ...], 10819101},
+
{[0, 9, 4, 4, 6, 0, 2, 4, 0, 3, ...], 8658998},
+
{[0, 2, 8, 3, 0, 4, 5, 0, 5, ...], 11616760},
+
{[4, 8, 3, 5, 2, 8, 0, 8, ...], 4294043},
+
{[8, 1, 0, 8, 2, 1, 0, ...], 11210309},
+
{[5, 8, 6, 9, 6, 8, ...], 1113711},
+
{[1, 6, 5, 5, 4, ...], 16530315},
+
{[5, 1, 3, 9, ...], 8014000},
+
{[7, 4, 5, ...], 13932057},
+
{[8, 9, ...], 9987703},
+
{[4, ...], 10745797},
+
{[...], ...},
+
{...},
+
...
+
]
+
```
+
+
## Part 1
+
+
```elixir
+
hashes
+
|> Enum.map(&elem(&1, 1))
+
|> Enum.sum()
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
13461553007
+
```
+
+
## Part 2
+
+
```elixir
+
hashes
+
|> Task.async_stream(
+
fn {prices, _} -> Buyer.sequences(prices) end,
+
ordered: false
+
)
+
|> Enum.reduce(%{}, fn {:ok, a}, b -> Map.merge(a, b, fn _k, v, k -> v + k end) end)
+
|> Enum.max_by(&elem(&1, 1))
+
|> elem(1)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
1499
+
```
+
+
<!-- livebook:{"offset":11738,"stamp":{"token":"XCP.GjkWCjlMBRZbt2b3Ic6te1lRoiRN-o788mezmoiandQKEk9mR1MC2aSWY6otgof8lHDa_afMMYYnBV9YHmLjoK0wooHF17OPyx6ruqV5hYpKoVBVZuhSx_gT8_2Ac2S73Pk","version":2}} -->
+203
2024/day23.livemd
···
+
<!-- livebook:{"persist_outputs":true} -->
+
+
# Day 23
+
+
```elixir
+
Mix.install([:kino_aoc, {:libgraph, github: "bitwalker/libgraph"}, :combination])
+
```
+
+
## Section
+
+
<!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIyMyIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
+
+
```elixir
+
{:ok, puzzle_input} =
+
KinoAOC.download_puzzle("2024", "23", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
{:ok,
+
"on-za\nbp-hs\nvc-bg\ntm-us\nzf-ox\nib-lc\nuo-zs\nov-qj\nll-eb\niy-tq\nbg-by\nun-ix\ngi-do\nrv-ou\nyp-qu\nqb-um\nqs-dn\nru-ro\net-fw\nyx-jt\nns-iz\nod-rc\nny-ap\nvb-fd\nwf-wr\nyh-qy\nfa-ct\nqo-fv\nig-jv\nqi-ff\nnj-ii\nsa-gg\ncp-un\nez-kh\nvs-du\ngp-qs\npt-qj\nyp-my\njf-sz\nyo-gm\nfn-xw\niu-xr\nse-ox\nmw-ie\nfw-br\nxy-iu\nqw-wi\nxc-dq\nvb-cq\ntw-zj\nka-aq\ngo-ds\nvi-cn\npz-kz\npy-nd\npt-ws\nog-lw\nlb-hj\nef-ac\ncv-qa\nsq-jv\nfw-xk\nlu-fc\nbj-bp\nzh-fi\ntg-nm\nsp-at\nke-dh\nut-ly\ngr-vr\nko-qg\nxg-df\nrc-up\nbd-it\ngz-en\nqj-ev\nwf-dx\nxn-hi\npq-th\nkr-gw\ngu-sm\ncv-xr\nzq-fp\nep-kq\nfv-dx\nlc-rw\ney-ef\nek-rw\ntw-eg\nfc-zw\nxm-ho\ngj-oy\nhy-og\nec-tw\npy-hw\nqr-jh\nvh-ea\nvz-ja\nov-ev\nyh-vh\nyk-fc\nfm-yi\nyf-kx\ner-bi\nbi-qq\ngc-fk\nie-gf\njk-fn\nxl-il\nbs-dl\nsh-op\npy-vx\ncn-jl\ntl-ee\nxw-wn\nzv-br\nkr-yn\ndj-wd\nwj-bz\nhf-bg\nzh-ql\nbs-ls\ntq-jk\nmz-dz\nav-jr\ngj-dr\npo-iy\nof-aq\nun-fw\nnv-bx\njz-nl\nze-ae\nvd-df\nix-et\nrn-ik\ndz-ou\nmz-ej\nec-kx\nxr-cf\njt-vr\nix-fw\nes-er\nbv-no\nwj-df\nyv-cl\njd-xl\nlu-vo\nxo-td\nvq-ow\nlc-vm\nca-lf\noq-on\nwj-xg\nfn-rp\nka-np\nbx-ez\ndz-sz\nkt-xl\ndd-jd\nla-qn\nqe-pt\ngl-ly\nqj-cc\nat-rf\nke-om\ndc-hu\nqb-rr\nov-ku\ntq-xw\nfz-tn\nma-hi\nbr-yw\nno-sp\ndj-kn\nyn-gw\ngo-ir\nbz-xg\nwo-se\nrz-wa\nqy-sx\nqn-ym\npo-tq\nxr-jh\ndf-tn\noe-vi\nsw-el\nvm-vr\ntg-nf\ncg-zt\nwf-fl\ncd-nc\nsw-qa\nfo-jg\nhj-av\nwd-rn\nwc-wq\noq-vw\nkx-ux\nop-nq\nsm-ru\nch-fw\nqx-uy\nti-fw\nrp-qm\npo-tj\nse-nw\npj-rs\nbo-sn\nsy-ur\niy-jb\ntm-rz\ndg-jt\nfa-sq\nok-th\nzq-ps\nhr-kr\npz-zs\nwq-ze\nms-an\nnp-aq\ntl-ka\npw-dh\nbm-sz\nuu-gm\nft-vb\nau-ab\nlx-lw\ncp-ri\nep-xm\nry-hk\nyi-gf\ncj-qr\nfl-lu\nbv-za\nyw-xk\nne-ss\nln-wv\nwf-vo\nlx-jy\noy-xy\nkq-fa\neh-lv\nuq-mi\nis-mx\nwn-eo\nqr-xy\nlr-ms\nkt-jd\nyk-lu\nqe-cc\naj-si\nqq-bp\nlw-xa\nus-pp\nen-mq\nct-te\nod-db\ncp-br\nrg-ou\nev-ku\nqg-ec\nuv-np\njn-sw\nxj-ie\nqr-xr\ntr-zp\nha-gg\nrx-pz\nsa-fl\ngx-vz\nmg-oi\nyc-zn\nxw-jo\nae-ou\nhj-gn\nix-ri\nsq-ct\nwo-xr\nbl-wl\ntt-ac\nbs-ij\nmh-re\nhg-lv\nwu-fh\nrt-rq\nsn-vq\nzy-vh\nyh-zy\ntu-oz\nbk-ai\nds-gq\nss-ob\ndv-di\nvw-on\nxr-zb\nfr-jl\nro-om\nrk-mg\nyc-hi\nvv-nf\nkz-nt\nrt-qw\nzj-ux\nox-wv\nfz-dc\nya-xo\ngq-du\nmx-fk\nsi-mo\nmo-ef\ndb-ex\nhw-rc\njy-qd\noz-lb\nvi-cm\nvx-ec\nxr-aa\nnx-ni\nny-fv\nta-vc\nnq-yi\nzt-gp\nnd-iu\nvv-yd\nsh-gf\nyf-hm\ndq-ee\nbg-bt\nnc-kz\ngq-py\nek-sy\nty-le\njo-eo\ndy-ko\nxa-qd\nrm-ns\ngk-xp\ngz-jr\ncr-ez\nwr-fc\nhe-cg\nin-og\ndw-sh\nuk-bf\nbr-un\nok-gi\nch-gr\ncx-gz\ndv-ho\nbx-cr\nex-go\nik-nv\nkh-wb\nol-vk\nhg-bf\nod-du\nvj-qk\nyd-uj\nfu-lq\nbi-bj\nvl-il\ncd-ob\nax-us\nmw-nq\nvr-rw\nhx-uf\nwz-vb\nem-xe\nee-of\nhm-ec\nek-ds\nys-sy\nqq-jq\ngu-jg\nzc-oi\nji-yb\nou-kw\nep-lh\nid-nx\ngp-wp\nph-ns\ncn-io\nwn-tq\nrw-vm\nnx-fv\nce-gn\nvr-lt\nxl-dd\nzw-sa\nwr-ty\nkz-jx\njd-rx\nna-hk\nnc-ob\nnw-re\nwt-jq\naj-sw\nkc-bi\nwq-qx\njt-ib\ncb-ly\nuj-zp\ncy-ps\nsm-om\nbu-bd\nux-ko\nxa-hy\nbc-uq\nsi-sw\nyc-ma\nyk-sa\ngf-mw\nbp-eq\nfh-zh\nmn-bo\nbw-hj\nes-bj\nop-xj\nup-hh\nds-db\ngx-qu\nyo-fp\nwg-ls\net-zc\ndn-vw\nyb-bt\nsk-sb\nxe-ea\nni-ap\nhw-go\ndn-zc\nno-vw\npt-cc\nrv-wc\nwc-xq\njg-ke\noo-jg\ndo-ss\nie-nq\npq-is\nrf-oq\nzn-vb\neb-ef\ngp-rs\npt-pf\nmd-lb\nle-zw\nxn-tf\nui-cb\nbz-fz\npj-gp\nzr-ee\npp-ax\nkl-jq\nxc-of\nox-lr\nuy-rv\nvd-sb\nyy-bh\nvn-dq\ndt-hg\nnp-vn\nla-fh\ngw-eh\ncq-wz\nno-ia\nqj-ws\npl-pt\ndf-ge\nzq-vj\njg-om\nnq-sh\nzy-kr\npv-im\naq-vn\nsq-yx\nsb-df\nih-gx\ngn-av\ndc-ff\nwg-ph\nsm-fo\nux-dk\ngi-kv\nhr-dt\nrc-go\nax-tm\npp-bo\nnn-xe\njf-mz\nvl-jd\nfs-cl\ngz-gn\nui-ly\nrx-hy\nrn-dj\nqe-pf\njx-gy\ntr-qb\neu-lr\nyt-ih\ntr-oi\nnc-ss\nnh-pb\nir-nd\nel-qf\ntl-aq\nkj-es\nru-fo\nfw-bu\nps-qk\nlq-lx\ncm-fg\nel-si\nvs-hw\neg-ux\nmt-lh\ntt-yy\njz-sq\nfm-nq\nvx-ko\nbl-lx\nrc-ex\nby-ji\neq-kl\ntk-vd\nmo-qf\nzr-xd\nbt-vc\nux-mi\nha-us\nvr-ib\nhx-rq\nat-no\nui-tx\nvs-od\nfp-ay\nzj-kx\nvs-ds\nqo-vk\nhw-db\npf-ku\nmd-jr\nfp-fe\nyg-tx\nmz-gs\nnl-ct\ncn-oe\nxj-ri\nya-ku\nnw-mh\nvh-ff\nft-hz\nen-md\nps-fp\naf-rx\nvx-kx\nkv-fd\nkr-lf\nae-rg\nsp-vw\nvn-zr\nea-pi\nat-vw\nrw-ax\nkg-vh\nxy-cv\nca-gw\nem-nn\nhj-en\ngw-ra\nfr-cy\ned-wu\nyf-tw\nuo-lz\ngc-pq\ntw-ux\nqy-kg\ncx-fo\nit-ly\nuj-mg\nrp-po\nsq-yv\nzh-zs\nth-ne\nes-fe\nrn-nv\naa-gj\nzb-aa\nwt-kl\nwu-uo\nbb-ce\nby-bt\nqb-gv\nbp-es\nbd-tx\nma-cq\nyt-qu\nuu-mn\nke-fa\nmx-jn\ndq-ew\nax-ow\nhv-dx\nyh-sx\ngx-ry\njz-jv\nsb-wj\ndo-ok\ngj-qn\nbr-ri\nlu-zw\nsb-ge\nkg-ao\nuu-fp\nus-xh\ndd-jb\nxp-wi\ncf-cj\nhm-zj\nle-sa\nwf-ty\nqx-xq\noi-rr\nbl-og\nmq-hj\ndw-xi\naw-ap\nsk-cs\nwu-yq\ngm-zq\nna-ry\nwp-pj\nne-gy\ndt-yn\nau-bm\nrk-ur\nnm-oi\naf-zm\ncd-ss\ndj-ez\ncf-oy\nce-md\nth-kz\nnt-cd\nrm-iz\njz-fs\nni-qo\njx-do\nzy-xe\nls-uq\nsy-jt\nwa-xh\nlf-lv\nys-jt\nij-wg\njw-mw\nbk-ef\nyx-ek\nvr-cm\njv-sk\ndw-ej\nmo-pq\nov-pl\nfz-ge\nmt-ep\ncq-hz\nza-zc\nlj-uy\nrv-ae\nse-ln\nkw-ze\nwo-ln\nvo-zw\nwd-fd\nxo-pl\nmx-gc\nln-lr\nsy-rw\ngy-fs\nzy-ea\nkc-er\nfl-l" <> ...}
+
```
+
+
```elixir
+
connections =
+
puzzle_input
+
|> String.split("\n", trim: true)
+
|> Enum.map(fn <<a::binary-2, "-", b::binary-2>> ->
+
{a, b}
+
end)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
[
+
{"on", "za"},
+
{"bp", "hs"},
+
{"vc", "bg"},
+
{"tm", "us"},
+
{"zf", "ox"},
+
{"ib", "lc"},
+
{"uo", "zs"},
+
{"ov", "qj"},
+
{"ll", "eb"},
+
{"iy", "tq"},
+
{"bg", "by"},
+
{"un", "ix"},
+
{"gi", "do"},
+
{"rv", "ou"},
+
{"yp", "qu"},
+
{"qb", "um"},
+
{"qs", "dn"},
+
{"ru", "ro"},
+
{"et", "fw"},
+
{"yx", "jt"},
+
{"ns", "iz"},
+
{"od", "rc"},
+
{"ny", "ap"},
+
{"vb", "fd"},
+
{"wf", "wr"},
+
{"yh", "qy"},
+
{"fa", "ct"},
+
{"qo", "fv"},
+
{"ig", "jv"},
+
{"qi", "ff"},
+
{"nj", "ii"},
+
{"sa", "gg"},
+
{"cp", "un"},
+
{"ez", "kh"},
+
{"vs", "du"},
+
{"gp", "qs"},
+
{"pt", "qj"},
+
{"yp", "my"},
+
{"jf", "sz"},
+
{"yo", "gm"},
+
{"fn", "xw"},
+
{"iu", "xr"},
+
{"se", "ox"},
+
{"mw", "ie"},
+
{"fw", "br"},
+
{"xy", "iu"},
+
{"qw", "wi"},
+
{"xc", "dq"},
+
{"vb", ...},
+
{...},
+
...
+
]
+
```
+
+
```elixir
+
party =
+
Graph.new(type: :undirected)
+
|> Graph.add_edges(connections)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
#Graph<type: undirected, num_vertices: 520, num_edges: 3380>
+
```
+
+
```elixir
+
cliques = Graph.cliques(party)
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
[
+
["yf", "dk", "dy", "hm", "vx", "zj", "ec", "eg", "ko", "kx", "tw", "ux"],
+
["yf", "dk", "hm", "vx", "zj", "ec", "eg", "qg", "ko", "kx", "tw", "ux"],
+
["yf", "ob"],
+
["xa", "wl", "lx", "lq", "jy", "in", "hy", "lw", "qd", "fu", "ub", "og"],
+
["xa", "wl", "lx", "jy", "bl", "in", "hy", "lw", "qd", "fu", "ub", "og"],
+
["xa", "wi"],
+
["bd", "cb", "it", "ut", "fq", "hs", "ur", "ly", "tx", "yg", "ui", "gl"],
+
["bd", "cb", "it", "ut", "fq", "ur", "ly", "tx", "yg", "ui", "gl", "rk"],
+
["bd", "bu"],
+
["nm", "qb", "gv", "nf", "oi", "tg", "uj", "yd", "rr", "tr", "vv", "mg"],
+
["nm", "qb", "gv", "nf", "oi", "tg", "uj", "yd", "rr", "tr", "vv", "zp"],
+
["nm", "ge"],
+
["dk", "jn"],
+
["cn", "lh", "di", "xm", "cm", "oe", "vi", "ho", "fg", "mt", "io", "dv"],
+
["cn", "zt"],
+
["cn", "jl"],
+
["qp", "xd"],
+
["qp", "zq", "qk", "uu", "cy", "fp", "ay", "yo", "gm", "vj", "ps", "fr"],
+
["qp", "zq", "qk", "uu", "cy", "ay", "yo", "gm", "vj", "jl", "ps", "fr"],
+
["xq", "qx", "rg", "wc", "um", "rv", "ae", "kw", "lj", "ze", "wq", "ou"],
+
["xq", "kg"],
+
["xq", "qo"],
+
["ti", "et", "bu", "xk", "ix", "fw", "un", "ri", "cp", "br", "gr", "ch"],
+
["ti", "et", "bu", "xk", "fw", "un", "ri", "cp", "br", "gr", "ch", "yw"],
+
["ti", "ab"],
+
["nh", "hv", "id", "ap", "fv", "ny", "pb", "ni", "aw", "nx", "vk", "qo"],
+
["nh", "pj"],
+
["nh", "lk"],
+
["ys", "ib", "dg", "vr", "yx", "jt", "ek", "lt", "sy", "vm", "lc", "rw"],
+
["ys", "ib", "dg", "yx", "jt", "pg", "ek", "lt", "sy", "vm", "lc", "rw"],
+
["ys", "tl"],
+
["cb", "ha"],
+
["ue", "dd", "kd", "zm", "kt", "il", "af", "xx", "vl", "xl", "jd", "rx"],
+
["ue", "dd", "kd", "kt", "il", "af", "xx", "vl", "xl", "jd", "rx", "pz"],
+
["ue", "bh"],
+
["jg", "cx", "fo", "ro", "ru", "oo", "dh", "as", "zx", "ke", "om", "gu"],
+
["jg", "cx", "fo", "ro", "ru", "dh", "as", "sm", "zx", "ke", "om", "gu"],
+
["jg", "cy"],
+
["bz", "fz", "qi", "tn", "xg", "dc", "ge", "sb", "df", "hu", "vd", ...],
+
["bz", "ae"],
+
["bz", "gm"],
+
["im", "dz", "ab", "sz", "ej", "mz", "pv", "rj", ...],
+
["im", "dz", "sz", "ej", "mz", "pv", "rj", ...],
+
["im", "ps"],
+
["sw", "gc", "si", "aj", "is", ...],
+
["sw", "gc", "si", "aj", ...],
+
["sw", "fn"],
+
["cg", "zt", ...],
+
["cg", ...],
+
[...],
+
...
+
]
+
```
+
+
## Part 1
+
+
```elixir
+
cliques
+
|> Stream.flat_map(fn clique ->
+
if length(clique) >= 3 do
+
Combination.combine(clique, 3)
+
else
+
[]
+
end
+
end)
+
|> Stream.filter(fn clique -> Enum.any?(clique, &String.starts_with?(&1, "t")) end)
+
|> MapSet.new()
+
|> MapSet.size()
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
1248
+
```
+
+
## Part 2
+
+
```elixir
+
cliques
+
|> Enum.max_by(&length/1)
+
|> Enum.sort()
+
|> Enum.join(",")
+
```
+
+
<!-- livebook:{"output":true} -->
+
+
```
+
"aa,cf,cj,cv,dr,gj,iu,jh,oy,qr,xr,xy,zb"
+
```
+
+
<!-- livebook:{"offset":9387,"stamp":{"token":"XCP.YMMjV81j86GOTx0hGVW-U0w7aqvuBdig59tmj2pqELbNIP0HXjbZA1WSQwLRMCUIuzZ1PLs6_0ehAVdgp7sj4Wuc6QaM8KCZ3j-zJrTUmr2_hxaACLOnkijsz6m2hIS8E6Q","version":2}} -->