this repo has no description

2024 day 15-23

hauleth.dev 89e91428 6dce628d

verified
+11 -3
2024/day14.livemd
··· 175 175 176 176 ```elixir 177 177 {tree, steps} = 178 - 0..10_000 178 + Stream.from_index() 179 179 |> Task.async_stream( 180 180 fn step -> 181 181 robots = Robot.walk(robots, room, step) ··· 199 199 Image.new!(w, h) 200 200 |> Image.mutate(fn img -> 201 201 for %{pos: {x, y}} <- tree do 202 - Image.Draw.point(img, x, y, color: :white) 202 + # Add some festivity 203 + color = 204 + if abs(:math.sin(x + y)) < 0.5 do 205 + :red 206 + else 207 + :green 208 + end 209 + 210 + Image.Draw.point(img, x, y, color: color) 203 211 end 204 212 205 213 {:ok, img} ··· 208 216 |> Image.resize!(4, interpolate: :nearest) 209 217 ``` 210 218 211 - <!-- livebook:{"offset":9077,"stamp":{"token":"XCP.gUbmyoJABRufOfOt0ZeaLvsGKeSMKLrJo_tuzD9IPlUw8bA8QTK0V6_qDCVmNX02724bl4wTSGMbDl9LH4-qrXfejoCDaxokcatvdIiDcPrwE0PpJ7V34ORcoI0URmYd_Mo","version":2}} --> 219 + <!-- livebook:{"offset":9213,"stamp":{"token":"XCP.bbViODF6Z4_TcNSzpaXWzuFflurdyZ5JsvKHJZr6NjgJ4MQaH2OorTxA-YR5uDBN5HxiB0uC5hX0vi-Kgdm26HMcOubYpE_c39bjuPfPH_BH4SVxLeEac5c8aaRtPdt7CJk","version":2}} -->
+395
2024/day15.livemd
··· 1 + <!-- livebook:{"persist_outputs":true} --> 2 + 3 + # Day 15 4 + 5 + ```elixir 6 + Mix.install([:kino_aoc]) 7 + ``` 8 + 9 + ## Section 10 + 11 + <!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIxNSIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} --> 12 + 13 + ```elixir 14 + {:ok, puzzle_input} = 15 + KinoAOC.download_puzzle("2024", "15", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION")) 16 + ``` 17 + 18 + <!-- livebook:{"output":true} --> 19 + 20 + ``` 21 + {:ok, 22 + "##################################################\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<^^^>" <> ...} 23 + ``` 24 + 25 + ```elixir 26 + #puzzle_input = 27 + """ 28 + ########## 29 + #..O..O.O# 30 + #......O.# 31 + #.OO..O.O# 32 + #..O@..O.# 33 + #O#..O...# 34 + #O..O..O.# 35 + #.OO.O.OO# 36 + #....O...# 37 + ########## 38 + 39 + <vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^ 40 + vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v 41 + ><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv< 42 + <<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^ 43 + ^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^>< 44 + ^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^ 45 + >^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^ 46 + <><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<> 47 + ^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v> 48 + v^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^ 49 + """ 50 + 51 + #puzzle_input = 52 + """ 53 + ######## 54 + #..O.O.# 55 + ##@.O..# 56 + #...O..# 57 + #.#.O..# 58 + #...O..# 59 + #......# 60 + ######## 61 + 62 + <^^>>>vv<v>>v<< 63 + """ 64 + ``` 65 + 66 + <!-- livebook:{"output":true} --> 67 + 68 + ``` 69 + warning: outdented heredoc line. The contents inside the heredoc should be indented at the same level as the closing """. The following is forbidden: 70 + 71 + def text do 72 + """ 73 + contents 74 + """ 75 + end 76 + 77 + Instead make sure the contents are indented as much as the heredoc closing: 78 + 79 + def text do 80 + """ 81 + contents 82 + """ 83 + end 84 + 85 + The current heredoc line is indented too little 86 + └─ Workspace/hauleth/advent-of-code/2024/day15.livemd#cell:7w6bq5lw7vctw7mk:3:3 87 + 88 + warning: outdented heredoc line. The contents inside the heredoc should be indented at the same level as the closing """. The following is forbidden: 89 + 90 + def text do 91 + """ 92 + contents 93 + """ 94 + end 95 + 96 + Instead make sure the contents are indented as much as the heredoc closing: 97 + 98 + def text do 99 + """ 100 + contents 101 + """ 102 + end 103 + 104 + The current heredoc line is indented too little 105 + └─ Workspace/hauleth/advent-of-code/2024/day15.livemd#cell:7w6bq5lw7vctw7mk:28:3 106 + 107 + 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) 108 + └─ Workspace/hauleth/advent-of-code/2024/day15.livemd#cell:7w6bq5lw7vctw7mk:1 109 + 110 + ``` 111 + 112 + <!-- livebook:{"output":true} --> 113 + 114 + ``` 115 + "########\n#..O.O.#\n##@.O..#\n#...O..#\n#.#.O..#\n#...O..#\n#......#\n########\n\n<^^>>>vv<v>>v<<\n" 116 + ``` 117 + 118 + ```elixir 119 + [map, moves] = String.split(puzzle_input, "\n\n") 120 + ``` 121 + 122 + <!-- livebook:{"output":true} --> 123 + 124 + ``` 125 + ["##################################################\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##################################################", 126 + ">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" <> ...] 127 + ``` 128 + 129 + ```elixir 130 + %{robot: [robot], wall: walls, box: boxes} = 131 + map 132 + |> String.split("\n", trim: true) 133 + |> Enum.with_index() 134 + |> Enum.flat_map(fn {row, y} -> 135 + row 136 + |> String.to_charlist() 137 + |> Enum.with_index() 138 + |> Enum.reject(fn {kind, _} -> kind == ?. end) 139 + |> Enum.map(fn {kind, x} -> 140 + kind = 141 + case kind do 142 + ?# -> :wall 143 + ?O -> :box 144 + ?@ -> :robot 145 + end 146 + 147 + {{x, y}, kind} 148 + end) 149 + end) 150 + |> Enum.group_by(&elem(&1, 1), &elem(&1, 0)) 151 + 152 + walls = MapSet.new(walls) 153 + boxes = MapSet.new(boxes) 154 + ``` 155 + 156 + <!-- livebook:{"output":true} --> 157 + 158 + ``` 159 + MapSet.new([ 160 + {38, 2}, 161 + {29, 26}, 162 + {9, 34}, 163 + {47, 38}, 164 + {47, 44}, 165 + {22, 37}, 166 + {19, 38}, 167 + {27, 21}, 168 + {19, 22}, 169 + {16, 10}, 170 + {16, 38}, 171 + {35, 26}, 172 + {10, 32}, 173 + {36, 14}, 174 + {28, 48}, 175 + {17, 30}, 176 + {32, 18}, 177 + {40, 35}, 178 + {6, 23}, 179 + {28, 37}, 180 + {29, 47}, 181 + {29, 40}, 182 + {29, 10}, 183 + {6, 42}, 184 + {23, 46}, 185 + {10, 33}, 186 + {4, 46}, 187 + {43, 47}, 188 + {12, 8}, 189 + {3, 16}, 190 + {15, 3}, 191 + {20, 46}, 192 + {33, 48}, 193 + {35, 6}, 194 + {41, 9}, 195 + {25, 29}, 196 + {1, 2}, 197 + {3, 30}, 198 + {8, 5}, 199 + {18, 37}, 200 + {37, 43}, 201 + {3, 47}, 202 + {30, 26}, 203 + {41, 31}, 204 + {4, 15}, 205 + {33, 40}, 206 + {6, 21}, 207 + {5, 26}, 208 + {1, ...}, 209 + {...}, 210 + ... 211 + ]) 212 + ``` 213 + 214 + ```elixir 215 + moves = moves |> String.to_charlist() |> Enum.reject(& &1 not in ~c"^>v<") 216 + ``` 217 + 218 + <!-- livebook:{"output":true} --> 219 + 220 + ``` 221 + ~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" ++ ... 222 + ``` 223 + 224 + ## Part 1 225 + 226 + ```elixir 227 + defmodule Warehouse.A do 228 + def walk(start, path, walls, boxes) do 229 + Enum.reduce(path, {start, boxes}, fn dir, {pos, boxes} -> 230 + move(pos, walls, boxes, dir) 231 + end) 232 + |> elem(1) 233 + end 234 + 235 + def move({x, y}, walls, boxes, dir) do 236 + next = next({x, y}, dir) 237 + 238 + cond do 239 + next in walls -> 240 + {{x, y}, boxes} 241 + 242 + next in boxes -> 243 + if new_boxes = move_box(next, boxes, walls, dir) do 244 + {next, new_boxes} 245 + else 246 + {{x, y}, boxes} 247 + end 248 + 249 + true -> 250 + {next, boxes} 251 + end 252 + end 253 + 254 + defp move_box(pos, boxes, walls, dir) do 255 + next = next(pos, dir) 256 + cond do 257 + next in walls -> nil 258 + 259 + next in boxes -> 260 + if new_boxes = move_box(next, boxes, walls, dir) do 261 + new_boxes |> MapSet.delete(pos) |> MapSet.put(next) 262 + end 263 + 264 + true -> 265 + boxes |> MapSet.delete(pos) |> MapSet.put(next) 266 + end 267 + end 268 + 269 + defp next({x, y}, ?^), do: {x, y - 1} 270 + defp next({x, y}, ?>), do: {x + 1, y} 271 + defp next({x, y}, ?v), do: {x, y + 1} 272 + defp next({x, y}, ?<), do: {x - 1, y} 273 + end 274 + ``` 275 + 276 + <!-- livebook:{"output":true} --> 277 + 278 + ``` 279 + {:module, Warehouse.A, <<70, 79, 82, 49, 0, 0, 14, ...>>, {:next, 2}} 280 + ``` 281 + 282 + ```elixir 283 + robot 284 + |> Warehouse.A.walk(moves, walls, boxes) 285 + |> Enum.map(fn {x, y} -> x + y * 100 end) 286 + |> Enum.sum() 287 + ``` 288 + 289 + <!-- livebook:{"output":true} --> 290 + 291 + ``` 292 + 1406628 293 + ``` 294 + 295 + ## Part 2 296 + 297 + ```elixir 298 + defmodule Warehouse.B do 299 + def resize({x, y}, walls, boxes) do 300 + start = {2 * x, y} 301 + 302 + walls = 303 + walls 304 + |> Enum.flat_map(fn {x, y} -> 305 + [{2 * x, y}, {2 * x + 1, y}] 306 + end) 307 + |> MapSet.new() 308 + 309 + boxes = 310 + boxes 311 + |> Enum.flat_map(fn {x, y} -> 312 + pos = [{2 * x, y}, {2 * x + 1, y}] 313 + box = %{p: pos} 314 + 315 + for p <- pos do 316 + {p, box} 317 + end 318 + end) 319 + 320 + {start, walls, boxes} 321 + end 322 + 323 + def walk(start, path, walls, boxes) do 324 + Enum.reduce(path, {start, boxes}, fn dir, {pos, boxes} -> 325 + move(pos, walls, boxes, dir) 326 + end) 327 + |> elem(1) 328 + end 329 + 330 + def move({x, y}, walls, boxes, dir) do 331 + next = next({x, y}, dir) 332 + 333 + cond do 334 + next in walls -> 335 + {{x, y}, boxes} 336 + 337 + box = boxes[next] -> 338 + if new_boxes = move_box(box, boxes, walls, dir) do 339 + {next, new_boxes} 340 + else 341 + {{x, y}, boxes} 342 + end 343 + 344 + true -> 345 + {next, boxes} 346 + end 347 + end 348 + 349 + defp move_box(%{p: pos}, boxes, walls, dir) do 350 + next = next(pos, dir) 351 + 352 + cond do 353 + Enum.any?(pos, & &1 in walls) -> 354 + throw(:wall) 355 + 356 + (next_boxes = select_boxes_at(pos, boxes)) != [] -> 357 + if new_boxes = move_box(next, boxes, walls, dir) do 358 + new_boxes |> MapSet.delete(pos) |> MapSet.put(next) 359 + end 360 + 361 + true -> 362 + boxes |> Map.drop(pos) |> MapSet.put(next) 363 + end 364 + catch 365 + :throw, :wall -> nil 366 + end 367 + 368 + defp select_boxes_at(pos, boxes) do 369 + boxes 370 + |> Map.take(pos) 371 + |> Enum.uniq() 372 + end 373 + 374 + defp next({x, y}, ?^), do: {x, y - 1} 375 + defp next({x, y}, ?>), do: {x + 1, y} 376 + defp next({x, y}, ?v), do: {x, y + 1} 377 + defp next({x, y}, ?<), do: {x - 1, y} 378 + end 379 + ``` 380 + 381 + <!-- livebook:{"output":true} --> 382 + 383 + ``` 384 + warning: variable "next_boxes" is unused (if the variable is not meant to be used, prefix it with an underscore) 385 + └─ Workspace/hauleth/advent-of-code/2024/day15.livemd#cell:3ajets4kgmkyknvu:59: Warehouse.B.move_box/4 386 + 387 + ``` 388 + 389 + <!-- livebook:{"output":true} --> 390 + 391 + ``` 392 + {:module, Warehouse.B, <<70, 79, 82, 49, 0, 0, 20, ...>>, {:next, 2}} 393 + ``` 394 + 395 + <!-- livebook:{"offset":23559,"stamp":{"token":"XCP.GtnzBtRKuk3dCuG1gVPqYVHJwR27FPAQixvDel9XY7YKKtIR-fLOYjYE9q5s_RDyt_V8hQtSWHWE0pTlg7ukiaTmklnlkowdbH-y0AJ21EtpRoXXQ3C48_7vRp_64BdLpHY","version":2}} -->
+303
2024/day16.livemd
··· 1 + <!-- livebook:{"persist_outputs":true} --> 2 + 3 + # Day 16 4 + 5 + ```elixir 6 + Mix.install([:kino_aoc, :image]) 7 + ``` 8 + 9 + ## Setup 10 + 11 + <!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIxNiIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} --> 12 + 13 + ```elixir 14 + {:ok, puzzle_input} = 15 + KinoAOC.download_puzzle("2024", "16", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION")) 16 + ``` 17 + 18 + <!-- livebook:{"output":true} --> 19 + 20 + ``` 21 + {:ok, 22 + "#############################################################################################################################################\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#.#.#########.#######.#.#.#.###.###.###.#.###########.###.#.###.#.###.#.###.#####.#.#########.#.#.###.#.#.###.#.#.#.#.#." <> ...} 23 + ``` 24 + 25 + ```elixir 26 + %{?# => walls, ?S => [start], ?E => [finish]} = 27 + puzzle_input 28 + |> String.trim() 29 + |> String.split("\n", trim: true) 30 + |> Enum.with_index() 31 + |> Enum.flat_map(fn {row, y} -> 32 + row 33 + |> String.trim() 34 + |> String.to_charlist() 35 + |> Enum.with_index() 36 + |> Enum.map(fn {char, x} -> 37 + {{x, y}, char} 38 + end) 39 + end) 40 + |> Enum.group_by(&elem(&1, 1), &elem(&1, 0)) 41 + 42 + walls = MapSet.new(walls) 43 + ``` 44 + 45 + <!-- livebook:{"output":true} --> 46 + 47 + ``` 48 + MapSet.new([ 49 + {76, 13}, 50 + {112, 138}, 51 + {38, 2}, 52 + {124, 56}, 53 + {83, 76}, 54 + {140, 11}, 55 + {100, 134}, 56 + {75, 140}, 57 + {103, 106}, 58 + {68, 134}, 59 + {124, 60}, 60 + {35, 30}, 61 + {2, 132}, 62 + {8, 50}, 63 + {78, 98}, 64 + {101, 62}, 65 + {98, 136}, 66 + {95, 56}, 67 + {74, 12}, 68 + {102, 74}, 69 + {22, 38}, 70 + {14, 86}, 71 + {12, 135}, 72 + {86, 10}, 73 + {29, 26}, 74 + {4, 81}, 75 + {31, 42}, 76 + {9, 34}, 77 + {137, 16}, 78 + {86, 138}, 79 + {90, 0}, 80 + {14, 122}, 81 + {120, 42}, 82 + {102, 57}, 83 + {84, 102}, 84 + {138, 124}, 85 + {0, 101}, 86 + {116, 96}, 87 + {54, 138}, 88 + {18, 134}, 89 + {82, 60}, 90 + {15, 92}, 91 + {58, 58}, 92 + {78, 75}, 93 + {75, 0}, 94 + {16, 73}, 95 + {76, 2}, 96 + {58, 84}, 97 + {138, ...}, 98 + {...}, 99 + ... 100 + ]) 101 + ``` 102 + 103 + ```elixir 104 + {_, {w, h}} = Enum.min_max(walls) 105 + 106 + w = w + 1 107 + h = h + 1 108 + ``` 109 + 110 + <!-- livebook:{"output":true} --> 111 + 112 + ``` 113 + 141 114 + ``` 115 + 116 + ```elixir 117 + put_in(%{}, [Access.key(:a, %{}), :b], 10) 118 + ``` 119 + 120 + <!-- livebook:{"output":true} --> 121 + 122 + ``` 123 + %{a: %{b: 10}} 124 + ``` 125 + 126 + ```elixir 127 + defmodule Race.B do 128 + @turns ~w'^ > v <'a 129 + 130 + defguardp score(elements, pos, dir) when :erlang.map_get({pos, dir}, elements).score 131 + 132 + def search_paths(start, finish, dir \\ :>, walls) when dir in @turns do 133 + result = do_search([{0, [{start, dir}]}], walls, %{}) 134 + 135 + %{paths: visited, score: score} = result[{finish, :>}] 136 + 137 + all = get_all(visited, result) 138 + 139 + {score, all} 140 + end 141 + 142 + def get_all(path, seen) do 143 + Enum.reduce(path, MapSet.new(), fn p, acc -> 144 + path = MapSet.new(seen[p].paths, fn {p, _} -> p end) 145 + MapSet.union(acc, path) 146 + end) 147 + end 148 + 149 + def do_search([], _, visited), do: visited 150 + 151 + def do_search([{cost, [{curr, dir} | _] = path} | rest], walls, visited) 152 + when cost == score(visited, curr, dir) do 153 + visited = Map.update!(visited, {curr, dir}, &%{&1 | paths: path}) 154 + 155 + do_search(rest, walls, visited) 156 + end 157 + 158 + def do_search([{cost, [{curr, prev} | _] = path} | rest], walls, visited) 159 + when not is_map_key(visited, {curr, prev}) 160 + when cost < score(visited, curr, prev) do 161 + visited = Map.put(visited, {curr, prev}, %{score: cost, paths: path}) 162 + 163 + @turns 164 + |> Enum.map(fn dir -> {cost + cost(prev, dir), [{step(curr, dir), dir} | path]} end) 165 + |> Enum.reject(fn {_cost, [{pos, _} | _]} -> pos in walls end) 166 + |> sort_merge(rest) 167 + |> do_search(walls, visited) 168 + end 169 + 170 + def do_search([{_, [_curr | _]} | rest], walls, visited), 171 + do: do_search(rest, walls, visited) 172 + 173 + # Going straight is cheap and turning is costly 174 + defp cost(a, a), do: 1 175 + defp cost(_, _), do: 1001 176 + 177 + defp step({x, y}, :^), do: {x, y - 1} 178 + defp step({x, y}, :>), do: {x + 1, y} 179 + defp step({x, y}, :v), do: {x, y + 1} 180 + defp step({x, y}, :<), do: {x - 1, y} 181 + 182 + defp sort_merge([], bs), do: bs 183 + defp sort_merge(as, []), do: as 184 + 185 + defp sort_merge([a | as], [b | bs]) do 186 + if a < b do 187 + [a | sort_merge(as, [b | bs])] 188 + else 189 + [b | sort_merge([a | as], bs)] 190 + end 191 + end 192 + end 193 + ``` 194 + 195 + <!-- livebook:{"output":true} --> 196 + 197 + ``` 198 + {:module, Race.B, <<70, 79, 82, 49, 0, 0, 23, ...>>, {:sort_merge, 2}} 199 + ``` 200 + 201 + ```elixir 202 + {score, paths} = Race.B.search_paths(start, finish, walls) 203 + ``` 204 + 205 + <!-- livebook:{"output":true} --> 206 + 207 + ``` 208 + {134588, 209 + MapSet.new([ 210 + {77, 129}, 211 + {17, 138}, 212 + {17, 137}, 213 + {37, 139}, 214 + {19, 137}, 215 + {100, 131}, 216 + {139, 68}, 217 + {14, 139}, 218 + {79, 128}, 219 + {19, 138}, 220 + {50, 137}, 221 + {139, 67}, 222 + {137, 104}, 223 + {137, 117}, 224 + {131, 49}, 225 + {107, 125}, 226 + {3, 127}, 227 + {135, 64}, 228 + {4, 131}, 229 + {21, 134}, 230 + {63, 127}, 231 + {101, 124}, 232 + {5, 139}, 233 + {125, 14}, 234 + {129, 48}, 235 + {139, 70}, 236 + {21, 119}, 237 + {17, 129}, 238 + {137, 120}, 239 + {17, 136}, 240 + {131, 120}, 241 + {32, 139}, 242 + {133, 21}, 243 + {102, 123}, 244 + {12, 111}, 245 + {123, 19}, 246 + {112, 127}, 247 + {73, 129}, 248 + {7, 116}, 249 + {127, 22}, 250 + {7, 137}, 251 + {9, 131}, 252 + {24, 133}, 253 + {137, 95}, 254 + {8, 133}, 255 + {134, 7}, 256 + {129, ...}, 257 + {...}, 258 + ... 259 + ])} 260 + ``` 261 + 262 + ## Part 1 263 + 264 + ```elixir 265 + score 266 + ``` 267 + 268 + <!-- livebook:{"output":true} --> 269 + 270 + ``` 271 + 134588 272 + ``` 273 + 274 + ```elixir 275 + Image.new!(w, h) 276 + |> Image.mutate(fn img -> 277 + for {x, y} <- walls do 278 + Image.Draw.point(img, x, y, color: [128, 0, 0]) 279 + end 280 + 281 + for {x, y} <- paths do 282 + Image.Draw.point(img, x, y, color: [0, 255, 0]) 283 + end 284 + 285 + img 286 + end) 287 + |> elem(1) 288 + |> Image.resize!(6, interpolate: :nearest) 289 + ``` 290 + 291 + ## Part 2 292 + 293 + ```elixir 294 + MapSet.size(paths) 295 + ``` 296 + 297 + <!-- livebook:{"output":true} --> 298 + 299 + ``` 300 + 625 301 + ``` 302 + 303 + <!-- livebook:{"offset":9337,"stamp":{"token":"XCP.AVI7h-Nq9jZKx9YmL5qYerJkeKKqddhzKrKUkab-HwNDUM8nQItD1O_rd2ROsJxc96gwIzwrMAixlIdLeZAgOVhtCs22LZM44Wl1VwcpYbg3RNCdgwIjqGheO5YrCGrEGJc","version":2}} -->
+206
2024/day17.livemd
··· 1 + <!-- livebook:{"persist_outputs":true} --> 2 + 3 + # Day 17 4 + 5 + ```elixir 6 + Mix.install([:kino_aoc]) 7 + ``` 8 + 9 + ## Section 10 + 11 + <!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIxNyIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} --> 12 + 13 + ```elixir 14 + {:ok, puzzle_input} = 15 + KinoAOC.download_puzzle("2024", "17", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION")) 16 + ``` 17 + 18 + <!-- livebook:{"output":true} --> 19 + 20 + ``` 21 + {:ok, 22 + "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"} 23 + ``` 24 + 25 + ```elixir 26 + defmodule Computer do 27 + @instructions ~w[adv bxl bst jnz bxc out bdv cdv]a 28 + |> Enum.with_index() 29 + |> Map.new(fn {name, ins} -> {ins, name} end) 30 + 31 + def load(opcodes) do 32 + opcodes 33 + |> Enum.chunk_every(2) 34 + |> Enum.map(fn [opcode, op] -> 35 + {@instructions[opcode], op} 36 + end) 37 + |> List.to_tuple() 38 + end 39 + 40 + def process(program, reg) do 41 + reg = Map.merge(%{a: 0, b: 0, c: 0}, Map.new(reg)) 42 + do_process(program, 0, reg, []) 43 + end 44 + 45 + defp do_process(program, idx, _reg, out) when idx >= tuple_size(program) do 46 + Enum.reverse(out) 47 + end 48 + 49 + defp do_process(program, idx, reg, out) do 50 + ins = elem(program, idx) 51 + 52 + case compute(ins, reg) do 53 + new_reg when is_map(new_reg) -> 54 + do_process(program, idx + 1, new_reg, out) 55 + 56 + {:out, op} -> 57 + do_process(program, idx + 1, reg, [op | out]) 58 + 59 + {:jump, op} -> 60 + do_process(program, op, reg, out) 61 + end 62 + end 63 + 64 + def compute({:adv, op}, reg), 65 + do: %{reg | a: div(reg.a, 2 ** combo(op, reg))} 66 + 67 + def compute({:bdv, op}, reg), 68 + do: %{reg | b: div(reg.a, 2 ** combo(op, reg))} 69 + 70 + def compute({:cdv, op}, reg), 71 + do: %{reg | c: div(reg.a, 2 ** combo(op, reg))} 72 + 73 + def compute({:bxl, op}, reg), 74 + do: %{reg | b: Bitwise.bxor(reg.b, op)} 75 + 76 + def compute({:bxc, _op}, reg), 77 + do: %{reg | b: Bitwise.bxor(reg.b, reg.c)} 78 + 79 + def compute({:bst, op}, reg), 80 + do: %{reg | b: Bitwise.band(combo(op, reg), 0b111)} 81 + 82 + def compute({:out, op}, reg), 83 + do: {:out, Bitwise.band(combo(op, reg), 0b111)} 84 + 85 + def compute({:jnz, op}, reg) do 86 + if reg.a != 0 do 87 + {:jump, op} 88 + else 89 + reg 90 + end 91 + end 92 + 93 + defp combo(v, _) when v in 0..3, do: v 94 + defp combo(4, %{a: a}), do: a 95 + defp combo(5, %{b: b}), do: b 96 + defp combo(6, %{c: c}), do: c 97 + end 98 + ``` 99 + 100 + <!-- livebook:{"output":true} --> 101 + 102 + ``` 103 + {:module, Computer, <<70, 79, 82, 49, 0, 0, 21, ...>>, {:combo, 2}} 104 + ``` 105 + 106 + ```elixir 107 + [ 108 + "Register A: " <> a, 109 + "Register B: " <> b, 110 + "Register C: " <> c, 111 + "Program: " <> raw_code 112 + ] = String.split(puzzle_input, "\n", trim: true) 113 + 114 + reg = %{ 115 + a: String.to_integer(a), 116 + b: String.to_integer(b), 117 + c: String.to_integer(c) 118 + } |> dbg() 119 + 120 + code = 121 + raw_code 122 + |> String.split(",") 123 + |> Enum.map(&String.to_integer/1) 124 + 125 + program = Computer.load(code) 126 + ``` 127 + 128 + <!-- livebook:{"output":true} --> 129 + 130 + ``` 131 + %{a: 66245665, b: 0, c: 0} 132 + ``` 133 + 134 + <!-- livebook:{"output":true} --> 135 + 136 + ``` 137 + {{:bst, 4}, {:bxl, 7}, {:cdv, 5}, {:bxl, 7}, {:bxc, 6}, {:adv, 3}, {:out, 5}, {:jnz, 0}} 138 + ``` 139 + 140 + ## Part 1 141 + 142 + ```elixir 143 + out = Computer.process(program, reg) 144 + ``` 145 + 146 + <!-- livebook:{"output":true} --> 147 + 148 + ``` 149 + [1, 4, 6, 1, 6, 4, 3, 0, 3] 150 + ``` 151 + 152 + ```elixir 153 + IO.puts(Enum.join(out, ",")) 154 + ``` 155 + 156 + <!-- livebook:{"output":true} --> 157 + 158 + ``` 159 + 1,4,6,1,6,4,3,0,3 160 + ``` 161 + 162 + <!-- livebook:{"output":true} --> 163 + 164 + ``` 165 + :ok 166 + ``` 167 + 168 + ## Part 2 169 + 170 + ```elixir 171 + defmodule Quine do 172 + def find(program, target) do 173 + do_find(program, Enum.reverse(target), Enum.to_list(0..7)) 174 + end 175 + 176 + def do_find(_program, [], out), do: out 177 + 178 + def do_find(program, [n | rest], out) do 179 + potential = 180 + for a <- out, 181 + i <- 0..7, 182 + hd(Computer.process(program, a: a * 8 + i)) == n, 183 + do: a * 8 + i 184 + 185 + do_find(program, rest, potential) 186 + end 187 + end 188 + ``` 189 + 190 + <!-- livebook:{"output":true} --> 191 + 192 + ``` 193 + {:module, Quine, <<70, 79, 82, 49, 0, 0, 10, ...>>, {:do_find, 3}} 194 + ``` 195 + 196 + ```elixir 197 + Quine.find(program, code) |> Enum.min() 198 + ``` 199 + 200 + <!-- livebook:{"output":true} --> 201 + 202 + ``` 203 + 265061364597659 204 + ``` 205 + 206 + <!-- livebook:{"offset":4021,"stamp":{"token":"XCP.PwUWTErrjClVJj6ZS87ZLrfbzleELwxqD__HBvfB1y_Yc633Wj72_Jigo2Z3T7V2ONi1nVguQ_AE_NSyLCF5sjSmWldUKuW294o_wsQqiM_gKhXOjSLzJOnslN9iIEFIEww","version":2}} -->
+194
2024/day18.livemd
··· 1 + <!-- livebook:{"persist_outputs":true} --> 2 + 3 + # Day 18 4 + 5 + ```elixir 6 + Mix.install([:kino_aoc, :image]) 7 + ``` 8 + 9 + ## Section 10 + 11 + <!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIxOCIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} --> 12 + 13 + ```elixir 14 + {:ok, puzzle_input} = 15 + KinoAOC.download_puzzle("2024", "18", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION")) 16 + ``` 17 + 18 + <!-- livebook:{"output":true} --> 19 + 20 + ``` 21 + {:ok, 22 + "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" <> ...} 23 + ``` 24 + 25 + ```elixir 26 + bytes = 27 + puzzle_input 28 + |> String.split("\n", trim: true) 29 + |> Enum.map(fn row -> 30 + [x, y] = String.split(row, ",") 31 + 32 + {String.to_integer(x), String.to_integer(y)} 33 + end) 34 + ``` 35 + 36 + <!-- livebook:{"output":true} --> 37 + 38 + ``` 39 + [ 40 + {21, 9}, 41 + {69, 53}, 42 + {31, 24}, 43 + {2, 9}, 44 + {50, 53}, 45 + {2, 5}, 46 + {3, 44}, 47 + {69, 49}, 48 + {25, 26}, 49 + {50, 31}, 50 + {68, 41}, 51 + {54, 67}, 52 + {19, 8}, 53 + {11, 9}, 54 + {9, 29}, 55 + {1, 31}, 56 + {13, 12}, 57 + {28, 5}, 58 + {69, 41}, 59 + {51, 66}, 60 + {53, 43}, 61 + {65, 35}, 62 + {40, 67}, 63 + {43, 13}, 64 + {21, 34}, 65 + {49, 3}, 66 + {65, 61}, 67 + {25, 9}, 68 + {39, 21}, 69 + {59, 37}, 70 + {11, 24}, 71 + {9, 30}, 72 + {63, 62}, 73 + {41, 69}, 74 + {6, 29}, 75 + {68, 47}, 76 + {45, 1}, 77 + {9, 1}, 78 + {11, 14}, 79 + {59, 19}, 80 + {67, 54}, 81 + {12, 5}, 82 + {41, 44}, 83 + {59, 45}, 84 + {3, 28}, 85 + {57, 42}, 86 + {7, 25}, 87 + {43, 11}, 88 + {31, ...}, 89 + {...}, 90 + ... 91 + ] 92 + ``` 93 + 94 + ```elixir 95 + Image.new!(71, 71, color: :forestgreen) 96 + |> Image.mutate(fn img -> 97 + for x <- 0..70, y <- 0..70, {x, y} in Enum.take(bytes, 1024) do 98 + Image.Draw.point(img, x, y, color: :firebrick) 99 + end 100 + 101 + img 102 + end) 103 + |> elem(1) 104 + |> Image.resize!(4, interpolate: :nearest) 105 + ``` 106 + 107 + ```elixir 108 + defmodule Memory do 109 + @d [{-1, 0}, {1, 0}, {0, -1}, {0, 1}] 110 + def find_path(from, to, bytes), do: do_find([{0, from}], to, MapSet.new(bytes), %{}) 111 + 112 + def do_find([], _, _, _), do: :none 113 + 114 + def do_find([{dist, to} | _], to, _, _visited), do: dist 115 + 116 + def do_find([{dist, {x, y} = p} | rest], {w, h} = to, bytes, visited) 117 + when not is_map_key(visited, p) 118 + when dist < :erlang.map_get(p, visited) 119 + do 120 + visited = Map.put(visited, p, dist) 121 + 122 + next = 123 + for {dx, dy} <- @d, 124 + (x + dx) in 0..w, 125 + (y + dy) in 0..h, 126 + p = {x + dx, y + dy}, 127 + p not in bytes, 128 + not is_map_key(visited, p), 129 + do: {dist + 1, p} 130 + 131 + next 132 + |> Enum.concat(rest) 133 + |> Enum.sort() 134 + |> do_find(to, bytes, visited) 135 + end 136 + 137 + def do_find([_ | rest], to, bytes, visited), do: do_find(rest, to, bytes, visited) 138 + end 139 + ``` 140 + 141 + <!-- livebook:{"output":true} --> 142 + 143 + ``` 144 + {:module, Memory, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:do_find, 4}} 145 + ``` 146 + 147 + ## Part 1 148 + 149 + ## Part 1 150 + 151 + ```elixir 152 + Memory.find_path({0, 0}, {70, 70}, Enum.take(bytes, 1024)) 153 + ``` 154 + 155 + <!-- livebook:{"output":true} --> 156 + 157 + ``` 158 + 250 159 + ``` 160 + 161 + ## Part 2 162 + 163 + ```elixir 164 + {x, y} = 165 + bytes 166 + |> Enum.reverse() 167 + |> Stream.unfold(fn 168 + [] -> nil 169 + [_ | rest] = curr -> {curr, rest} 170 + end) 171 + |> Enum.find_value(fn [pos | fallen] -> 172 + path = Memory.find_path({0, 0}, {70, 70}, fallen) 173 + 174 + if path != :none do 175 + pos 176 + end 177 + end) 178 + 179 + IO.puts("#{x},#{y}") 180 + ``` 181 + 182 + <!-- livebook:{"output":true} --> 183 + 184 + ``` 185 + 56,8 186 + ``` 187 + 188 + <!-- livebook:{"output":true} --> 189 + 190 + ``` 191 + :ok 192 + ``` 193 + 194 + <!-- livebook:{"offset":7984,"stamp":{"token":"XCP.CPT4l_BNbZGxGbR_fK_dYfzmCSPzRQfyiJPfaGWsNChhlNQI36bgn8XXEOmsc56qlDi2H-j-H4aYpxwTYXzlirEAyckZaTUuHdujjNaTLq1pQEjB3uTTMbVmMkdf1KvN3g0","version":2}} -->
+126
2024/day19.livemd
··· 1 + <!-- livebook:{"persist_outputs":true} --> 2 + 3 + # Day 19 4 + 5 + ```elixir 6 + Mix.install([:kino_aoc]) 7 + ``` 8 + 9 + ## Section 10 + 11 + <!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIxOSIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} --> 12 + 13 + ```elixir 14 + {:ok, puzzle_input} = 15 + KinoAOC.download_puzzle("2024", "19", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION")) 16 + ``` 17 + 18 + <!-- livebook:{"output":true} --> 19 + 20 + ``` 21 + {:ok, 22 + "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" <> ...} 23 + ``` 24 + 25 + ```elixir 26 + [towels | patterns] = String.split(puzzle_input, "\n", trim: true) 27 + 28 + towels = 29 + towels 30 + |> String.split(", ") 31 + ``` 32 + 33 + <!-- livebook:{"output":true} --> 34 + 35 + ``` 36 + ["rrbb", "rgrb", "rbbwbw", "ruw", "grwb", "wbg", "rrggu", "wugbb", "gwr", "rrgu", "wbbb", "bwrgugb", 37 + "rgww", "brrw", "gwwg", "brgbb", "ubbbu", "rbgruw", "bwub", "rru", "grbu", "grw", "bwrbr", 38 + "wrwbwu", "bgbr", "urrb", "bbb", "guggb", "gwuwuw", "ubu", "wbr", "bb", "ubwwrb", "bruuwu", "buw", 39 + "wrr", "gbgrr", "ggw", "ru", "wub", "uub", "gbrw", "uwrwrb", "uwuu", "wbbu", "gwu", "brrr", 40 + "grggur", "wugrbrw", "rwuurgg", ...] 41 + ``` 42 + 43 + ```elixir 44 + defmodule Towels do 45 + def count(target, towels) do 46 + possible = 47 + towels 48 + |> Enum.filter(&String.contains?(target, &1)) 49 + |> Enum.sort() 50 + 51 + do_count([{target, 1}], possible) 52 + end 53 + 54 + defp do_count([], _), do: 0 55 + defp do_count([{"", count} | _], _), do: count 56 + 57 + defp do_count([{target, score} | rest], towels) do 58 + towels 59 + |> Enum.reduce(rest, fn h, acc -> 60 + case target do 61 + ^h <> rest -> insert(acc, {rest, score}) 62 + _ -> acc 63 + end 64 + end) 65 + |> do_count(towels) 66 + end 67 + 68 + defp insert([{longest, _} = top | t], {text, _} = new) 69 + when byte_size(text) < byte_size(longest) do 70 + [top | insert(t, new)] 71 + end 72 + 73 + defp insert([{same, count} | t], {same, add}), 74 + do: [{same, count + add} | t] 75 + 76 + defp insert(t, new), do: [new | t] 77 + end 78 + ``` 79 + 80 + <!-- livebook:{"output":true} --> 81 + 82 + ``` 83 + {:module, Towels, <<70, 79, 82, 49, 0, 0, 12, ...>>, {:insert, 2}} 84 + ``` 85 + 86 + ```elixir 87 + ways = Enum.map(patterns, &Towels.count(&1, towels)) 88 + ``` 89 + 90 + <!-- livebook:{"output":true} --> 91 + 92 + ``` 93 + [6620974293119, 0, 35074418436970, 51307147748, 1695253946038, 12806406135744, 4413048272, 94 + 52744440529, 21533960420, 189633269638, 308662314336, 28930988196, 0, 0, 2335754782, 105920229640, 95 + 6464319032, 87075196587, 3720984622862, 2177845982468, 5546717284590, 8535586138, 834112091460, 96 + 6647844832, 21252082644, 5923960105816, 22344301329, 0, 0, 582455705324, 5162034941182, 97 + 368835846080, 30797645913, 0, 5315701730, 1953742172864, 910841596, 5512526952, 673582370688, 98 + 2029241325402, 13227054560, 81761616492, 0, 184404641300, 19196318323832, 773246829645, 99 + 97032877104, 0, 0, 0, ...] 100 + ``` 101 + 102 + ## Part 1 103 + 104 + ```elixir 105 + Enum.count(ways, & &1 > 0) 106 + ``` 107 + 108 + <!-- livebook:{"output":true} --> 109 + 110 + ``` 111 + 306 112 + ``` 113 + 114 + ## Part 2 115 + 116 + ```elixir 117 + Enum.sum(ways) 118 + ``` 119 + 120 + <!-- livebook:{"output":true} --> 121 + 122 + ``` 123 + 604622004681855 124 + ``` 125 + 126 + <!-- livebook:{"offset":7059,"stamp":{"token":"XCP.002DySFes8xjfbs_CVpc_QP75dkQcDFc5l37WdKhIJnRNctYjy9B2s3kTIev5coTlF4OCw1O-s8QuxIAU1HRaVoeZUHdw248FBapl1Ki5EyAYF1LHsn0MfuWbSukOOamT4I","version":2}} -->
+420
2024/day20.livemd
··· 1 + <!-- livebook:{"persist_outputs":true} --> 2 + 3 + # Day 20 4 + 5 + ```elixir 6 + Mix.install([:kino_aoc]) 7 + ``` 8 + 9 + ## Section 10 + 11 + <!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIyMCIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} --> 12 + 13 + ```elixir 14 + {:ok, puzzle_input} = 15 + KinoAOC.download_puzzle("2024", "20", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION")) 16 + ``` 17 + 18 + <!-- livebook:{"output":true} --> 19 + 20 + ``` 21 + {:ok, 22 + "#############################################################################################################################################\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#.#####.#.#################.###.#.#.#.#.#.###.#.###.###.#.#.#.###.#.#.###.#.#.#.#.#####.###.#.###.#.###.#.#.#.#.#.###.#." <> ...} 23 + ``` 24 + 25 + ```elixir 26 + #puzzle_input = 27 + """ 28 + ############### 29 + #...#...#.....# 30 + #.#.#.#.#.###.# 31 + #S#...#.#.#...# 32 + #######.#.#.### 33 + #######.#.#...# 34 + #######.#.###.# 35 + ###..E#...#...# 36 + ###.#######.### 37 + #...###...#...# 38 + #.#####.#.###.# 39 + #.#...#.#.#...# 40 + #.#.#.#.#.#.### 41 + #...#...#...### 42 + ############### 43 + """ 44 + ``` 45 + 46 + <!-- livebook:{"output":true} --> 47 + 48 + ``` 49 + warning: outdented heredoc line. The contents inside the heredoc should be indented at the same level as the closing """. The following is forbidden: 50 + 51 + def text do 52 + """ 53 + contents 54 + """ 55 + end 56 + 57 + Instead make sure the contents are indented as much as the heredoc closing: 58 + 59 + def text do 60 + """ 61 + contents 62 + """ 63 + end 64 + 65 + The current heredoc line is indented too little 66 + └─ Workspace/hauleth/advent-of-code/2024/day20.livemd#cell:iyjl3w4kz3srtwoq:3:3 67 + 68 + ``` 69 + 70 + <!-- livebook:{"output":true} --> 71 + 72 + ``` 73 + "###############\n#...#...#.....#\n#.#.#.#.#.###.#\n#S#...#.#.#...#\n#######.#.#.###\n#######.#.#...#\n#######.#.###.#\n###..E#...#...#\n###.#######.###\n#...###...#...#\n#.#####.#.###.#\n#.#...#.#.#...#\n#.#.#.#.#.#.###\n#...#...#...###\n###############\n" 74 + ``` 75 + 76 + ```elixir 77 + map = 78 + puzzle_input 79 + |> String.split("\n") 80 + |> Enum.with_index() 81 + |> Enum.flat_map(fn {row, y} -> 82 + row 83 + |> String.split("", trim: true) 84 + |> Enum.with_index() 85 + |> Enum.map(fn {c, x} -> 86 + {{x, y}, c} 87 + end) 88 + end) 89 + ``` 90 + 91 + <!-- livebook:{"output":true} --> 92 + 93 + ``` 94 + [ 95 + {{0, 0}, "#"}, 96 + {{1, 0}, "#"}, 97 + {{2, 0}, "#"}, 98 + {{3, 0}, "#"}, 99 + {{4, 0}, "#"}, 100 + {{5, 0}, "#"}, 101 + {{6, 0}, "#"}, 102 + {{7, 0}, "#"}, 103 + {{8, 0}, "#"}, 104 + {{9, 0}, "#"}, 105 + {{10, 0}, "#"}, 106 + {{11, 0}, "#"}, 107 + {{12, 0}, "#"}, 108 + {{13, 0}, "#"}, 109 + {{14, 0}, "#"}, 110 + {{15, 0}, "#"}, 111 + {{16, 0}, "#"}, 112 + {{17, 0}, "#"}, 113 + {{18, 0}, "#"}, 114 + {{19, 0}, "#"}, 115 + {{20, 0}, "#"}, 116 + {{21, 0}, "#"}, 117 + {{22, 0}, "#"}, 118 + {{23, 0}, "#"}, 119 + {{24, 0}, "#"}, 120 + {{25, 0}, "#"}, 121 + {{26, 0}, "#"}, 122 + {{27, 0}, "#"}, 123 + {{28, 0}, "#"}, 124 + {{29, 0}, "#"}, 125 + {{30, 0}, "#"}, 126 + {{31, 0}, "#"}, 127 + {{32, 0}, "#"}, 128 + {{33, 0}, "#"}, 129 + {{34, 0}, "#"}, 130 + {{35, 0}, "#"}, 131 + {{36, 0}, "#"}, 132 + {{37, 0}, "#"}, 133 + {{38, 0}, "#"}, 134 + {{39, 0}, "#"}, 135 + {{40, 0}, "#"}, 136 + {{41, 0}, "#"}, 137 + {{42, 0}, "#"}, 138 + {{43, 0}, "#"}, 139 + {{44, 0}, "#"}, 140 + {{45, 0}, "#"}, 141 + {{46, 0}, "#"}, 142 + {{47, ...}, "#"}, 143 + {{...}, ...}, 144 + {...}, 145 + ... 146 + ] 147 + ``` 148 + 149 + ```elixir 150 + %{"#" => walls, "." => road, "S" => [start], "E" => [finish]} = 151 + Enum.group_by(map, &elem(&1, 1), &elem(&1, 0)) 152 + ``` 153 + 154 + <!-- livebook:{"output":true} --> 155 + 156 + ``` 157 + %{ 158 + "#" => [ 159 + {0, 0}, 160 + {1, 0}, 161 + {2, 0}, 162 + {3, 0}, 163 + {4, 0}, 164 + {5, 0}, 165 + {6, 0}, 166 + {7, 0}, 167 + {8, 0}, 168 + {9, 0}, 169 + {10, 0}, 170 + {11, 0}, 171 + {12, 0}, 172 + {13, 0}, 173 + {14, 0}, 174 + {15, 0}, 175 + {16, 0}, 176 + {17, 0}, 177 + {18, 0}, 178 + {19, 0}, 179 + {20, 0}, 180 + {21, 0}, 181 + {22, 0}, 182 + {23, 0}, 183 + {24, 0}, 184 + {25, 0}, 185 + {26, 0}, 186 + {27, 0}, 187 + {28, 0}, 188 + {29, 0}, 189 + {30, 0}, 190 + {31, 0}, 191 + {32, 0}, 192 + {33, 0}, 193 + {34, 0}, 194 + {35, 0}, 195 + {36, 0}, 196 + {37, 0}, 197 + {38, 0}, 198 + {39, 0}, 199 + {40, 0}, 200 + {41, 0}, 201 + {42, 0}, 202 + {43, 0}, 203 + {44, 0}, 204 + {45, 0}, 205 + {46, 0}, 206 + {47, ...}, 207 + {...}, 208 + ... 209 + ], 210 + "." => [ 211 + {1, 1}, 212 + {2, 1}, 213 + {3, 1}, 214 + {5, 1}, 215 + {6, 1}, 216 + {7, 1}, 217 + {9, 1}, 218 + {10, 1}, 219 + {11, 1}, 220 + {13, 1}, 221 + {14, 1}, 222 + {15, 1}, 223 + {17, 1}, 224 + {18, 1}, 225 + {19, 1}, 226 + {20, 1}, 227 + {21, 1}, 228 + {22, 1}, 229 + {23, 1}, 230 + {24, 1}, 231 + {25, 1}, 232 + {27, 1}, 233 + {28, 1}, 234 + {29, 1}, 235 + {30, 1}, 236 + {31, 1}, 237 + {32, 1}, 238 + {33, 1}, 239 + {34, 1}, 240 + {35, 1}, 241 + {39, 1}, 242 + {40, 1}, 243 + {41, 1}, 244 + {43, 1}, 245 + {44, 1}, 246 + {45, 1}, 247 + {46, 1}, 248 + {47, 1}, 249 + {49, 1}, 250 + {50, 1}, 251 + {51, 1}, 252 + {53, 1}, 253 + {54, 1}, 254 + {55, 1}, 255 + {56, 1}, 256 + {57, 1}, 257 + {59, ...}, 258 + {...}, 259 + ... 260 + ], 261 + "E" => [{27, 59}], 262 + "S" => [{49, 53}] 263 + } 264 + ``` 265 + 266 + ```elixir 267 + defmodule Race do 268 + def distances(start, finish, walls) do 269 + do_distances(start, finish, 0, MapSet.new(walls), %{}) 270 + end 271 + 272 + defp do_distances(finish, finish, n, _, acc), 273 + do: Map.put(acc, finish, n) 274 + 275 + defp do_distances(current, finish, n, walls, acc) do 276 + acc = Map.put(acc, current, n) 277 + 278 + current 279 + |> neigh() 280 + |> Enum.reject(&(&1 in walls or Map.has_key?(acc, &1))) 281 + |> hd() 282 + |> do_distances(finish, n + 1, walls, acc) 283 + end 284 + 285 + def neigh({x, y}, d \\ 1) do 286 + for {dx, dy} <- [{0, d}, {0, -d}, {d, 0}, {-d, 0}], do: {x + dx, y + dy} 287 + end 288 + 289 + def neighbours({x, y}, r \\ 1) do 290 + for dx <- -r..r, 291 + dy <- -r..r, 292 + {dx, dy} != {0, 0}, 293 + d = abs(dx) + abs(dy), 294 + d <= r, 295 + do: {x + dx, y + dy} 296 + end 297 + 298 + def d({xa, ya}, {xb, yb}) do 299 + abs(xa - xb) + abs(ya - yb) 300 + end 301 + end 302 + ``` 303 + 304 + <!-- livebook:{"output":true} --> 305 + 306 + ``` 307 + {:module, Race, <<70, 79, 82, 49, 0, 0, 17, ...>>, {:d, 2}} 308 + ``` 309 + 310 + ```elixir 311 + steps = Race.distances(start, finish, walls) 312 + ``` 313 + 314 + <!-- livebook:{"output":true} --> 315 + 316 + ``` 317 + %{ 318 + {18, 103} => 8261, 319 + {61, 121} => 7060, 320 + {65, 63} => 2098, 321 + {77, 129} => 6964, 322 + {1, 26} => 695, 323 + {116, 69} => 4441, 324 + {83, 76} => 4281, 325 + {117, 125} => 5656, 326 + {103, 106} => 5785, 327 + {30, 113} => 8041, 328 + {89, 14} => 2511, 329 + {35, 30} => 1133, 330 + {37, 53} => 32, 331 + {11, 39} => 384, 332 + {131, 5} => 2998, 333 + {65, 43} => 1754, 334 + {139, 46} => 3615, 335 + {12, 135} => 7871, 336 + {65, 131} => 7046, 337 + {49, 117} => 7412, 338 + {29, 25} => 1108, 339 + {83, 36} => 2319, 340 + {47, 27} => 1556, 341 + {4, 81} => 8645, 342 + {13, 124} => 8295, 343 + {121, 77} => 4608, 344 + {103, 39} => 3756, 345 + {119, 60} => 4389, 346 + {13, 85} => 8604, 347 + {63, 81} => 6682, 348 + {111, 108} => 5755, 349 + {111, 103} => 5764, 350 + {15, 92} => 8587, 351 + {1, 101} => 8500, 352 + {20, 3} => 939, 353 + {61, 95} => 6878, 354 + {23, 67} => 9208, 355 + {78, 75} => 6545, 356 + {79, 17} => 2358, 357 + {17, 137} => 7852, 358 + {124, 93} => 4933, 359 + {138, 9} => 3283, 360 + {58, 33} => 1667, 361 + {67, 105} => 6818, 362 + {47, 44} => 1195, 363 + {122, 137} => 5595, 364 + {13, 55} => 154, 365 + {97, 138} => 6129, 366 + {75, ...} => 2165, 367 + {...} => 1616, 368 + ... 369 + } 370 + ``` 371 + 372 + ## Part 1 373 + 374 + ```elixir 375 + Enum.reduce(steps, 0, fn {pos, start}, acc -> 376 + count = 377 + steps 378 + |> Map.take(Race.neighbours(pos, 2)) 379 + |> Enum.count(fn {last, finish} -> 380 + finish - start - Race.d(pos, last) >= 100 381 + end) 382 + 383 + count + acc 384 + end) 385 + ``` 386 + 387 + <!-- livebook:{"output":true} --> 388 + 389 + ``` 390 + 1393 391 + ``` 392 + 393 + ## Part 2 394 + 395 + 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. 396 + 397 + ```elixir 398 + steps 399 + |> Task.async_stream( 400 + fn {pos, start} -> 401 + steps 402 + |> Map.take(Race.neighbours(pos, 20)) 403 + |> Enum.count(fn {last, finish} -> 404 + finish - start - Race.d(pos, last) >= 100 405 + end) 406 + end, 407 + ordered: false 408 + ) 409 + |> Enum.reduce(0, fn {:ok, count}, acc -> 410 + count + acc 411 + end) 412 + ``` 413 + 414 + <!-- livebook:{"output":true} --> 415 + 416 + ``` 417 + 990096 418 + ``` 419 + 420 + <!-- livebook:{"offset":11400,"stamp":{"token":"XCP.ONwDp6zRpWXsXASH95Q0puANk15Li1hG2FDCrv6Gqu42Q7k9pb_Te_6RDoUE0dp3yYbG7jry8-6iHGJvcZtsDFstlznyVHk9HVhXRZiC2uQczaOfF4K8HQL9QuzNguTht7A","version":2}} -->
+182
2024/day21.livemd
··· 1 + <!-- livebook:{"persist_outputs":true} --> 2 + 3 + # Day 21 4 + 5 + ```elixir 6 + Mix.install([:kino_aoc]) 7 + ``` 8 + 9 + ## Section 10 + 11 + <!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIyMSIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} --> 12 + 13 + ```elixir 14 + {:ok, puzzle_input} = 15 + KinoAOC.download_puzzle("2024", "21", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION")) 16 + ``` 17 + 18 + <!-- livebook:{"output":true} --> 19 + 20 + ``` 21 + {:ok, "638A\n965A\n780A\n803A\n246A"} 22 + ``` 23 + 24 + ```elixir 25 + codes = 26 + puzzle_input 27 + |> String.split("\n", trim: true) 28 + |> Enum.map(fn <<num::3-binary>> <> "A" = code -> 29 + {String.to_charlist(code), String.to_integer(num)} 30 + end) 31 + ``` 32 + 33 + <!-- livebook:{"output":true} --> 34 + 35 + ``` 36 + [{~c"638A", 638}, {~c"965A", 965}, {~c"780A", 780}, {~c"803A", 803}, {~c"246A", 246}] 37 + ``` 38 + 39 + ```elixir 40 + dirpad = %{ 41 + [?A, ?>] => ~c[vA], 42 + [?A, ?^] => ~c[<A], 43 + [?A, ?v] => ~c[<vA], 44 + [?A, ?<] => ~c[v<<A], 45 + 46 + [?>, ?A] => ~c[^A], 47 + [?>, ?^] => ~c[<^A], 48 + [?>, ?v] => ~c[<A], 49 + [?>, ?<] => ~c[<<A], 50 + 51 + [?^, ?A] => ~c[>A], 52 + [?^, ?>] => ~c[v>A], 53 + [?^, ?v] => ~c[vA], 54 + [?^, ?<] => ~c[v<A], 55 + 56 + [?<, ?A] => ~c[>>^A], 57 + [?<, ?^] => ~c[>^A], 58 + [?<, ?v] => ~c[>A], 59 + [?<, ?>] => ~c[>>A], 60 + 61 + [?v, ?A] => ~c[>^A], 62 + [?v, ?^] => ~c[^A], 63 + [?v, ?<] => ~c[<A], 64 + [?v, ?>] => ~c[>A] 65 + } 66 + ``` 67 + 68 + <!-- livebook:{"output":true} --> 69 + 70 + ``` 71 + %{ 72 + ~c"<>" => ~c">>A", 73 + ~c"<A" => ~c">>^A", 74 + ~c"<^" => ~c">^A", 75 + ~c"<v" => ~c">A", 76 + ~c"><" => ~c"<<A", 77 + ~c">A" => ~c"^A", 78 + ~c">^" => ~c"<^A", 79 + ~c">v" => ~c"<A", 80 + ~c"A<" => ~c"v<<A", 81 + ~c"A>" => ~c"vA", 82 + ~c"A^" => ~c"<A", 83 + ~c"Av" => ~c"<vA", 84 + ~c"^<" => ~c"v<A", 85 + ~c"^>" => ~c"v>A", 86 + ~c"^A" => ~c">A", 87 + ~c"^v" => ~c"vA", 88 + ~c"v<" => ~c"<A", 89 + ~c"v>" => ~c">A", 90 + ~c"vA" => ~c">^A", 91 + ~c"v^" => ~c"^A" 92 + } 93 + ``` 94 + 95 + ```elixir 96 + 97 + ``` 98 + 99 + <!-- livebook:{"output":true} --> 100 + 101 + ``` 102 + nil 103 + ``` 104 + 105 + ```elixir 106 + defmodule Keypad do 107 + def naive(input, lut) do 108 + [?A | input] 109 + |> Enum.chunk_every(2, 1, :discard) 110 + |> Enum.flat_map(&Map.get(lut, &1, [?A])) 111 + end 112 + 113 + def expand(input, lut) do 114 + Stream.concat([?A], input) 115 + |> Stream.chunk_every(2, 1, :discard) 116 + |> Stream.flat_map(&Map.get(lut, &1, [?A])) 117 + end 118 + end 119 + ``` 120 + 121 + <!-- livebook:{"output":true} --> 122 + 123 + ``` 124 + {:module, Keypad, <<70, 79, 82, 49, 0, 0, 9, ...>>, {:expand, 2}} 125 + ``` 126 + 127 + ```elixir 128 + 129 + ``` 130 + 131 + <!-- livebook:{"output":true} --> 132 + 133 + ``` 134 + nil 135 + ``` 136 + 137 + ```elixir 138 + Keypad.expand(~c[<A^A>^^AvvvA], dirpad) 139 + |> Enum.count() 140 + 141 + #|> Enum.map(fn {k, v} -> 142 + # [?A | Map.get(dirpad, k, [?A])] 143 + # |> Enum.chunk_every(2, 1, :discard) 144 + # |> Enum.map() 145 + #end) 146 + #|> Enum.group_by(&elem(&1, 0), &elem(&1, 1)) 147 + #|> Map.new(fn {k, v} -> {k, Enum.sum(v)} end) 148 + ``` 149 + 150 + <!-- livebook:{"output":true} --> 151 + 152 + ``` 153 + 28 154 + ``` 155 + 156 + ```elixir 157 + Keypad.naive(~c[<A^A>^^AvvvA], dirpad) 158 + |> Keypad.naive(dirpad) 159 + |> Enum.chunk_every(2, 1, [?A]) 160 + |> Enum.frequencies() 161 + |> Map.values() 162 + |> Enum.sum() 163 + ``` 164 + 165 + <!-- livebook:{"output":true} --> 166 + 167 + ``` 168 + 68 169 + ``` 170 + 171 + ```elixir 172 + ~c"<vA<AA>>^AvAA<^A>Av<<A>>^AvA^A<vA>^Av<<A>^A>AAvA^Av<<A>A>^AAAvA<^A>A" 173 + ~c"<vA<AA>>^AvAA<^A>A<v<A>>^AvA^A<vA>^A<v<A>^A>AAvA^A<v<A>A>^AAAvA<^A>A" |> length 174 + ``` 175 + 176 + <!-- livebook:{"output":true} --> 177 + 178 + ``` 179 + 68 180 + ``` 181 + 182 + <!-- livebook:{"offset":3144,"stamp":{"token":"XCP.rEBKR0PbENlE02mf_Mo6R3RTWsHU-tFuA9VTPd907vq3-8e37LytxC6qWBmZAHZHLc_e1t3ZaG85X5KBWsYq0WGEzo7HC0U9-oE0dpPKGKeF7oBGgFeiEoDsX6GDKTwp76o","version":2}} -->
+198
2024/day22.livemd
··· 1 + <!-- livebook:{"persist_outputs":true} --> 2 + 3 + # Day 22 4 + 5 + ```elixir 6 + Mix.install([:kino_aoc]) 7 + ``` 8 + 9 + ## Section 10 + 11 + <!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIyMiIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} --> 12 + 13 + ```elixir 14 + {:ok, puzzle_input} = 15 + KinoAOC.download_puzzle("2024", "22", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION")) 16 + ``` 17 + 18 + <!-- livebook:{"output":true} --> 19 + 20 + ``` 21 + {:ok, 22 + "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" <> ...} 23 + ``` 24 + 25 + ```elixir 26 + inits = 27 + puzzle_input 28 + |> String.split("\n", trim: true) 29 + |> Enum.map(&String.to_integer/1) 30 + ``` 31 + 32 + <!-- livebook:{"output":true} --> 33 + 34 + ``` 35 + [4832674, 14802956, 7210529, 7709095, 6063251, 12294789, 15666951, 12074106, 15427686, 1214891, 36 + 15165649, 3609602, 10200989, 16451437, 10915511, 3479515, 173864, 1238342, 3381843, 14767788, 37 + 16088065, 15637051, 15981887, 15854806, 4988920, 7980791, 11263142, 8044640, 4572291, 328777, 38 + 11851557, 13706949, 16451719, 15991644, 14668984, 8852039, 1685443, 13814197, 14117797, 6281998, 39 + 12395020, 1681090, 16476099, 2171296, 10155667, 15490827, 6723206, 7272972, 1788575, 2950054, ...] 40 + ``` 41 + 42 + ```elixir 43 + defmodule Buyer do 44 + def hash(number, rounds \\ 2000) do 45 + Enum.map_reduce(1..rounds//1, number, fn _, acc -> 46 + r = do_round(acc) 47 + {rem(r, 10), r} 48 + end) 49 + end 50 + 51 + defp do_round(num) do 52 + num = subround(num, num * 64) 53 + num = subround(num, div(num, 32)) 54 + subround(num, num * 2048) 55 + end 56 + 57 + defp subround(a, b), do: rem(Bitwise.bxor(a, b), 16_777_216) 58 + 59 + def sequences(prices) do 60 + prices 61 + |> Enum.chunk_every(5, 1, :discard) 62 + |> Enum.reduce(%{}, fn seq, map -> 63 + Map.put_new(map, diffs(seq), List.last(seq)) 64 + end) 65 + end 66 + 67 + defp diffs(vals) do 68 + vals 69 + |> Enum.chunk_every(2, 1, :discard) 70 + |> Enum.map(fn [a, b] -> b - a end) 71 + |> Integer.undigits(256) 72 + end 73 + end 74 + ``` 75 + 76 + <!-- livebook:{"output":true} --> 77 + 78 + ``` 79 + {:module, Buyer, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:diffs, 1}} 80 + ``` 81 + 82 + ```elixir 83 + hashes = Enum.map(inits, &Buyer.hash(&1)) 84 + ``` 85 + 86 + <!-- livebook:{"output":true} --> 87 + 88 + ``` 89 + [ 90 + {[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, 91 + 4, 3, 3, 8, 0, 5, 2, 1, 2, 8, 6, 2, 2, 3, 6, 9, ...], 8186085}, 92 + {[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, 93 + 2, 4, 5, 9, 5, 8, 5, 0, 6, 9, 3, 2, 3, 4, 4, ...], 16060909}, 94 + {[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, 95 + 5, 6, 0, 7, 3, 0, 9, 4, 8, 4, 0, 2, 2, 7, ...], 3581487}, 96 + {[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, 97 + 9, 6, 6, 7, 2, 1, 7, 2, 7, 3, 2, 7, 3, ...], 14331752}, 98 + {[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, 99 + 1, 6, 7, 3, 8, 8, 7, 5, 3, 3, 2, 3, ...], 11096256}, 100 + {[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, 101 + 7, 1, 3, 1, 7, 9, 3, 3, 6, 2, 4, ...], 8119288}, 102 + {[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, 103 + 2, 8, 0, 5, 0, 9, 7, 2, 5, 9, ...], 4175670}, 104 + {[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, 105 + 6, 2, 0, 2, 9, 7, 8, 0, 9, ...], 9128738}, 106 + {[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, 107 + 3, 6, 8, 1, 9, 6, 1, 5, ...], 13899897}, 108 + {[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, 109 + 5, 9, 7, 0, 3, 3, 6, ...], 12087848}, 110 + {[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, 111 + 3, 9, 9, 9, 7, 2, ...], 11514818}, 112 + {[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, 113 + 9, 5, 6, 9, 3, ...], 4150418}, 114 + {[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, 115 + 0, 2, 7, 1, ...], 2679493}, 116 + {[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, 117 + 6, 9, 6, ...], 84072}, 118 + {[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, 119 + 5, 8, ...], 3938870}, 120 + {[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, 121 + 8, ...], 15186439}, 122 + {[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, 123 + ...], 4224277}, 124 + {[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, 125 + ...], 6637814}, 126 + {[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, ...], 127 + 15335578}, 128 + {[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, ...], 129 + 14808063}, 130 + {[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, ...], 131 + 2236221}, 132 + {[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}, 133 + {[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}, 134 + {[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}, 135 + {[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}, 136 + {[2, 1, 2, 4, 0, 6, 0, 8, 6, 5, 9, 5, 1, 7, 1, 3, 9, 3, 2, 8, 5, 4, 8, ...], 4484251}, 137 + {[1, 5, 9, 2, 0, 5, 7, 4, 6, 2, 3, 4, 7, 9, 9, 7, 9, 8, 3, 4, 2, 3, ...], 12505941}, 138 + {[3, 2, 8, 0, 7, 6, 7, 8, 6, 2, 0, 4, 7, 6, 2, 8, 2, 7, 3, 0, 3, ...], 12324709}, 139 + {[3, 6, 3, 2, 2, 5, 4, 5, 3, 2, 2, 8, 5, 8, 7, 6, 5, 9, 3, 0, ...], 12840916}, 140 + {[7, 4, 1, 3, 5, 7, 1, 9, 4, 8, 2, 0, 2, 6, 7, 1, 7, 8, 4, ...], 13939301}, 141 + {[0, 4, 4, 4, 6, 9, 8, 0, 2, 3, 9, 9, 4, 0, 6, 0, 4, 2, ...], 7392065}, 142 + {[7, 8, 0, 0, 4, 1, 6, 1, 5, 9, 0, 3, 1, 4, 5, 8, 9, ...], 13395486}, 143 + {[5, 5, 1, 7, 9, 8, 0, 1, 5, 5, 6, 2, 1, 6, 6, 5, ...], 14846825}, 144 + {[4, 1, 5, 9, 7, 1, 3, 6, 6, 5, 8, 9, 1, 0, 7, ...], 15647415}, 145 + {[5, 0, 0, 5, 4, 4, 9, 3, 4, 0, 4, 9, 0, 0, ...], 15491670}, 146 + {[5, 3, 1, 3, 6, 7, 3, 2, 8, 6, 2, 5, 0, ...], 12602693}, 147 + {[9, 6, 3, 2, 6, 3, 9, 6, 6, 5, 2, 6, ...], 16470307}, 148 + {[8, 4, 3, 6, 0, 4, 0, 8, 5, 5, 9, ...], 10819101}, 149 + {[0, 9, 4, 4, 6, 0, 2, 4, 0, 3, ...], 8658998}, 150 + {[0, 2, 8, 3, 0, 4, 5, 0, 5, ...], 11616760}, 151 + {[4, 8, 3, 5, 2, 8, 0, 8, ...], 4294043}, 152 + {[8, 1, 0, 8, 2, 1, 0, ...], 11210309}, 153 + {[5, 8, 6, 9, 6, 8, ...], 1113711}, 154 + {[1, 6, 5, 5, 4, ...], 16530315}, 155 + {[5, 1, 3, 9, ...], 8014000}, 156 + {[7, 4, 5, ...], 13932057}, 157 + {[8, 9, ...], 9987703}, 158 + {[4, ...], 10745797}, 159 + {[...], ...}, 160 + {...}, 161 + ... 162 + ] 163 + ``` 164 + 165 + ## Part 1 166 + 167 + ```elixir 168 + hashes 169 + |> Enum.map(&elem(&1, 1)) 170 + |> Enum.sum() 171 + ``` 172 + 173 + <!-- livebook:{"output":true} --> 174 + 175 + ``` 176 + 13461553007 177 + ``` 178 + 179 + ## Part 2 180 + 181 + ```elixir 182 + hashes 183 + |> Task.async_stream( 184 + fn {prices, _} -> Buyer.sequences(prices) end, 185 + ordered: false 186 + ) 187 + |> Enum.reduce(%{}, fn {:ok, a}, b -> Map.merge(a, b, fn _k, v, k -> v + k end) end) 188 + |> Enum.max_by(&elem(&1, 1)) 189 + |> elem(1) 190 + ``` 191 + 192 + <!-- livebook:{"output":true} --> 193 + 194 + ``` 195 + 1499 196 + ``` 197 + 198 + <!-- livebook:{"offset":11738,"stamp":{"token":"XCP.GjkWCjlMBRZbt2b3Ic6te1lRoiRN-o788mezmoiandQKEk9mR1MC2aSWY6otgof8lHDa_afMMYYnBV9YHmLjoK0wooHF17OPyx6ruqV5hYpKoVBVZuhSx_gT8_2Ac2S73Pk","version":2}} -->
+203
2024/day23.livemd
··· 1 + <!-- livebook:{"persist_outputs":true} --> 2 + 3 + # Day 23 4 + 5 + ```elixir 6 + Mix.install([:kino_aoc, {:libgraph, github: "bitwalker/libgraph"}, :combination]) 7 + ``` 8 + 9 + ## Section 10 + 11 + <!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIyMyIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} --> 12 + 13 + ```elixir 14 + {:ok, puzzle_input} = 15 + KinoAOC.download_puzzle("2024", "23", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION")) 16 + ``` 17 + 18 + <!-- livebook:{"output":true} --> 19 + 20 + ``` 21 + {:ok, 22 + "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" <> ...} 23 + ``` 24 + 25 + ```elixir 26 + connections = 27 + puzzle_input 28 + |> String.split("\n", trim: true) 29 + |> Enum.map(fn <<a::binary-2, "-", b::binary-2>> -> 30 + {a, b} 31 + end) 32 + ``` 33 + 34 + <!-- livebook:{"output":true} --> 35 + 36 + ``` 37 + [ 38 + {"on", "za"}, 39 + {"bp", "hs"}, 40 + {"vc", "bg"}, 41 + {"tm", "us"}, 42 + {"zf", "ox"}, 43 + {"ib", "lc"}, 44 + {"uo", "zs"}, 45 + {"ov", "qj"}, 46 + {"ll", "eb"}, 47 + {"iy", "tq"}, 48 + {"bg", "by"}, 49 + {"un", "ix"}, 50 + {"gi", "do"}, 51 + {"rv", "ou"}, 52 + {"yp", "qu"}, 53 + {"qb", "um"}, 54 + {"qs", "dn"}, 55 + {"ru", "ro"}, 56 + {"et", "fw"}, 57 + {"yx", "jt"}, 58 + {"ns", "iz"}, 59 + {"od", "rc"}, 60 + {"ny", "ap"}, 61 + {"vb", "fd"}, 62 + {"wf", "wr"}, 63 + {"yh", "qy"}, 64 + {"fa", "ct"}, 65 + {"qo", "fv"}, 66 + {"ig", "jv"}, 67 + {"qi", "ff"}, 68 + {"nj", "ii"}, 69 + {"sa", "gg"}, 70 + {"cp", "un"}, 71 + {"ez", "kh"}, 72 + {"vs", "du"}, 73 + {"gp", "qs"}, 74 + {"pt", "qj"}, 75 + {"yp", "my"}, 76 + {"jf", "sz"}, 77 + {"yo", "gm"}, 78 + {"fn", "xw"}, 79 + {"iu", "xr"}, 80 + {"se", "ox"}, 81 + {"mw", "ie"}, 82 + {"fw", "br"}, 83 + {"xy", "iu"}, 84 + {"qw", "wi"}, 85 + {"xc", "dq"}, 86 + {"vb", ...}, 87 + {...}, 88 + ... 89 + ] 90 + ``` 91 + 92 + ```elixir 93 + party = 94 + Graph.new(type: :undirected) 95 + |> Graph.add_edges(connections) 96 + ``` 97 + 98 + <!-- livebook:{"output":true} --> 99 + 100 + ``` 101 + #Graph<type: undirected, num_vertices: 520, num_edges: 3380> 102 + ``` 103 + 104 + ```elixir 105 + cliques = Graph.cliques(party) 106 + ``` 107 + 108 + <!-- livebook:{"output":true} --> 109 + 110 + ``` 111 + [ 112 + ["yf", "dk", "dy", "hm", "vx", "zj", "ec", "eg", "ko", "kx", "tw", "ux"], 113 + ["yf", "dk", "hm", "vx", "zj", "ec", "eg", "qg", "ko", "kx", "tw", "ux"], 114 + ["yf", "ob"], 115 + ["xa", "wl", "lx", "lq", "jy", "in", "hy", "lw", "qd", "fu", "ub", "og"], 116 + ["xa", "wl", "lx", "jy", "bl", "in", "hy", "lw", "qd", "fu", "ub", "og"], 117 + ["xa", "wi"], 118 + ["bd", "cb", "it", "ut", "fq", "hs", "ur", "ly", "tx", "yg", "ui", "gl"], 119 + ["bd", "cb", "it", "ut", "fq", "ur", "ly", "tx", "yg", "ui", "gl", "rk"], 120 + ["bd", "bu"], 121 + ["nm", "qb", "gv", "nf", "oi", "tg", "uj", "yd", "rr", "tr", "vv", "mg"], 122 + ["nm", "qb", "gv", "nf", "oi", "tg", "uj", "yd", "rr", "tr", "vv", "zp"], 123 + ["nm", "ge"], 124 + ["dk", "jn"], 125 + ["cn", "lh", "di", "xm", "cm", "oe", "vi", "ho", "fg", "mt", "io", "dv"], 126 + ["cn", "zt"], 127 + ["cn", "jl"], 128 + ["qp", "xd"], 129 + ["qp", "zq", "qk", "uu", "cy", "fp", "ay", "yo", "gm", "vj", "ps", "fr"], 130 + ["qp", "zq", "qk", "uu", "cy", "ay", "yo", "gm", "vj", "jl", "ps", "fr"], 131 + ["xq", "qx", "rg", "wc", "um", "rv", "ae", "kw", "lj", "ze", "wq", "ou"], 132 + ["xq", "kg"], 133 + ["xq", "qo"], 134 + ["ti", "et", "bu", "xk", "ix", "fw", "un", "ri", "cp", "br", "gr", "ch"], 135 + ["ti", "et", "bu", "xk", "fw", "un", "ri", "cp", "br", "gr", "ch", "yw"], 136 + ["ti", "ab"], 137 + ["nh", "hv", "id", "ap", "fv", "ny", "pb", "ni", "aw", "nx", "vk", "qo"], 138 + ["nh", "pj"], 139 + ["nh", "lk"], 140 + ["ys", "ib", "dg", "vr", "yx", "jt", "ek", "lt", "sy", "vm", "lc", "rw"], 141 + ["ys", "ib", "dg", "yx", "jt", "pg", "ek", "lt", "sy", "vm", "lc", "rw"], 142 + ["ys", "tl"], 143 + ["cb", "ha"], 144 + ["ue", "dd", "kd", "zm", "kt", "il", "af", "xx", "vl", "xl", "jd", "rx"], 145 + ["ue", "dd", "kd", "kt", "il", "af", "xx", "vl", "xl", "jd", "rx", "pz"], 146 + ["ue", "bh"], 147 + ["jg", "cx", "fo", "ro", "ru", "oo", "dh", "as", "zx", "ke", "om", "gu"], 148 + ["jg", "cx", "fo", "ro", "ru", "dh", "as", "sm", "zx", "ke", "om", "gu"], 149 + ["jg", "cy"], 150 + ["bz", "fz", "qi", "tn", "xg", "dc", "ge", "sb", "df", "hu", "vd", ...], 151 + ["bz", "ae"], 152 + ["bz", "gm"], 153 + ["im", "dz", "ab", "sz", "ej", "mz", "pv", "rj", ...], 154 + ["im", "dz", "sz", "ej", "mz", "pv", "rj", ...], 155 + ["im", "ps"], 156 + ["sw", "gc", "si", "aj", "is", ...], 157 + ["sw", "gc", "si", "aj", ...], 158 + ["sw", "fn"], 159 + ["cg", "zt", ...], 160 + ["cg", ...], 161 + [...], 162 + ... 163 + ] 164 + ``` 165 + 166 + ## Part 1 167 + 168 + ```elixir 169 + cliques 170 + |> Stream.flat_map(fn clique -> 171 + if length(clique) >= 3 do 172 + Combination.combine(clique, 3) 173 + else 174 + [] 175 + end 176 + end) 177 + |> Stream.filter(fn clique -> Enum.any?(clique, &String.starts_with?(&1, "t")) end) 178 + |> MapSet.new() 179 + |> MapSet.size() 180 + ``` 181 + 182 + <!-- livebook:{"output":true} --> 183 + 184 + ``` 185 + 1248 186 + ``` 187 + 188 + ## Part 2 189 + 190 + ```elixir 191 + cliques 192 + |> Enum.max_by(&length/1) 193 + |> Enum.sort() 194 + |> Enum.join(",") 195 + ``` 196 + 197 + <!-- livebook:{"output":true} --> 198 + 199 + ``` 200 + "aa,cf,cj,cv,dr,gj,iu,jh,oy,qr,xr,xy,zb" 201 + ``` 202 + 203 + <!-- livebook:{"offset":9387,"stamp":{"token":"XCP.YMMjV81j86GOTx0hGVW-U0w7aqvuBdig59tmj2pqELbNIP0HXjbZA1WSQwLRMCUIuzZ1PLs6_0ehAVdgp7sj4Wuc6QaM8KCZ3j-zJrTUmr2_hxaACLOnkijsz6m2hIS8E6Q","version":2}} -->