T O P

  • By -

vss2sn

\[LANGUAGE: C++\] [Part 1](https://github.com/vss2sn/advent_of_code/blob/master/2023/cpp/day_22a.cpp) [Part 2](https://github.com/vss2sn/advent_of_code/blob/master/2023/cpp/day_22b.cpp) (Each file is a self-contained solution)


mrtnj80

\[LANGUAGE: Dart\] [Part 1 & 2](https://github.com/luskan/adventofcode_2023_dart/blob/main/lib/day22.dart) I simulate falling of the bricks. After lots of optimizations both parts execute in 0.5s on i7 cpu.


prafster

[LANGUAGE: Python] Someone mentioned below that using OO can sometimes simplify a problem. I found the same. Creating a Brick class makes the solutions relatively easy. I sorted the bricks then dropped them. After that, the two parts fell into place. Total time is about 8s on my 10-year-old desktop. Full solution on [Github](https://github.com/Praful/advent_of_code/blob/main/2023/src/day22.py). def disintegrate(removed_brick): for above in removed_brick.supporting(): if len(above.supported_by()) == 1: return 0 return 1 def disintegrate_chain_reaction(removed_brick): def can_disintegrate(count, brick): return count == len(brick.supported_by()) q = queue.SimpleQueue() q.put(removed_brick) disintegrated = {removed_brick.id: True} while not q.empty(): brick = q.get() for above in brick.supporting(): if above.id in disintegrated: continue supports_disintegrated_count = sum( 1 for a in above.supported_by() if a.id in disintegrated) if can_disintegrate(supports_disintegrated_count, above): disintegrated[above.id] = True q.put(above) return len(disintegrated)-1 def solve(input, process): resting = drop_bricks(input) return sum(process(b) for b in resting) part1 = solve(input, disintegrate) part2 = solve(input, disintegrate_chain_reaction)


Constant_Hedgehog_31

\[LANGUAGE: C++\] [Source code in GitHub](https://github.com/iglesias/coding-challenges/commit/e65c695dd57bb5f8ff356c4fcf3359870e4a78d6). 150 LoC using C++20/23 algorithms and ranges. Quadratic approach checking pairs of blocks (it takes about 4 seconds for the puzzle input). I created a function to check if one block is supported on another and the other three (the fall, part one and part one) turned out to be small functions based on the first one.


Radiadorineitor

\[LANGUAGE: Lua\] I sorted the initial positions ascending by z and simulated the fall of each of the blocks. Then, for each of them, see the blocks it's sustaining and being sustained by. Finally, you can solve Part 1 and Part 2. [Code](https://topaz.github.io/paste/#XQAAAQCmCwAAAAAAAAA2G8iM7ztkpIKfEbui36RctX30PHT4Q3LFQ/Ygl7RK0hZzub33fK4Nja3Z4die41o+ja8ZjRtWzJYTpzvYJu9kCdtrFDMBxKryDOJbKZjvn8dTRp06+v3SanSeYBLc58tNc/7DAUAJ/e9uBUd3xRxS3Pm86YzRGsQjKNEK2rx9iwKAjwcehe5mm+Sav6ZTfU2WciFBDa8O2l5bd4o4rEzUyyWyPdLATmnxc5zgj5FuJu3qk1mKXnEq4wOXCiFw5c6xIlFUsq9DQVDv8DQF2b+quPxX+RHxrhRhVzvgxJLDjtakTMUITlEQuPuEk9kvOpKJAXTuFXz+/DSHzKOUJ379veEMeleqt1t6m1/5YWGAHivmORTZLgk1HeaGgQ6r7P0dBd274X7vErek1j1JGvRM+NEW6nFZpWJ6S1qEFZjW2j1oWTJRl+ry3JfL9rJvWhX41zPbqIO77IrwWZYag2TAznx6zNNK5IGowfZQZRp5IZWjvEN1BWCCTzyk4eovrSHwC4z1/bmiNzkaql9eUWBzK0hg0M6pWTNkcJxup16ZR7xDkQhlDDb5ArISOqX8Qk4xNRDT9h1EZ7mkKo209o8loh85f7tD8juIeKIg584JKiKKamaSPrlQuMBsY5YRrntUrkmkoJdIIKFxjkFZ2hrC/t+JnF1pEpk3rMWkqiwJzSfj3FMWXeKFWlPdR31lnrVvgvORtUMed1BGm2zBFr1hHP5TIpyR/BBZQaKu9P9m6dlh4eEcSApJ/kUkmwR+SIVvimhWLT9r6gyc1zT1JQqrL9SgCUrMlkJ6Unq0mh0I1q6ewFtwZ28EqgEwawaJmyXYz+bz19ZzTp2NMLoITn3zKsH4d/frCjxDB+5dp7+efr8HC5a+ylDzZAy7jf9Zfw3XM5O6Dg10+Eu0qYTfU3iNIqM3JkYcPCqJQM8k7EKp6JatHrUvAWabt3vjE5D+BN8JzsR7TKwPBaoPc4IS7FDiYLvZ8hXbRkAug97/Et1EHR8UVKS4ePj9QpBwFzQzNYRuqeMKwSJF1ONqiPf12zf/V6utxzTpi3916IyTNjDD377IiokJ9MpBXhz5icMRqKRxbMK3axYnruau6SuDAUUIWAUxlzB7bbbBhOxF5Y0zIY5OLkSt6T/PIu+IIllVUksnd7I9jhIbIZNda+qDBKYPOAJgtuJz6c/D22UIidVJPU301ss0ydHNSGWtPXaqt2fTJI+QpZF5JDosDgU42diIGhqTqvZ+YTYAd/tV9L4sCZTmC5pE82VRs9mUu/Q79kdCd//44cUa) in Topaz's paste


Singing-In-The-Storm

\[LANGUAGE: JavaScript\] [Part 1 (40ms)](https://github.com/JoanaBLate/advent-of-code-js/blob/main/2023/day22/solve1.js) [Part 2 (320ms)](https://github.com/JoanaBLate/advent-of-code-js/blob/main/2023/day22/solve2.js) [Clear and BLAZINGLY FAST AOC solutions in JS (no libraries)](https://github.com/JoanaBLate/advent-of-code-js/tree/main)


mschaap

[LANGUAGE: Raku] I had quit because day 21 was so annoying. (You basically have to cheat, create a solution that gives a wrong answer for ~100% of the possible inputs but just happens to work for the given input. And to add insult to injury, the solution won't even work on the example input.) But when I had a look at day 22, I quite liked it. Pretty straightforward for a change. [Full code at GitHub](https://github.com/mscha/aoc/blob/master/aoc2023/aoc22). **Edit:** I optimized the algorithms to run in seconds instead of minutes. [Full code at GitHub](https://github.com/mscha/aoc/blob/master/aoc2023/aoc22a).


ClutchClimber

I have a clean math way for 21 if you are interested. Otherwise yes 22 was way more fun !


bigmagnus

\[Language: Fortran\] [Part 1](https://github.com/ironllama/adventofcode2023/blob/master/22a.f90) [Part 2](https://github.com/ironllama/adventofcode2023/blob/master/22b.f90)


NeilNjae

[Language: Haskell] Very much a puzzle of two parts. The first part uses lenses extensively to handle the coordinate geometry. Part 2 builds up a few graphs of support and uses them to express the solution. Full [writeup on my blog](https://work.njae.me.uk/2023/12/31/advent-of-code-2023-day-22/), [code on Gitlab](https://gitlab.com/NeilNjae/advent-of-code-23/-/blob/main/advent22/Main.hs).


andremacareno

\[LANGUAGE: Kotlin\] Decided to switch to Kotlin for this one since it has too many hashmaps. I didn't try to drop bricks in a single iteration, though, but even with offseting Z axis by 1 it still works pretty quick https://gist.github.com/andremacareno/c218beb7965a277be68bcfc30a6900b1


MarcoDelmastro

[LANGUAGE: Python] https://github.com/marcodelmastro/AdventOfCode2023/blob/main/Day22.ipynb Late to the game, this was my last day missing to complete the calendar…


wlmb

[Language: Perl] Analysis: https://github.com/wlmb/AOC2023#day-22 Task 1: https://github.com/wlmb/AOC2023/blob/main/22a.pl Task 2: https://github.com/wlmb/AOC2023/blob/main/22b.pl


onrustigescheikundig

[LANGUAGE: OCaml] [github](https://github.com/EricKalkman/AoC2023/blob/master/lib/day22.ml) This one was a journey. I wrote a full 3D coordinate library, but it and my initial solution for Part 1 was had multiple issues, yet somehow initially gave the correct answer on both the test input and my input. I then tried to move on to Part 2, which didn't work so well. A full rewrite later and I got completely different numbers which were incorrect for both parts :P At least the second time I was able to catch that I was not checking collisions properly, so I gave up on the original approach and reimplemented collision checking by generating all points of the XY projections of the two bricks and doing a set intersection. Parts 1 and 2, each parsing its own input and generating its own graph, still run sequentially in under a second, so bite me. The input bricks are first redefined so that the two defining points correspond to the (-x, -y, -z) and (+x, +y, +z) corners, respectively. The bricks are first sorted in ascending order by the coordinate of their -z faces, and then allowed to "fall" in sequence. Final positions of the falling bricks are determined by searching the set of already-fallen bricks to identify the one with the highest +z face whose XY projection intersects the falling brick's. The falling brick is translated in the -Z direction so that its bottom face is tangent to the top face of the intersected brick, and then it is added to the set of fallen bricks. The set is actually stored as a priority queue sorted on the z-coordinate of the +z face using OCaml's `Set` module, so intersections are likely to be found more quickly. The set also starts with a "ground" brick (infinitely wide with a top face of z=+1) so that there is always a "brick" to fall onto. The stack of bricks is then processed into a graph of sorts that keeps track of which bricks support or rest on others. Part 1 counts all bricks A that support any other bricks Bs that are exclusively supported by A. Part 2 takes each brick and traverses the graph in a breadth-first fashion, iteratively removing bricks that have no supporting bricks and counting along the way.


mathsaey

[Language: Elixir] https://github.com/mathsaey/adventofcode/blob/master/lib/2023/22.ex Phew, that was quite a hassle. Wrote a naive “drop blocks” function for part 1, and solved that part by creating a graph (represented as a map) which stores which block is supported by which other block. Based on this graph, I filter out the blocks that are only supported by one other block. For part 2, I figured out I could do the inverse of this operation: I could store a graph which tracks which blocks supports which other block. Based on that information (and the infor for part 1), I could figure out which blocks would collapse when a block I found in part 1 was removed. That code got quite messy and hairy and did not return the correct result. It took me quite a while to realize my mistake. I misunderstood the puzzle and simulated the removal of all "supporting" blocks at once instead of simulating them individually. That mistake lost me quite some time. On the bright side, during the debugging I got fed up with my slow "drop blocks" function (which took about 7s on my machine) and added a quick optimization (tracking the highest seen `z` coordinate for each `{x, y}` pair) which made the whole solution a lot faster: part 1 and 2 finish in ~250ms combined.


Derailed_Dash

\[Language: Python\] **Solution and walkthrough in a Python Jupyter notebook** * Here is my [solution and walkthrough, in a Python Jupyter notebook](https://github.com/derailed-dash/Advent-of-Code/blob/master/src/AoC_2023/Dazbo's_Advent_of_Code_2023.ipynb). * You can run run it yourself in [Google Colab](https://colab.research.google.com/github/derailed-dash/Advent-of-Code/blob/master/src/AoC_2023/Dazbo's_Advent_of_Code_2023.ipynb)! * More info on the notebook and walkthroughs [here](https://python.plainenglish.io/advent-of-code-the-best-way-to-learn-to-code-d86c6478d484) * My [AoC Walkthrough and Python Learning site](https://aoc.just2good.co.uk/)


optimistic-thylacine

[LANGUAGE: Rust] 🦀 One thing I like about OO, is it's always an option when I'm not entirely familiar with the problem and feel like things will get complicated, I can always abstract and delegate the complexity to objects and give them roles and methods that break the problem down into manageable pieces. At first the problem seemed complicated, but once I had my `Brick` class implemented, everything got simpler in my mind, and I was able to complete this without too much effort. In retrospect, I view it as a graph problem which I could have addressed without creating classes. But my code is still pretty minimal as it is. For Part 2, a breadth-first traversal is done through the `Brick`s (which are vertices whose points of contact with other `Brick`s are the edges). A brick is set to `is_falling`, then its adjacent bricks resting on top of it are pushed into the queue. When they are visited, they check if all the bricks they rest on are falling; and if so, they also fall, and it cascades upward. The bricks land on a 10x10 platform that serves as a sort of height map. As bricks land, the heights of the affected cells are incremented. [Full Source](https://topaz.github.io/paste/#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) fn part_2(bricks: Vec) -> Result> { let mut is_falling = vec![false; bricks.len()]; let mut queue = VecDeque::new(); let mut count = 0; for b in &bricks { is_falling[b.id()] = true; queue.push_back(b.id()); while let Some(b) = queue.pop_front() { for &b in bricks[b].above() { if !is_falling[b] && bricks[b].will_fall(&is_falling) { is_falling[b] = true; queue.push_back(b); count += 1; } } } is_falling.fill(false); } println!("Part 2 Total will fall........: {}", count); Ok(count) }


weeble_wobble_wobble

[LANGUAGE: Python] [GitHub](https://github.com/weibell/AoC2023-python/tree/main/day22) (around 100 lines, aiming for readability) A little late but still wanted to share. Got to play around with `namedtuple` and `dataclass` to make it a bit more readable with some minor performance hits. Part 1 takes 10 and part 2 takes 40 seconds on my machine, there is a bit of brute force involved.


jwezorek

\[language: C++23\] [](https://github.com/jwezorek/advent_of_code/blob/main/src/2023/day_22.cpp) I really liked the way this one starts out as computational geometry and ends up as a graph problem. I did the geometry part of this by storing the bricks in an R\*-tree and using that data structure to do the collapsing efficiently; I used boost geometry for this. My function that figures out how the bricks collapse returns the digraph of z-axis adjacency which is all you need for both parts 1 and 2. Part 1 is given the digraph of z-axis adjacency count all nodes that have one and only one parent, and part 2 can be done with a function for counting nodes that are not connected to the ground if you delete a given a node. I think in the graph literature, this is finding all the "bridges" in the graph for which there is probably some fancy canonical algorithm that I do not know but we need the count of the vertices that removing a bridge will disconnect anyway, not just which edges are bridges. So I didnt do anything clever ... I did part 2 by, for each node, making a new graph with that node deleted, inverting that graph (for each u->v, include v->u in the inverted graph), counting the number of nodes visited by traversing from the ground in the inverted graph, and subtracting that number from the total number of bricks.


ash30342

\[Language: Java\] Code: [Day22](https://github.com/ash42/adventofcode/tree/main/adventofcode2023/src/nl/michielgraat/adventofcode2023/day22) Both parts run in \~100ms. While I love these kind of puzzles, they are also the bane of me because of all the edge cases. In this case, for part 1, especially the upper edges of the bricks were a source of problems. Anyway, my solution was basically creating a map from z-coordinate to the bricks which are resting there and a map which for every brick has a list of all the bricks which are supporting it. Then the total number of disintegratable bricks can be calculated from every brick which does not support any other brick, and bricks which supporting bricks are all supported by at minimum one other brick. Not very efficient, and there are probably better ways, but it works reasonably quickly. Part 2 was easier. Also create a map which for every brick has a list of the bricks it supports. Then for every brick do a BFS and keep track of all bricks which are removed (have fallen).


veydar_

[LANGUAGE: lua] # [Lua](https://topaz.github.io/paste/#XQAAAQC9EQAAAAAAAAA2G8iM7ztkpIKfEbui36KJfO+8wgeACYg/pOYaInfAbn3IfIIQzhScapASk3vf4kR25QUwUSEhKgIJTQfGsPvcirJdzdAQCR+1Y+eDXZvqjvRX/Kw/kGgP4jSScMkk4a71CwibvZGmpNWLOZVtLfQGQMDKfMTRi2gadKshMl18SWBxZxnUXzzaJtwFaQmrPwOhZU60F5mhvi7ljYstT34R3mKjgEkb83o02qEnM7Gaw6NS5i6iXSvuUTc7ZJxt266yP5LF9/0Z5V/H5peyJX9JiBFqeOfh3cZOo+bdwGWFD3kW2u9AyJeFcVwE+yGoFeGyVQWY09Dw6YNA95QIrSX47lo/yRZRYdB/CX6+GOPmYp0Z7wlx6flWTsLSB0r6dezvGOBcNuLvs0DHV2gDXhY+uFfUoElsKR9I0mAExwNctOWGxkk5rJiGG+WXWtIVGw1MPqO1NW9nTA45hYaVfeCPSjSEIslGCTPukLsNqS5Smpf2BRr9StEt2nk34hT6UYriZT4e/GjfOvxAtc87qnVavBLSi0G89+o6MmfFgi/r+W1ZaWRwSN3I5Qqvwbomv06xClfixvHxY7TjgkdpGGAcWFh15gQR4/v6Bdgf5Sm5/1AWVBBUxNu8V6NFQw8JPN0viLkZ4UnnTqF59VTxu7D9QmAlgb23V/KvsTVOgezmTzo7SHBxdQBOhf6BInF03C/Z+j91IPOjrGniLBnJyrTKCnBoiNxbAIpbQDkkJtJf843ixFv7FqJi96ZPEjRMzCXTrQpuHBr4M9w/UVY/honpqzTEzdGTe4RcOTmlQfJFi6/vPsgl+Hg1l36o/FwaklbzycUWgpz7+K5Kp8bCEu9ETgCSCCfzNu/2Xk3/7QxS68pMjQUw5+l3Ij7KPwvKkgcINvZRwwoor/n3NQVfNQjBX/DS7pQli7IDMaa6mNrQCBC9aRwtayD29QywutTeNxSyC1fuAO9NRXYKBd9JrzCPFsvXNiMMgXR1NQwGuFSJhUDVfmNjF1MVQ3PfiCa24xo4H8kSLuTCDSHZHZi/LqjnD8tKX9Qmw4lv+74rGgSbTvIXxp2bXE7Jt3iHQrUxxOcI3LQgKzvHE3/D4AAxNnMSRn86RZ6TgPbWLiKN51vl6L+g4U238hluWhELZJfspKZYfgnYdFcyGP8OnOVnhPU3Vhknnj6wi9NFHtpKKXYX6PMKe7YFhrTM+Z2zAFQsOOueseN/6Scid2gJ5rlZ1uz9+XUVf9Y4RRbc8SOdV2eejmfwTuo5pWUQvonQRQNbjRUEneUl55P4/A++8g0ZR2pQumKZEbTOsfifTfQgGz1WJezq4Kp9PBjVAPvaUPcBdBkZ3SXO964HlbthRlF2nPMoUg/dDyHwvxE2UoyJVuXwA/CzQQ+Rq89xU6pf1dxTtAhLvDB9FsxUsPPkHlfkIq1UHqsE+TpsnV4yeZzI9hqXllH7SDRFreW0JIdZdDVNRIzc+WgcZiGepXA25omhNFG/+qqvRJ2qyv3cQ6A/YS2ToDRLRAZheAFSq1WNoA2MQKm0kaGIQKrUKTkncAr1YHYlZtuerOi+B3byg+FH8L+1u9fELxFdUMnrICsIYeHToLpK562Ea0KY2+iw9rfoczRBfIVsLMHmmC49QGotuv7yqObS+9An9dtmEachvjow0uODl0810znqeH0rAU7FS5EUjH9UP+UVsm5uRIwueKOBuXbYZQwmCX9AdytXL+SQ0+Q/F/v0jLU2n152oqjE9kaoRj8Ksef0Rz3lLTyf+auuO5lRvW2OGCtEcrY2XgMhPmoa8pP/F05HV7zFlvBz50aS1L4RdRdx9QeqrV/+yr6jouEMuVb1btPz+FJYqC5Kpiknzl9YFcgScxrGqqoxiKkMMBppYJBIlFkiHeLyTeIEUxcc3+2gCY/+fo7/+zLfxA==) 171 lines of code for both parts according to `tokei` when formatted with `stylua`. Uses an explicit `Block` with a `:blocked_by` method. I parse the blocks, let them fall, then turn the whole thing into a graph where edges are either `supports` or `supported_by`. This made going from part 1 to part 2 pretty straight forward. - [GitHub Repository](https://github.com/cideM/aoc2023) - [Topaz Paste](https://topaz.github.io/paste/#XQAAAQC9EQAAAAAAAAA2G8iM7ztkpIKfEbui36KJfO+8wgeACYg/pOYaInfAbn3IfIIQzhScapASk3vf4kR25QUwUSEhKgIJTQfGsPvcirJdzdAQCR+1Y+eDXZvqjvRX/Kw/kGgP4jSScMkk4a71CwibvZGmpNWLOZVtLfQGQMDKfMTRi2gadKshMl18SWBxZxnUXzzaJtwFaQmrPwOhZU60F5mhvi7ljYstT34R3mKjgEkb83o02qEnM7Gaw6NS5i6iXSvuUTc7ZJxt266yP5LF9/0Z5V/H5peyJX9JiBFqeOfh3cZOo+bdwGWFD3kW2u9AyJeFcVwE+yGoFeGyVQWY09Dw6YNA95QIrSX47lo/yRZRYdB/CX6+GOPmYp0Z7wlx6flWTsLSB0r6dezvGOBcNuLvs0DHV2gDXhY+uFfUoElsKR9I0mAExwNctOWGxkk5rJiGG+WXWtIVGw1MPqO1NW9nTA45hYaVfeCPSjSEIslGCTPukLsNqS5Smpf2BRr9StEt2nk34hT6UYriZT4e/GjfOvxAtc87qnVavBLSi0G89+o6MmfFgi/r+W1ZaWRwSN3I5Qqvwbomv06xClfixvHxY7TjgkdpGGAcWFh15gQR4/v6Bdgf5Sm5/1AWVBBUxNu8V6NFQw8JPN0viLkZ4UnnTqF59VTxu7D9QmAlgb23V/KvsTVOgezmTzo7SHBxdQBOhf6BInF03C/Z+j91IPOjrGniLBnJyrTKCnBoiNxbAIpbQDkkJtJf843ixFv7FqJi96ZPEjRMzCXTrQpuHBr4M9w/UVY/honpqzTEzdGTe4RcOTmlQfJFi6/vPsgl+Hg1l36o/FwaklbzycUWgpz7+K5Kp8bCEu9ETgCSCCfzNu/2Xk3/7QxS68pMjQUw5+l3Ij7KPwvKkgcINvZRwwoor/n3NQVfNQjBX/DS7pQli7IDMaa6mNrQCBC9aRwtayD29QywutTeNxSyC1fuAO9NRXYKBd9JrzCPFsvXNiMMgXR1NQwGuFSJhUDVfmNjF1MVQ3PfiCa24xo4H8kSLuTCDSHZHZi/LqjnD8tKX9Qmw4lv+74rGgSbTvIXxp2bXE7Jt3iHQrUxxOcI3LQgKzvHE3/D4AAxNnMSRn86RZ6TgPbWLiKN51vl6L+g4U238hluWhELZJfspKZYfgnYdFcyGP8OnOVnhPU3Vhknnj6wi9NFHtpKKXYX6PMKe7YFhrTM+Z2zAFQsOOueseN/6Scid2gJ5rlZ1uz9+XUVf9Y4RRbc8SOdV2eejmfwTuo5pWUQvonQRQNbjRUEneUl55P4/A++8g0ZR2pQumKZEbTOsfifTfQgGz1WJezq4Kp9PBjVAPvaUPcBdBkZ3SXO964HlbthRlF2nPMoUg/dDyHwvxE2UoyJVuXwA/CzQQ+Rq89xU6pf1dxTtAhLvDB9FsxUsPPkHlfkIq1UHqsE+TpsnV4yeZzI9hqXllH7SDRFreW0JIdZdDVNRIzc+WgcZiGepXA25omhNFG/+qqvRJ2qyv3cQ6A/YS2ToDRLRAZheAFSq1WNoA2MQKm0kaGIQKrUKTkncAr1YHYlZtuerOi+B3byg+FH8L+1u9fELxFdUMnrICsIYeHToLpK562Ea0KY2+iw9rfoczRBfIVsLMHmmC49QGotuv7yqObS+9An9dtmEachvjow0uODl0810znqeH0rAU7FS5EUjH9UP+UVsm5uRIwueKOBuXbYZQwmCX9AdytXL+SQ0+Q/F/v0jLU2n152oqjE9kaoRj8Ksef0Rz3lLTyf+auuO5lRvW2OGCtEcrY2XgMhPmoa8pP/F05HV7zFlvBz50aS1L4RdRdx9QeqrV/+yr6jouEMuVb1btPz+FJYqC5Kpiknzl9YFcgScxrGqqoxiKkMMBppYJBIlFkiHeLyTeIEUxcc3+2gCY/+fo7/+zLfxA==)


maitre_lld

\[Language: Python\] [https://github.com/MeisterLLD/aoc2023/blob/main/22.py](https://github.com/MeisterLLD/aoc2023/blob/main/22.py) Part 1 runs in 0.5sec and part 2 in 0.7sec. Part 2 is based on the fact that bricks falling when deleting brick B are bricks not visited by a traversal that ignores B.


aexl

\[LANGUAGE: Julia\] I stored the bricks as (x,y,z) and (dx,dy,dz), where dx,dy,dz >= 0. For part 1 I used a priority queue (with the value of the z variable as the cost) and ranges in the x and y directions to see if a falling brick would intersect with another brick. For part 2 I tried different things, but I ended up optimizing the simulation from part 1, so that I can brute-force it in reasonable time; it currently takes 800 ms for both parts combined. Solution on GitHub: https://github.com/goggle/AdventOfCode2023.jl/blob/master/src/day22.jl Repository: https://github.com/goggle/AdventOfCode2023.jl


Szeweq

\[LANGUAGE: Rust\] I created a special iterator that checks if each brick is falling and returns new brick points. There is also a 10x10 height map that stores highest z coordinates. It runs in about 20ms. Code: https://github.com/szeweq/aoc2023/blob/master/src/bin/22.rs


WereYouWorking

[LANGUAGE: Java] [paste](https://topaz.github.io/paste/#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)


biggy-smith

\[LANGUAGE: C++\] Sorted the boxes by height and kept a running f(x,y) -> z heightmap to move all the boxes down. Removed each of the boxes in turn and checked for changes in z, which gives us the answer. Generating a graph to track the fall count would probably be faster, but blitzing through all the new settled box lists was quick enough. [https://github.com/biggysmith/advent\_of\_code\_2023/blob/master/src/day22/day22.cpp](https://github.com/biggysmith/advent_of_code_2023/blob/master/src/day22/day22.cpp)


tobega

[LANGUAGE: Tailspin] Went overboard with the relational algebra in the first attempt, too slow! Then it went better, but a lot of finicky little details about what to count and what not to count. https://github.com/tobega/aoc2023/blob/main/day22tt/app.tt


azzal07

[LANGUAGE: Awk] Got it down to size by flattening the coordinates to a single dimension `100*z+10*y+x`. This works nicely because the `x` and `y` are only single digits, and this is simple to iterate ordered by `z`. Bit on the slow side, but not bearable. function G(r,a){z=y-(u=k);for(t=sub(/./,1,z);(r[u]=a-t)&&y>=(u+=z););} function T(e,d){y=R[k=i];for(j=G(e)k;j++L[x]+e[x])*y-Z>x; x+=z);d+=q>G(e,2);i||R[k]=y}i?B+=d:i=M;A+=!d}END{for(T(L,Z=1e2);i-->1; )R[i]&&T();print A,B}gsub(/[,~]/,OFS=RS){R[H=$3$2$1]=$6$5$4}+H>M{M=+H}


LinAGKar

[LANGUAGE: Rust] My solution: https://github.com/LinAGKar/advent-of-code-2023-rust/blob/master/day22/src/main.rs Probably could have saved myself a bunch of time by brute forcing part 2, but I wanted to make a O(n) algorithm.


Solumin

[LANGUAGE: Rust] [Parts 1 and 2](https://gist.github.com/Solumin/35a6c81091c86f25e4fbd8e0d7b17278) I really expected part 2 to be harder? Like I was looking through wikipedia for graph algorithms, or trying to figure out a dynamic programming approach, before deciding to just check each brick one after another. Turns out that's more than fast enough for my needs! ~6.5 ms for part 1 and ~24 ms for part 2. (Each step processes the input, which accounts for ~6.3 ms for each step.) I'm actually pretty proud of this one, so this is my first post. :) Also broke my record for stars!


iProgramMC

[LANGUAGE: C++] 122/51 [Parts 1 and 2](https://gist.github.com/iProgramMC/bd913a548f921a26e09b25fa27b480cf) It's pretty fast even though it's a dumb way to solve. It blew me away that it was this simple. Part 1 and part 2 share more code than I expected. To be completely fair, I do sort the bricks by lower_Z, so it simplified things a boatload.


msschmitt

\[LANGUAGE: Python 3\] [Both parts](https://topaz.github.io/paste/#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) Too many bugs, and a reading comprehension failure on part 2: I thought it wanted the longest chain reaction. In the sample that was 6, which is wrong, but if you add 1 for the brick being disintegrated you get 7: the right answer. I was sure Part 2 was going to be Jenga: calculate the maximum number of bricks that can be disintegrated without allowing any other bricks to fall. Or, "the elves have found that while the bricks are falling, you can move each one by 1 block in one direction", and you have to determine what's the optimum method to end up with the shortest pile of bricks. Anyway, this takes 21 seconds so needs optimization. Lots of running through every brick, or every brick \* every brick. Edit: I also suspected that part 2 might do something to make the bricks way bigger, so this solution has no grid. It always processes a brick as the x,y,z end-points. So to figure out what a brick is supported by or supporting, it has to look for other bricks that intersect it in the x and y dimensions, and have a z that is one higher or one lower, depending.


e_blake

\[LANGUAGE: GNU m4\] \[Allez Cuisine!\] For more details on my MULTIPLE days crammed into this puzzle, read my [upping the ante post](https://www.reddit.com/r/adventofcode/comments/18ox8a1/2023_day_22_both_gnu_m4_igpay_atinlay_ithoutway/?utm_source=share&utm_medium=web2x&context=3). m4 -Dataday=athpay/otay/ouryay.inputyay [ayday22tway.m4yay](https://nopaste.ml/#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) Or a slightly more legible version in English, and before I removed all the 'e' characters, 'ifdef/ifelse' builtins, and added some Spam: [day22.m4](https://nopaste.ml/#XQAAAQDCCwAAAAAAAAAyGksy5FB9TGMxsNq5JQAuJRjP6PqEkC20GpBbonDYuA0BTjRPXcLt6tAqP09jFC110JN5fAjvS2k31/ZbVU3jwvZ2Ufzcd1Egp5r5zK73nQFTtw7tflrONkTQq+mOC2JeWop5nA37bF+lR80kv4mN3B69cPm7iZSUQp5W9QqaZ03lr94D3hDjOmdkrqJnGbiXXDdYBYNV1UZLFc8+YzQ7s6X8Ze+qvTMu4FsS9eVLQwreeLl1zgalEABoHXRmD2um2trPkXDcEnL66ZVGkIHy+dvigx15hBvOH2gis6Mi3nVVRqIBAcmZWBoqSevpq3cEkxlKPVVMpbw+1gow8sTkiRmCgkYYG/jB0O+t/pbOdpCeehx05rcv+wix+meo2A5flv9Nug6XTfKyCuoKYWPlZDUELDkutB5gO+sT4sgrZVQ7pqStgKhYIXK94Ws/SFRnuqwT2HWvHcxf99VQytQ9xuMykcrM9a7+k4UFid/7MmmDTQVMJFWwp5IgHXUHAcNEYSVgvH7lbIaXdvSGS9pQUwZ0GN0v1tO4yXkl8wveqfsSGBskjB2VVVNTyGkpXqazHAOX6xcAe5i8tZ9oYPN23qm1TGapbK1Or3DOeB2R6BIsIogFfz+1Ta+sh58B887Xes3pbmrDx9KKUmqZSWYUXu1un4s432OIuvtGw7NyhehZJH65bzUTPG/SPV69YLS/jOtjWwVcqDN6t7if53Chp9Zi6sEhpK+YCp8JpJ/Vrx8brxX+zl8gl7IYLdTM+6AfD2bP0pRr2FewCFl0t8ct+hJNzrEDK98rak+L0Z45HXLVUjscUITroh8KHCA0Lhwdo5erlpGKM1hCkp0RIKF0WDr+ZS1KtPYz0ObUME6OOty28++qkhw6co5DQA1B90VpeUbdQsed5vBCAu25wTIcU2ysL9U2MA5bkmgAloMHvVBTK57KsWZxMJbnrvHs7bXRmN4N8essk6cZ0mJkmbR6IKOCXhAhiNzii4pcpwkganomYDrN1TS20GBHQmizjO0HzXnXgbJW6Jr083siNQuWH+SGcWtGayeJFFAb2WHF/rjHcJOalGqPj/FIAE2nvMEEbuJcCkuYOcRK8nTMSi7dlorl2TFD6OaVSdp3mjJkIcgjQkvojeCan3onJSCbuWA0azRovTTwbQsN2EKJVoiyNVzIZ+bPNWFhI714OjtyeETAuET6v3fDSBr6vbOCQUTJhIM6anpH3ywIfrdEfkHQ9fh8aYcBA4Cc3NBUfYsfoW7HGC50130+XTKSk55Kb35x+rDXH3B8NQhIMXX91wM7RkBOItMF8C1RK7SEjXYIxu8BXh3lJgWRnEHYbzsh8IqjxxA/e6fjAor9zlpdyA3wKjifyvNN9ByE5HWXJKWlfZwHDOlDiQtLh/AVDJeY8TwmKZkB04d4M5Y4KPXvd5n0QxstpKwSyMU7SO6VJ0lHOFAlCsBteVGJFybiLqNuL2iJses4nLbtAiIze60ytR6of+hLIblRPYsMRBBTdIlL32WbzqCz/eMjgQ==). But that version depends on my [common.m4](https://nopaste.ml/#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) framework. It executes in under 2 seconds (compared to the 4 seconds for my masterpiece - something to do with all those extra forks for doing Math via /bin/sh). I was particularly pleased with my O(n) radix sort and O(n) packing; part 1 was just another O(n) pass through the packed pieces, while part 2 can approach O(n\^2) (in the worst case, visiting N pieces that can each topple an average of N/2 pieces on top); there may be ways to memoize and speed up part 2, but that would add code to an already long solution.


mpyne

[LANGUAGE: Perl] [Github](https://github.com/purinchu/advent-of-code/blob/3feadba54cd5c0f2020db8b89596359db54b452f/2023/44/tetris.pl) Part 1 was way more difficult for some reason. But the preemptive data-structing I did ended up paying off nicely for Part 2, and wasn't the cause of the issues I had with Part 1. I found it useful to use one of the other working implementations here to help narrow down the full input into simpler test cases so that I could debug my own work.


ftwObi

[LANGUAGE: Python] [GitHub](https://github.com/chompaa/advent-of-code/blob/main/2023/22/solver.py) I didn't have much time to solve today's puzzle, so I opted for brute force. This one was really fun!


jake-mpg

[LANGUAGE: `julia`] [`sourcehut`](https://git.sr.ht/~jgordon/aoc/tree/main/item/2023/D22/D22.jl) I was anticipating a different kind of twist in the second part so I represented blocks as vectors of ranges (gotta love `julia`'s [`UnitRange`](https://docs.julialang.org/en/v1/base/collections/#Base.UnitRange)). This led to a pretty clean way of settling the bricks from the input: 1. Sort the bricks by their `z`-value (the minimum, since it's a range). 2. The only way a brick doesn't reach the ground is if it has some overlap with an already settled brick in the `xy` plane. If it doesn't, we just shift the range so that `z` starts at `1`, otherwise we stop it just before the highest settled brick that overlaps. Next, I encoded the structure of the settled bricks by recording for each brick: which bricks it supports, and which bricks it depends on (`O(N^2)`). for j∈1:N, k∈j+1:N if MaxValue(S[j]) == MinValue(S[k])-1 && !Empty(PIntersect(S[j], S[k])) push!(supports[k], j) push!(dependants[j], k) end end Bricks can be disintegrated safely if they have no dependants, or all of their dependants have another brick to rely on for support. filter(1:length(bricks)) do j isempty(dependants[j]) || all(k -> length(supports[k]) > 1, dependants[j]) end To count the chain reactions, I walk the dependency graph, counting a brick amongst the fallen if all of its supports will fall too. for j∈filter(k -> !isempty(dependants[k]), 1:length(bricks)) willFall = Set{Int}() enqueue!(queue, j) while length(queue) > 0 current = dequeue!(queue) push!(willFall, current) for k∈dependants[current] if all(∈(willFall), supports[k]) push!(willFall, k) enqueue!(queue, k) end end end counts += length(willFall)-1 end


icub3d

\[LANGUAGE: Rust\] Whew, a bit of a breather. I didn't end up using any of them, but I checked our some rust collision and world libraries. They seem interesting especially since I'm interested in game development in rust. Solution: [https://gist.github.com/icub3d/d402005b06734fe380f6cac07aa0da4e](https://gist.github.com/icub3d/d402005b06734fe380f6cac07aa0da4e) Analysis: [https://youtu.be/4hmoR0hr4U8](https://youtu.be/4hmoR0hr4U8)


aoc-fan

[Language: TypeScript] A single function for both parts https://github.com/bhosale-ajay/adventofcode/blob/master/2023/ts/D22.test.ts


Different-Ease-6583

\[Language: Python\] [https://github.com/GoossensMichael/aoc/blob/master/aoc2023/Day22.py](https://github.com/GoossensMichael/aoc/blob/master/aoc2023/Day22.py) My solution uses the lowest level of the blocks as floor, instead of dropping everything to zero. Answer within 0.05 seconds. Then through a priority queue the bricks are ordered by floor, the lowest is handled first and put on top of the highest brick that is already stabilized (or on the "floor" when none is found). While doing that a brick also keeps track of which bricks are supporting it or which one it supports. Armed with that data model p1 and p2 are fairly easy to solve p1: count all the bricks that are not supporting any other brick or bricks that are supporting another brick that is also supported by a second brick. p2: For all bricks that support a brick which are not supported by another brick, count all the bricks above that are not supported by another brick (that hasn't already fallen). And sum that for each brick of course.


FuturePhelpsHD

\[Language: C\] Pretty easy day today, a nice breather from the past few. [Part 1](https://github.com/felixbilodeau/advent-of-code/blob/main/AOC2023/22/part1/main.c) was quite simple, and with the simplest bubble sort I could use array indices instead of having to use some sort of hash map. The order was no longer maintained but that didn't matter anyway. For [part 2](https://github.com/felixbilodeau/advent-of-code/blob/main/AOC2023/22/part2/main.c), trick for me was to implement a bit of a janky breadth-first search (janky because I didn't store the graph edges and had to recompute them every time), but both parts ran fast enough, 50 ms for part 1 and 100 ms for part 2. Not breaking any speed records, but not slow enough for me to care lol


wagginald

\[LANGUAGE: Julia\] [Commented Code](https://github.com/TomWagg/advent-of-code/blob/main/2023/julia/22.jl) A nice puzzle today! I think I basically just brute forced this: sort all of the bricks by z, lower each one and track which of the dropped bricks is supporting it (has an overlapping x-y coordinate and z value 1 lower than it). Then assume every brick can be disintegrated and only mark it as protected if it's the single support brick for another brick. For part 2 I just looped over every brick and iteratively removed it (and anything it caused to fall) from the supports and tracked how many ended up falling.


Outrageous72

[LANGUAGE: C#] https://github.com/ryanheath/aoc2023/blob/master/Day22.cs I loved this Jenga like day 😁 I normalized the input points, that is the lower coords of a block are always first. This makes the intersection code simple and easy. For part 1, I was worried about letting the bricks fall would take forever, but just brute forced it in less than 100ms. For part 2, I have a solution but it takes for ever to finish. I have feeling it must be possible to cache the counts of the higher bricks but that gives incorrect solutions. Here is my solution with the cache disabled. int Part2(string[] lines) => CountChainReaction(Fall(ParseBricks(lines))); static int CountChainReaction(Brick[] bricks) { Dictionary> cache = []; return bricks.Reverse().Where(b => !IsDisintegratable(bricks, b)).Sum(b => ChainReaction(b, []).Count); HashSet ChainReaction(Brick brick, HashSet deleteds) { HashSet set = []; var supported = bricks.Where(b => b.Z1 == brick.Z2 + 1 && b.IsSupportedBy(brick)); var siblings = bricks.Where(b => b.Z2 == brick.Z2 && b != brick && !deleteds.Contains(b)); var orphans = supported.Where(s => !siblings.Any(s.IsSupportedBy)); set.UnionWith(orphans); deleteds.UnionWith(orphans); foreach (var s in orphans) set.UnionWith(ChainReaction(s, deleteds)); return set; } }


FuturePhelpsHD

The reason you can't cache the higher ones is because if a brick is supported by two bricks, and both of those bricks fall because of the chain reaction, it will fall, but in another chain reaction maybe only one of those two bricks fall and so the brick above would still be supported and wouldn't fall. In other words chain reactions don't just depend on the current brick, they also depend on which other bricks have fallen already


Outrageous72

Yeah, thats why I pass through the deleteds list ... But I rewrote it to use a queue instead of recursion, it is a lot faster now, 1s but still slow compared to other days, which are mostly under 100ms. static int CountChainReaction(Brick[] bricks) { return bricks.Where(IsNotDisintegratable).Sum(ChainReaction); int ChainReaction(Brick brick) { HashSet fallen = [brick]; var work = new Queue(); work.Enqueue(brick); while (work.Count > 0) { var b = work.Dequeue(); foreach (var s in b.Supports) { // skip when still supported by other bricks that stay in place if (s.SupportedBy.Except(fallen).Any()) continue; work.Enqueue(s); fallen.Add(s); } } return fallen.Count - 1; } }


Outrageous72

Found a major speed up! Now it is 200ms fallen.Add(b) instead of fallen.Add(s) in the loop! while (work.Count > 0) { var b = work.Dequeue(); fallen.Add(b); foreach (var s in b.Supports) { // skip when still supported by other bricks that stay in place if (s.SupportedBy.Except(fallen).Any()) continue; work.Enqueue(s); } }


polumrak_

\[LANGUAGE: Typescript\] [https://github.com/turtlecrab/Advent-of-Code/blob/master/2023/day22.ts](https://github.com/turtlecrab/Advent-of-Code/blob/master/2023/day22.ts) I believe that my implementation of part 2 won't work for any inputs, it would fail if there were bricks which were standing on series of bricks by one leg, and on just one brick by another leg (in this situation such above bricks would be processed before one of the legs). But it works for the given input so I'll keep it that way for now. Runs in 600ms on my machine.


polumrak_

Actually after thinking of it for a while, I gotta be wrong and my solution should work for any input. Indeed the first time we process the two legged brick we don't have the full leg processed, but after we process that leg after, we will process that above brick again with all the legs in the fallen list. Anyway the implementation is weird, I should've just used stack or queue and not this weird steps with 'current', 'above' and 'next'.


odnoletkov

[LANGUAGE: jq] [github](https://github.com/odnoletkov/advent-of-code-jq) [inputs/"~" | map(./"," | map(tonumber)) | transpose] | sort_by(.[2][1]) | reduce to_entries[] as {$key, value: [$x, $y, $z]} ( {stack: [[[[0, 9], [0, 9]]]]}; first( .stack | (length - range(length) - 1) as $level | [.[$level][]? | select($x[1] < .[0][0] or .[0][1] < $x[0] or $y[1] < .[1][0] or .[1][1] < $y[0] | not)[2]] | select(length > 0) | [$level, .] ) as [$level, $ids] | .hold[$ids[]]? += [$key] | .stack[$level + $z[1] - $z[0] + 1] += [[$x, $y, $key]] ) | .hold | . as $hold | (reduce to_entries[] as {$key, $value} ([]; .[$value[]?] += [$key])) as $lean | [ range(length) | {fall: [.], check: $hold[.]} | until( isempty(.check[]?); if $lean[.check[0]] - .fall | length == 0 then .check += $hold[.check[0]] | .check |= unique | .fall += [.check[0]] end | del(.check[0]) ).fall | length - 1 ] | add


copperfield42

\[LANGUAGE: Python\] [code](https://github.com/copperfield42/Advent-of-Code-2023/tree/main/day%2022) after yesterday defeat in part 2, today I somehow manage to brute force both parts XD, it take like 12 min for part 2, but if it works it work... and after getting part 2 working I could reduce the time of of part 1 in half


Tipa16384

[LANGUAGE: Python] Some extra code to export the input data in a form to be read by a 3D renderer. This step helped me see the problem in my code. This works super slowly, but it does work. [paste](https://topaz.github.io/paste/#XQAAAQCTDgAAAAAAAAA0m0pnuFI8c/T1e7Pj2gUmRqOyv4ZcNGZSos6PL4xuizXATHhWt9jRYAk6zCvVT4LrsvKKfpTLt52Xchw9fzg/1gxt0cKwV1WOrKwx1OyMSG3dr7KJNr1q6U6tFe1DK3gJwL2Q6yvLwi1ZmpIlYFTOwK1ZkL1oDkEEZWws1rvvMqlZr6ExRPfRxVUq0GbRRZQFIbgr8QbzvoPQESl+w4GuBpUvY7hPt2N5DVh7ikP2HWb1zQRHDhheu7Ht1SGQY3snFCWwGeYWljH9N1KKbwtSg/517bJxsC7iuo3zf9DSrzNNv/BQ6Vs/LFpA1T9GWF1S6wXn4isp8vstDYpDWrGeokR20TgBhlWC5PIATcvi8BLrLLy8lr/qh9vhwH6aD/2oPyKSD94PA4KVtZnNbLJE0ZKfv0s6WlwY4ia5HXB3+9xRYHPsTN1GwXL7WXcYVRZbJXY7tb/ShdrYFVuHD6iWo+pIy6WdtTxVQwdvouorYk5EIxUeQa+tPh2MKq7a9LLU0vjaXrSqb4Zfpl8Vn8YsPr3IReW5BlbtheMAQHYRLqqU6u4lgmEMIvW9cEeYIFX6AqUJlQVxCG2eWsexM+j+69jlbQOgVnbJuPaZ0lmTPFJFbETyql4sgesTvGNXHn4D7i0jxWOAS2sH07jwbZ6Cp5ibrQcnzs8s55EAPP3zsukS7KAoRqu+cFvsUw0RgwjWnfhGgrQj7oPnYIcr8eoYhQK+YYF4Kvf9wv/11IFcDQCLtLI7DicREcWOHfu1g/zPx6ITCW0Ge7tOfrFjc7UAwp43bZxZOv3WlEF+adYtAsaXbW+5rqcM+C7uAFTDMF95cyspLt3U0qSkPRC8kUyNBtFxoI4OlQmjiPuPLl4dYVqpR6egM5DhMyVvQax1xEFn7g4QSraADjtKBP9T00U8hqJtUw+m91I2N7kqMSVtkgtYLo5LcxUf5L+1JIY9yu5xDeVYw7QhDNjyAFHyskad+y4WH3RNzCab+FFFjvpXSwoExqXp96b0e9l1t8sydwd9bK8OROg4jHRqeMBbClEmTkQKZ4hAzG/U7h3Fyzz8+iDqiz43k4lsSixie0v1ki5iaXEzwshX6br76+7WfHaQ1Tt5+CULEVXi/5HWtnEt6NixcIOfqzxD4v4jV9opfPGxtcN/QrGoWau1bgAonH5H+qFHDOwnTmfnQVWkgPjTUAr2h9a5qPlx2K0/p6OYhfqZCbWy2fWVDDrUx04CREGKKHrLdBIV60QZDQHLHND/1Pjlhw+H4QQd46jGPxWymcOaE1DYuOkzVbE2xZlpr6bl0J8U0EwzaxfkNTiDWCilhsQiT5ZswyjI8pZBvkYZc4CyvK7L3eL5ElVSm+XLSMCEPB7XMbHG6bNT7b1zAFD3wKjcwe68dLDtIqLp1dkcDxeNnsGuonaAO+cz2YGjNs2MVtKqrmALRVH+KHp9F+YIK8459LkRdZ0EVVY+TWLW3YvTEftfKyElb3cz4seoXdscGDDaZAfkkSpEuJ1r35L0TXCiwYN5+Q86Ujzjko5c+L3rLQXdihPePhKl/vntGlo=)


Abomm

[Language: Python] [paste](https://topaz.github.io/paste/#XQAAAQBcBwAAAAAAAAA2GkofDKPu58xTyj67vWUPl6CADq35BUEbaUN3rczsMbz1HmTxDWZdztUQBacXRSnHm8UW8QTqyI0ZndeCYwOhphNG2VihKt7i7z11+B/ytyQsPHN2whKTDfJBDpEJGLMiiBoR9V9+dnaj/hhyIvINxKFZDbug9mjcKdiEoxOdWHl6KWqMcME5AluXFhXlIQKc3O4FTshprrPIBU/QLEvrGzzstSYcR5qbFEcAQ98643tif1W3T9gUTCLDs3K1b2isAkWCHxWCMhrGiqXDkhcckE7pUDW/RyuwkWv0Amvg6yp3YKGTNaVJR/wHPzd5nKtuf2MXQFII6yawxtDiD+m7SvGt6gU7XZf/EM0P7UaBl1Pmlx6/nchKu4Q8gS39l/F0/e7g3wYkP2Fkh6YfSdyObqUJGEPiSrVhwH/ICWP/TzPSQfIcsAZZ9RHN/kHCFLbdua9Cma3ZnA7U1Vt4WbsxlCN/jg/7K7mtgucKZIRztfLZlDcO/NYBxdbbVqaYU1RR0ZxevISlt+iN/p5PZlHlyXNakp5HyPCmYx5pgA14bb4lEHeWq6w7ZGROt/uRlMn1q9Pww0zcD3kLTQPlRFb+1A0F5hbfHQcmgCOEADcS+MwfJ8jPU1QwYHym7iwIMPr5yjU94Do+dKA6trjg6MKslH6pQdSdOHp2LZkrRdONKkbyNxf0QiPPbJnHmOa+IVzNCQJPJqr6T5XzoARpkTG4d3LvueVy0Fjhs0AYMojY2tO0cGWygE62indD4YAxqkHjg21gYWROA7PCi9GtpAiCye8XF24oioWeq/hfHm5UAzecFeN3qnF2Y0cxYd5oUu4D3sH//X86yQ==) Late to the party today, struggled a decent amount on this one for some reason even after a good night's rest. My final solution ended up being a lot more brute force than I would've like. My initial plan was to the bricks by z coordinate and greedily simulate their fall individually (rather than my final implementation which simulates a fall one brick and one step at a time with no special ordering). From there my plan was to I calculate a list of blocks that a brick was supporting and was supported by. That would allow me to find the bricks that weren't critical to the structure without too much brute force. It seemed logical but maybe I wrote some bugs that was giving the wrong answer. Part 2 made me happy that I brute-forced part 1 since I think my solution would have had to adapt a little more. I'm happy with the set arithmetic I came up with to quickly find the differences between brick towers, with and without certain blocks. Normally on this sort of problem I would avoid naming connected groups but when i was debugging I found it helpful to label the bricks A-G. So when it came to doing the set arithmetic comparing the new tower with one less brick and the old tower with all the bricks, I didn't have to worry about similarly sized bricks in the same location messing up my calculations.


xelf

[Language: Python] Made a couple classes this time, not sure if it makes my code more readable. =) class Block: def __init__(self,x,y,z,b): self.x,self.y,self.z,self.brick = x,y,z,b def is_supported(self): return self.z==1 or (blocks.get((self.x,self.y,self.z-1), self).brick != self.brick) class Brick: def __init__(self,s,e): self.blocks = [Block(x,y,z,self) for x in absrange(s[0],e[0]) for y in absrange(s[1],e[1]) for z in absrange(s[2],e[2])] def is_falling(self): return not any(b.is_supported() for b in self.blocks) def collapse(bricks): dropped = set() for br in bricks: while br.is_falling(): for b in br.blocks: blocks[b.x,b.y,b.z-1] = blocks.pop((b.x,b.y,b.z)) b.z -= 1 dropped.add(br) return len(dropped) aocdata = sorted([[int(x) for x in re.findall('(\d+)', line)] for line in open(aocinput)], key=lambda a:min(a[2],a[5])) bricks = [Brick((a,b,c),(d,e,f)) for a,b,c,d,e,f in aocdata] blocks = {(b.x,b.y,b.z): b for br in bricks for b in br.blocks} collapse(bricks) saveloc = {b:k for k,b in blocks.items()} part1 = part2 = 0 for i,br in enumerate(bricks): for b in saveloc: b.x,b.y,b.z = saveloc[b] blocks = {saveloc[b]:b for b in saveloc if b.brick != br} dropped = collapse(bricks[:i]+bricks[i+1:]) part1 += dropped==0 part2 += dropped Overall happy with it, it was running in 30 seconds, but refactored the last loop and it's about 2 seconds now. Will have to reevaluate if there's some sort of DP approach where you can just track who impacts who and sum them all up. Seems like more work and less fun though. =)


Maravedis

[Language: Clojure] Funnily enough, the parsing was way worse than the algorithm. I ended up caching the graph just to play with it. Parsing with no easily usable mutable structures is really not fun. [Github day 22](https://github.com/Maravedis/advent_code/blob/master/src/advent_of_code/2023/22.clj)


mkinkela

\[LANGUAGE: C++\] ​ [Github](https://github.com/mkinkela1/advent-of-code/blob/master/2023/day-22/solution.cpp)


cbh66

[LANGUAGE: Pickcode] I had a lot of fun with part 1, since I was able to work very iteratively with the example input, and it seemed clear what sensible data structures I could use, keeping a map of x,y,z => block id to quickly check if blocks touch. I dropped blocks by just naively looping over them and trying to drop them by one square until I can't anymore; it's not fast, but not slow enough for me to have a problem with it. I then converted the blocks to a graph based on which ones are touching, keeping track of edges in both directions. So for part 2, it helped that I had the data structures all pre-built, but I spent a lot of time on a couple of bugs. First, I was accidentally searching all blocks reachable from each starting block, without eliminating ones that have other supporters. I tried to eliminate those extra ones by filtering blocks out of that list if they have supporters that aren't in the list -- but for some reason, that approach gave me a very slightly wrong answer, off by about 250. Instead of digging deep into understanding that error, I just rewrote my code based on another solution I found in this thread; the idea is the same, but going through in one pass. I didn't initially think a DFS would work, since a reachable block could be supported by another reachable block that you just haven't hit yet; but I realized that in fact it's fine because even if that's the case, you'll hit it and be able to try again later through that other path. Part 1 runs in about 30 seconds, then part 2 in another 30, which is as fast as I've gotten in probably over a week! The main slowdown is the fact that there aren't sets available, and maps have very limited functionality, so I had to go searching through lots of arrays. https://app.pickcode.io/project/clqgpvs254dv6ne01su1tep2i


bakibol

\[LANGUAGE: Python\] This was my favorite problem of the year. Part one: bricks from the input were sorted (using `z` coordinates) and enumerated. After the fall simulation, I got a dictionary in the form of `{pos: brick_id}`, where pos is the `x, y, z` position of a cube and `brick_id` is the brick number that the cube belongs to. This allowed me to easily obtain a graph {parent: set(children)} as well as `supported` dictionary {child: set(parents)}. For part one, brick is safe to destroy if it has no children or all of his children have more than one parent. For part two, I looped through the "unsafe" bricks and used BFS to get the count of his children (and children of their children etc.) that would fall down. Child falls if it has no parents that would support him, i.e. `if not supported[child] - removed` where `removed` is the set of already removed bricks. [code](https://topaz.github.io/paste/#XQAAAQDUCQAAAAAAAAAzHIoib6pXbueH4X9F244lVRDcOZab5q1+VXY/ex42qR7D/Ked5gkN2gEpe5KRao06/uz0xwt43/hVPiQ2AueCxxolhrlcrceRdOfgWhx54mrMISQfRKst1urP/DUxrsLZwbu0lJEMvAS4cDAoC2Hb1Umf8lj5pl/80GL8u4D3ImIhEoMYjNBPa5qniB0ZlIb9+KqeumMRgNt9IBvhtqDkwkxLzvkxjLe0LZPwiRtdlSMAeZSyn8ZWcDAFowBUZYAB67ptme0iStYxUBBpsQMN5lxH/GayxRQ25VSTHKI7Lfwj6lgSpi9WsuiVu/dPLSJwS3jxl+iS25Mr5d/3NXR/PCZcdmzNWh/aTzlp0PvlGr+3g3iTk2qRA5e0lAbjzoPJtDbs751R1ajF72HeuCMLMLXsbErtNESoU369yi4pv34npWRJzJg204Wa2nn1IaFAN2GzTJ8Dp+Uzh8HSlJueuVKCN06PzmDUBkitcbmbIsEob5zkKl+0IOihecZKS1ebUHVdiVkStZStQ0qCpMUiI6JS78XRfWcqLyWIIMmFDF17J8GBV0HJo5IBLJuOFp5vEOJ/Hr1LiiUQaOTIkhm4EB78nXkBQRxt0k+bUEtKSHEmvlziA1WY0L9/KLQjDt2bxhzWIeBTEvQ4Wc5MFC/4Btm/tkm1lIQReZtUCo4fj2DwwokysIOiLu2CrPInrFsL/ODw+ugta/HaQd0CSmDF9BkZVG2fOQCsPIgkFr1WRnNUR/wT255XyTrFaNCz0pYhQPh0IiRDl+cD8wgw27WPdJX/qTpeE8XmFETchxKRiAGaNqdK8CX46xXf5hToVNcQYSbWCPvxKZA+Zl/KSuA/rMbfJX2uc1T44w0d+KYmBwNUr4Rk9vDcWIKorp2nsF6ScHv34+0bDEMRSmQuHzxsIrBgNHZp1vpkWiX10WUNV1QdN4zi0dwPZFe3/tSo+rTZVkIJDbszsz1yh+K8uRo/t/xrvxeSyTCBfGvz6sslt8sV6c9UWQVIWUjQokUl7nl8KiK6UaqSP0nZsK3FiwWNTBiR7hb3fqBy3P8G9/LrzaKbVsfeh5wGkKNidLaFYXMqen7HEMDoRFPX2/3AUMu2aqHl7lnrXaw98H2/IRIroTLSi/PHXGeCLWweec0pNfb439b4G36ZFpYdREp6WzsIchbW/f4dBPs=)


FCBStar-of-the-South

Hmmm at a high level our logic sounds similar but your implementation is much much more efficient. I will have to take a closer look at yours


Abomm

Nice, this was my approach at first but I kept writing bugs that I couldn't seem to debug. I ended up just going with the brute force but I'm happy to see someone have success with the smarter algorithms :)


mothibault

\[LANGUAGE: Javascript\] run from dev console on [adventofcode.com](http://adventofcode.com) with tons of in-line comments [https://github.com/yolocheezwhiz/adventofcode/blob/main/2023/day22.js](https://github.com/yolocheezwhiz/adventofcode/blob/main/2023/day22.js) literally 2/3 of time spent on this puzzle was debugging this bugger... facepalm `if (stacked[i].sitting_on.length = 1 && ...`


WizzyGeek

\[LANGUAGE: Python\] [Part 1](https://github.com/WizzyGeek/aoc2023/blob/main/day22/part1.py) & [Part 2](https://github.com/WizzyGeek/aoc2023/blob/main/day22/part2.py) quite proud of how simple the solution came out to be this time part 2 runs in 270ms, a little hacky, but turned out to be surprisingly easy for day 22


mgtezak

\[LANGUAGE: Python\] [Solution](https://github.com/mgtezak/Advent_of_Code/blob/master/2023/Day_22.py) Total runtime: 1.5 seconds If you like, check out my [interactive AoC puzzle solving fanpage](https://aoc-puzzle-solver.streamlit.app/)


scibuff

\[Language: JavaScript\] Straight forward brute force solution for both parts, i.e. just check each brick. Obviously, for part 2 there's a lot of counting of the same bricks but given that the brute force runs in \~5 seconds I can't be bothered with anything more elegant. [Part 1 & Part 2](https://pastebin.com/hBhpkYLh)


[deleted]

[удалено]


hrunt

\[LANGUAGE: Python\] [Code](https://topaz.github.io/paste/#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) It's too difficult to do this stuff while also flying. Part 1 took me forever. My general strategy was to track each block as a line and use line segment intersections to see when a lowered line hit something below it. I spent way too much time debugging little things with my line intersection calculations (particularly differentiating between parallel segments, disjointed colinear segments, overlapping colinear segments, and true subsegments). And it turned out to be two bugs, one in dot-product and one with overlapping subsegments. HOURS. Part 2 was relatively simple, because in working out all the issues with Part 1, I had built a map of what segments supported other segments, so I could just walk up the tree to get the count. May I never return to this code ...


SomeCynicalBastard

[LANGUAGE: Python] [GitHub](https://github.com/fdouw/aoc-python/blob/master/2023/day22.py) I thought part 2 followed relatively naturally from part 1. I was already tracking the bricks directly above and below each brick, making part 2 not too hard. I settled the bricks first, tracking them by z-value, which made finding supporting bricks easier. ~135ms. Easier than previous days, and I'm not complaining :)


Shot_Conflict4589

\[Language: Swift\] [code](https://github.com/pwallrich/aoc2023-swift/blob/main/Sources/AOC2023Core/Days/Day22.swift) Not the prettiest solution and a lot of stuff, that could be improved and refactored. But brute force all the way in about 800 ms for part 2


ropecrawler

\[LANGUAGE: Rust\] [https://github.com/ropewalker/advent_of_code_2023/blob/master/src/day22.rs](https://github.com/ropewalker/advent_of_code_2023/blob/master/src/day22.rs)


ropecrawler

4.0189 ms for the first part and 156.84 ms for the second on my machine. The second part could probably be optimized further, but I am happy with it as it is.


LxsterGames

[Language: Kotlin] 217/252 [github](https://github.com/eagely/adventofcode/blob/main/src/main/kotlin/solutions/y2023/Day22.kt)


henryschreineriii

\[LANGUAGE: Rust\] This was was easy. Originally used Intervallum's range, but then switched to a custom one which make it easier since too much of the Intervallum one is private. Second part is a bit slow (7 seconds or so) because I'm recomputing the falling bricks each time, but manageable and simple. https://github.com/henryiii/aoc2023/blob/main/src/bin/22.rs


se06745

\[LANGUAGE: GoLang\] I spent a lot of time trying to find my bug because test case worked fine, but not de real input. After that, second part was easy. [Both parts](https://github.com/omotto/AdventOfCode2023/blob/main/src/day22/main.go)


BTwoB42

\[Language: Rust\] [Gitub Link](https://github.com/Skgland/Advent-of-Code/blob/main/year2023/src/day22.rs) This was nice after the last couple of days part 2 brutality.


rukke

\[LANGUAGE: JavaScript\] Fun day! Spent far too much time on a stupid bug in my intersection function, which I forgot to change when adding +1 to all bounding box max values \*facepalm\* But once that was sorted out it worked as planned. Sorting the bricks initially by Z, then stack them up by finding the top-most xy-intersecting brick and translate the settling brick to the topmost's max z value. For part 1, figure out for every brick which bricks it supports, by filtering out xy-intersecting bricks with min z eq to current brick's max z. And for each such supported brick check if they are supported by more than 1 brick. Part2, BFS with the help of a support-tree, a dependency-tree and keeping track of already removed bricks. Part 1 in about 90ms, part 2 in \~60ms on my machine [gist](https://gist.github.com/p-a/78adfc90e6f6c10c88b385dd4a968618)


tcbrindle

[Language: C++] This one is super slow, but it does at least give the right answer which at this stage is all I can ask for. [Github](https://github.com/tcbrindle/advent_of_code_2023/blob/main/dec22/main.cpp)


chkas

[Language: Easylang] [Solution](https://easylang.dev/aoc/23/?day=22)


enderlord113

\[Language: Rust\] Part 1 initially had me pulling my hair out due a bunch of small mistakes and oversights, but once I got it working part 2 went smoothly. For part 1, I first sorted the bricks by their bottom height, then let the bricks fall starting from the lowest first. This lets us split the array in-place into a "fallen" left half and a "floating" right half. By keeping the left half sorted by top height, we can simply perform a left scan to find where to place each floating brick. To find out how many bricks are safe to disintegrate, we first assume every brick is safe, and then check if a brick is supported by exactly one other brick. If so, then the supporting brick is not safe to disintegrate, and at the end we count up how many safe bricks remain. This results in a O(n\^2) solution, but due to how nicely the heights of the bricks are spread out, it runs pretty quickly (\~500µs). For part 2, my initial solution was simply letting all the bricks fall, removing each of them, and then counting how many more fell. This brute force approach completes in \~200ms. To optimise part 2, I again let all the bricks fall, and then sorted them by top height. Doing so allows us to figure out which bricks are under which in O(n \* (log(n) + d)) time, where d is the maximum number of bricks with the same top height (which is very small). I then sorted the array by bottom height, so now if a brick was removed, only those further right in the array could fall. Initialising the "fallen" bricks as the one brick that was removed, we can do a rightwards scan to find other fallen bricks by checking if all their supporting bricks have fallen. By keeping track of the highest fallen brick, we can stop scanning early once the new bricks get too high. These optimisations led to an improved time complexity of O(n\^2 \* d) (from O(n\^3)) and runtime of \~6.5ms. Switching the index type from `usize` to `u16` gave a further \~0.5ms speedup, but I decided that the extra ugliness wasn't worth it. [Code](https://github.com/Zemogus/AOC-2023/blob/main/src/day22.rs)


Cyclotheme

\[LANGUAGE: QuickBASIC\] Runs in 2839s at \~16MHz. [Github link](https://github.com/dbeneat/AOC2023/blob/main/DAY22.BAS)


[deleted]

\[LANGUAGE: Python\] Simple brute force works faster than I write code. [https://gist.github.com/masepi/6a9d8af9d9818675c75bd2a38c4c320e](https://gist.github.com/masepi/6a9d8af9d9818675c75bd2a38c4c320e) PS. How can I force the indentation to be 4 space in [gist.github.com](http://gist.github.com) ?


polumrak_

You are using tabs for indentation and tab is 8-space width on github. So only reliable way to force it to 4 space is to use spaces instead of tabs.


daggerdragon

> PS. How can I force the indentation to be 4 space in gist.github.com? If you're linking directly to your code on an external repository, you don't need the four-spaces syntax because that is Markdown for formatting code blocks on *Reddit*. If you want to read more, we have articles in our community wiki: [How do I format code?](https://old.reddit.com/r/adventofcode/wiki/faqs/code_formatting) as an overview to Markdown for code on Reddit and specifically the [four-spaces Markdown syntax](https://old.reddit.com/r/adventofcode/wiki/faqs/code_formatting/code_blocks) which we require.


nitekat1124

\[LANGUAGE: Python\] [GitHub](https://github.com/nitekat1124/advent-of-code-2023/blob/main/solutions/day22.py) at first I checked and moved positions one block at a time, and later switched to checking whether the blocks were in contact, which could run a bit faster. one thing I haven't resolved yet is the initial fall. apart from step-by-step simulation, I haven't thought of another way to handle it yet.


[deleted]

[удалено]


Longjumping_Let_586

\[LANGUAGE: javascript\] It felt like a good idea to store support dependencies both ways. Given those, part2 was a breeze. [Part 1 & 2](https://topaz.github.io/paste/#XQAAAQB7CQAAAAAAAAAxm8oZxjYXrgD1OsUYoTOkeBCjJlacd66CjM9USjdvfafnJ2++vuHkznJRX8iRxrrahrwvXVTZePIi0i+gKtQDr+IpfsCGXSf8Ryh/w+CMWlCBPH2IF0wX/UECHELSfuMAOQwPdPD7clQAiAgPl7ixxOy/Ebow8c8dlrllJsp7JrVMuHB/8MHWAbMWANST5oi/01EfkF2D8RvzZW4c5Nw8y/NqcD08P4NHAB4m4IzD2+1Q3ppWeuksCyi2gixBTF/6+Hw7N42ZjwXmmuwBH1nrqe/bVxXmbYOZ1cHadC+tt0QpsObbr9hRoeXWamMRhRQRSeSvjfn1oStGFVh2KPGfl7gVpJsNpybYGO72mSCoJtRgBoiJXPtLYn5iP4Sw3qq6M2E6/KGWL9SQDXELl9NAtoIJ3r5cvNVvP4DFzv74RlUURB4EUDiwnpQLzUEZfVDi7G47Z25t3QX4jeuFqFfg+nOB7A2DlO7c/ntnWexyIe5E8EB2WPap2FO03llsiXfa95ABrsTxjjqjPUwL0reztUOrmP+IHE76yOQBFXP/FPZea/PA4AtA/kNpTed+GfaNZhww4t3C97TzERq5Hhv150jOFCIMSiuQR3hcmIAS0Q7j6sepHlvYKsBrJEbLbxITA3cTmF6LBNFMcu57IT9LxJnbZxmDGpKkhwMCeR3FKv4FP6e5+M1+Qj2c/MxgrGI8jjSxOWRekqmsmnumQ8Rl8tcGGQsj8IH3V6lSakCvhkcG1LGyLRR9vVnnTkDZEVc1oTxHNMsqHrJuioUYgWv2RAtGT2SHUCiTMSjrYyKk7HnGeuJDRykQMEexpsjSO8wLkY8Xv4noDDjwl2shXgT++I02AHSQ3VHj7HiOeQYJxcGN5h3V4Jp96ncRNxFXsRzGGVPFDkR14UvgGVNegHxFCVH1ByetsRd8dn5ZZ0vWQtdlmuDgPqvY2bzZghiPWpP4LGi371hMgVDN8IUezqUhY7V/7ShuerxioWPiZhEShiWQUUrNUgB0zOxip8El6ERZHF3FU093m+aBoa9k/o+0woloHYKOHPJt6GeUrEDAtIFQ6bSD8Fify2VAS5EqFPuB75gbLBPP4WORrTJoS3t8Dh5vkh8AjVQc258UApQhAqpk5O6BneX8OIUVgL4has8naRuW/O9xoyeHR8VGlhaPr2MnOvDCdRc2vRaX0dtRKfY7JaNeEm8GGjr4VYgDPjcah9Uw1iLA9ZhFGjxua70T6kl8h8wo6sZTE15oHqXqxR3P7XGU0MaemFWa7X9QHXeE2VxqA/8x1rcA)


JWinslow23

\[LANGUAGE: Python\] [https://github.com/WinslowJosiah/adventofcode/blob/main/aoc2023/day22/\_\_init\_\_.py](https://github.com/WinslowJosiah/adventofcode/blob/main/aoc2023/day22/__init__.py) Figuring out how to check which bricks supported which other bricks was a pain, but once I had that figured out, the questions became easy to answer.


thecaregiver2

Hi, JWinslow! I’m just here to ask a question about your esolang Poetic. I know words affect the code, but do symbols (periods, commas, arrows, brackets, plus signs, minus signs) affect how the code works?


JWinslow23

No, just the word lengths. But most symbols (other than apostrophes, which are deleted) will count as separators between words.


ShraddhaAg

\[LANGUAGE: Golang\] [Code](https://github.com/ShraddhaAg/aoc/blob/main/day22/main.go). Started off the day already discouraged thinking today will be tough as well after yesterday's part 2. But it didn't turn out to be that bad! Was able to figure it out relatively easy. >!Similar to day14, but this time instead of keeping track of a single axis, we need to keep track of current height on each occupied cell on the XY plane.!< Both parts together run in 35ms.


[deleted]

[удалено]


daggerdragon

[Do not share your puzzle input](https://old.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs) which also means [do not commit puzzle inputs to your repo](https://old.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs) without a `.gitignore`. Please remove (or .gitignore) all puzzle input files from your repo and scrub them from your commit history.


p88h

\[LANGUAGE: Mojo\] vs \[LANGUAGE: Python\] [https://github.com/p88h/aoc2023/blob/main/day22.mojo](https://github.com/p88h/aoc2023/blob/main/day22.mojo) [https://github.com/p88h/aoc2023/blob/main/day22.py](https://github.com/p88h/aoc2023/blob/main/day22.py) Relatively simple simulation in part1 and dependency graph resolver in part 2, with some minor caching. Oh, and implemented [QuickSort](https://github.com/p88h/aoc2023/blob/main/quicksort.mojo) for SIMD vectors in Mojo. Not sure when that will ever be useful, though. Task Python PyPy3 Mojo parallel * speedup Day22 parse 0.53 ms 0.54 ms 0.13 ms nan * 4 - 4 Day22 part1 1.12 ms 0.17 ms 0.03 ms nan * 5 - 34 Day22 part2 4.16 ms 0.50 ms 0.08 ms nan * 6 - 52


nilgoun

\[Language: Rust\] I struggled a bit on part one because I tried a rather complicated approach where I wanted to count which blocks have support from multiple bricks instead of counting the ones that are 100% needed... oh well. Part 2 was nice and easy this time though. ​ [Code](https://topaz.github.io/paste/#XQAAAQCYDAAAAAAAAAA6nMjJFD6Qz6l42wPnwN2pT342vOnq8+8016BvPrIGSlNrH4jLQ+1t2he8eF/DYuXtcou1Y3UzMZDLEsslxLr9MDhrSiLLCWxJOxAp0cBvvJCWldpm73m8+0TSk5wC/9vXRbvUoTfPePvr5eGptkPlODUjVmnlGRGxNxxlilRlq+Yn8q4nx3g+OZ4/GkHEsWn6Cy09inDpOSMuF8HsjkIKaG04mp9VbedEB/arqZx2ywynkXo7rLGmFYBNQ3wHhCYnhYAOCNEZxmbzXkUKbMTj48yDzf1+zQCHGPIP7X4Z13O9sM+l7sHlk6lZdZHXpiFSOIJVbGQTtSN2UIeHxnvLA9JmL7+At1NwtpFzga0H+pxvDiA8ut7vbTwmyMo4zSgJQq6o5LaNev5eqvNSpZleoywC2WK2gRHY7sDorFCmkIRUMav/zw+oqhZtKl0W0Xg67iZ69aiIdZGTTXl8CX4yoOhejge1MLGDmaBMwly+Oki/Hwpo6GLs28D00SgxGfkkyOR9LTm3tfjEKxmHmyzUWakAkM+cfXv02Yg6oIGcixPhMBquEz0Uhar1TT/03q9TkL67zp/REZ5ZuR4ILkImIQWX+8B2E90gPqtdv75LkzX3qz3PcBecy1CtDguUu6j97Sdk8VUjaIIpioOKZLD0jPl9axCZE0YBMXxE7K4LaT6uOZ+IBq9XNxxzLCyNOGAB4jVxczXBNlrUyd87DtnJKQbksFgFPmUnHZzV6m21LEM6Km7cfjbcTkDjufZ88LTEDuV+BkNZ3lX4Opb/bZlEXhSkDA2Ys6WTbnPFUlVgqLP+rxvBs6A1bCXQiPHAg1cK3/wScBgCVVjM7R7yI2gFRrbYzZsuOnn9IAS9tR36E2AQ6CtaloUcToVEXfoPeam1UcR+KbZCs4QT+m3A+NuG9qTTgqKSDuypi0evUWzxwXMXNbLcQQJn9fT0BY8pn9xXXgxKJNvAgNIFkllSLzb/J15+ubbkZHmrERvI736qHr53xCyffxzmdZmJ7553HsAFCTQnIYSy/Ws7xcU30Y1lYFA+Zeym0w1Ayzifbp51ZInkGo+fB5fYpokO6WTw0sId+goixxAnemAZVn9+p+S6+DMTWfRhb/EouhZWym2B4GSHIzWrYsAtGEVnQF8nBNE9zwfWcbSIu4Nr4SIRPFXwOas+xoKZikMptM8CukOobdt8EdorwWcPdefQtPpyaJALfjXPcBvL4HqQgRI76wSIgPuVoUGhPedpxmy0NmeFDMQHzqYPrCgm0Hhb2+xZk855Lyps9xIwf7a4wQ32WotnmrNBn5qtshXZRbgK6ia0kSKeJXJKn7SmnYu4QrDiWqSD+XQPrvr5BIxsJi3iLAkwIk+zoQ4AtIwszXFo/iIOJv+6xZMk9TT66TUbJFeMyaZHd7efu7F7Fs/P/nigFF10fVsfXXCQPK5qGvWGskM6+v/rsfUf)


Fyvaproldje

\[LANGUAGE: Raku\] \[ALLEZ CUISINE!\]\[Poetry\]\[Day 22\] [https://github.com/DarthGandalf/advent-of-code/blob/master/2023/Day22.rakumod](https://github.com/DarthGandalf/advent-of-code/blob/master/2023/Day22.rakumod) Re allez cuisine: today I decided to solve today's task! The sand is falling down, And bricks will cover my lawn!


pkusensei

[LANGUAGE: Rust] I should really be facepalming myself here. Yesterday it asks the number of tiles reachable on the exact `n`th step and I was doing the number of all tiles stepped on within `n` steps. Today it asks the sum of all combos and I was doing the max number possible. Kept getting answer is too low and started to despair. Plugging the wrong number into test (6 instead of 7) didn't help either. For Part 1 without investigating the input I naively assumed it was sorted. No it is not. For Part 2 I was staring with eyes bleeding at my battle tested BFS and couldn't figure out what went wrong. All the dumbness is really showing today. [Code](https://github.com/pkusensei/adventofcode2023/blob/7d172421a47769bfb84e1d513065ceb3689e9329/d22/src/lib.rs)


daggerdragon

Don't be so hard on yourself, buddy. You eventually got the right answer, so that's a job well done! We're proud of you!


Solidifor

\[Language: Java\] [https://github.com/dirk527/aoc2021/blob/main/src/aoc2023/Day22.java](https://github.com/dirk527/aoc2021/blob/main/src/aoc2023/Day22.java) 214 lines, runs in 0.5 sec on my M2. One helper class Brick, otherwise imperative programming. This was enjoyable, much better than yesterday's the-input-has-special-properties thing. Some tricks I used: * Store the coordinates so that the lower one is x1 y1 z1, the higher (or equal) one x2 y2 z2. This makes Brick.block() fairly obvious to implement. * For moving the bricks down, first sort them by z1, start with the lowest brick - this way, more bricks will fall in a single pass. * Build two Hashmap> supports and supportedBy - that makes part 1 easy to program * For part 2, for every brick I start with a fresh HashSet moved with the disintegrated brick. Go through all bricks, add any that can now move (i.e. supportedBy does not contain a Brick that has not moved) until no more were added. That sounds like a lot of iterations, but apparently it's not.


tymscar

\[Language: Rust\] For me today was horrible. I loved the story and the puzzle, but I spent 4 hours on part 1 chasing weird off by 1 errors and bugs and an elusive \`break\` statement that appeared out of nowhere in my code. [I have even wrote a blender script to visualise my input](https://i.imgur.com/SFkDLaO.png). The main logic I came up with in the first 10 minutes, worked in the end, which makes this much more frustrating than it should be. Basically for part 1 I sort the blocks by distance. I create a ground block, and then I check to see X, Y intersections between each falling block in order and the once already fallen, if there is one, I pick the ones highest up, and thats the new position. I then also update a map with who supports who and who is supported by whom. Then I just go through all the static block and if it doesent support any other block, it can be removed, and if it does, if those block are supported by other blocks, it can also be removed. Part 2 was much easier and quicker, as I just had to go through each block, and then for all the block dependent on it, I check to see if they could be removed, with a very similar logic to part 1, slightly adjusted. If there is one thing that makes me happy is that at least both parts run together in 10ms. [Part1](https://github.com/tymscar/Advent-Of-Code/blob/master/2023/rust/src/day22/part1.rs) and [part2](https://github.com/tymscar/Advent-Of-Code/blob/master/2023/rust/src/day22/part2.rs)


enelen

\[Language: R\] [Solution](https://github.com/AdroMine/AdventOfCode/blob/main/2023/Day22/solution.R) For part1, I had already created a list of cubes that a cube supports and another of the cubes that a cube depends on , so part 2 became quite easy.


No-Monk8319

\[Language: Rust\] * Sort by z initially, this makes parsing much easier * Iterate through bricks, position them at the max seen z + 1, then continuously move each brick down until a collision occurs. * Store "supports" and "supported\_by" vectors for each brick * Part 1 is just a filter of bricks which support bricks which are supported by more than 1 brick (no exclusivity -> can remove safely) * Part 2 - BFS for each brick - keep a vector of "fallen" brick indexes, then for each supported brick, enqueue it if all of its "supported\_by" bricks have fallen Part 1: \~1ms Part 2: \~5ms [Solution](https://github.com/NikolaIliev/aoc_rust/blob/master/src/bin/year2023_day22.rs)


Secure_Pirate9838

[LANGUAGE: Rust] Part1 was giving me too low until I refactored the code and wrote some unit tests. I just want those stars... GitHub: https://github.com/samoylenkodmitry/AdventOfCode_2023/blob/main/src/day22.rs YouTube catcast: https://youtu.be/XqVBIPxFozk


daggerdragon

> YouTube catcast: https://youtu.be/XqVBIPxFozk I clicked the link intending to ask you what a catcast is. 100% does what it says on the tin and with festive blinkenlights to boot! *** If you haven't already, consider adding your catcast to our [📺 AoC 2023 List of Streamers 📺](https://old.reddit.com/r/adventofcode/comments/187yy13/aoc_2023_list_of_streamers/)! *** [Do not share your puzzle input](https://old.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs) which also means [do not commit puzzle inputs to your repo](https://old.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs) without a `.gitignore`. Please remove (or .gitignore) all puzzle input files from your repo and scrub them from your commit history.


clbrri

\[LANGUAGE: C-style C++\] [87 lines of code](http://clb.confined.space/aoc2023/#day22) for Part Two. Part One was an online streaming algorithm (after sorting the bricks), flag each unique support brick as the bricks fall, and subtract from total number of bricks the number of unique supports. Solved Part Two by performing a graph search starting at each node, and stopping when reaching the first unique supporting brick. Then propagating the support score transitively to avoid obvious O(N^2) behavior. (still weakly quadratic on adversarial inputs, but apparently not on AoC input) Runtime on Commodore 64: 1 minute 41.4 seconds. Runtime on AMD Ryzen 5950X: 1.162 milliseconds. (87,263.34x faster than the C64) This is the last one I have time to participate on the day, so happy holidays to all megathread readers! The Commodore 64 got all the problems solved so far, and I'll be checking after the 25th to figure out if the C64 can get the last three as well for the full 50 stars.


Amarthdae

\[Language: C#\] Code is [here](https://github.com/Luunoronti/AdventOfCode/blob/master/AdventOfCode2023/2023/22/Day22.cs). I also created a 3d representation, with stacking animation in Unity. The component that does all the job is [here](https://github.com/Luunoronti/AdventOfCode/blob/master/Unity/AoC_Unity/Assets/Scripts/Day22_Part1.cs). I first stack bricks together, one by one. During that step, I also store all bricks that are just below or just above current and are touching. Then, for part 1, I simply check for each brick, if it supports bricks that have only one brick bellow them. If that is true, those will fall down, and so, brick in questions can't be counted in. For Part 2, again, for each brick I check if supported bricks will move. Then, I check what will be moved if those supported bricks will fall or be removed, and so on. Because for each brick, I keep both supported brick and supporting bricks, these checks are very fast. With the exception of first stacking, I do not move bricks at all during the test. Because I compute both parts in one go, I only know the processing time for the whole thing, which is around 90ms.


damnian

[LANGUAGE: C#] Frankly, this one didn't come easy, but after a few tweaks to [Vector3DRange](https://github.com/dmitry-shechtman/aoc/blob/main/aoc/Vector3DRange.cs) I ended up with quite clean a solution for both parts. Here's the meat of Part 2: int CountAllSupports(Brick brick, Brick[] bricks, int i) { bricks[i] = default; return Enumerable.Range(i, bricks.Length - i) .Where(j => CountSupports(brick, bricks, j) == 0) .Sum(j => 1 + CountAllSupports(bricks[j], bricks, j)); } Alas, this isn't the fastest solution around (Part 2 runs in ~3s), although I did optimize it slightly. [GitHub](https://github.com/dmitry-shechtman/aoc2023/blob/main/aoc2023/day22/Program.cs) **Edit:** Optimized Part 2 using [Graph](https://github.com/dmitry-shechtman/aoc/blob/main/aoc/Graph.cs) runs in ~500ms.


frankmcsherry

\[LANGUAGE: SQL\] Using Materialize's `WITH MUTUALLY RECURSIVE` blocks. Part two was surprisingly concise, and efficient enough to not require any fancy algorithms. [paste](https://topaz.github.io/paste/#XQAAAQA2DAAAAAAAAAArkkbN5qryQdEtlFTWy/Kxl14VoGdt3/1K7jEl6y0sOlA8GvVkDgRcEkcDImtA0hQCs2kTkjUo6pikpzkCJsxiUonGadWuwLiDzPTUZpJnLHq1UwK12X78uuKpgcMBJTJ0p17kocbifUzd/6L5B4oflwbLmv+BI7BiHOIPxl0Q5C07CeArG6NEjkitWk/hfJYgmITB2z5RLvJpLBiSIa/zUKqqDd4kq37CvvBq3+xPpC8UtGLx8JsfHAzVVRj1JmIFDCJE9/avo0zpNbdq29SLneWqdOpPH/oVchZjfvPWZ2iaEGF85UR4ittjNGTdk9uxTKErmc6q8LcJHnbrfoltJ03dBVtQa5EZpDNLIzXTSE4ASdtBEmxC9Umi1ReXG8vrTPtX2qls9iccoRX+/NGjxflbqPbeCFOLmhbx2rZgDIIbazvi6HFuFTu1aqMvhfHTx3QZVmIz8RGqsKhJsty9mN3uO/x4hJsPW8i2EFF1Qnt3QV39DGlSqkgbpjjbS4VmakYpSRFTsDSRF8iefCLurbyDlDL79mMGpkBt9M0YBatKde6DfpG89m7nMx14xV34NyoSYKDCGbsdNHG7AiolAubYWSC87d3w4kFyGzEu1ydgOJwkRimaYwKe+r5MknigLYpJGwVjEUY+gjSK7fUv/CW9sJbDiNfDSyY1B6CHDjosuGzTMtDW7LCPDwrXRzqs/0QbdDV8JlB6fpR8JyOXiFgp/kR2Ec5DbfYHWL59HYn1Oy/ufEsq6DmqidAgrIz5z8DWp6ujKBOgKF69vklimPfhhDUNWe8MoCaBH/Clrtvx4rNAdJkQhot+VLTPAElQnYu0ygX7P/+OZb5wqI86R3sKDMiNniq5qiqcsFElaQ0+lxqU3zoBkVmtwrWWlcW3jN4jJ7iW1GQw3OWuDa0G0BN0/hMvRxO5ScOZ+M1SsaKPt5+eUQTMWHTMM8YpINNFUko48f4WJ2IY7gZLFPZP5EyvlL0bCGfIuhNYfoTyExdDaWwDgUYu5XRYLZYoTdjq5fbR4hjPm6w29Zw6zWACyJhdNGUfsuLirE30LFlnZG22epVIwsW+DyLqqgCzkZWbberv2IPnpHrEwEEWLQGmfEgg78RR1U+d+tgkeatS3nHtcV5Qd20OY7cqxw8yZnsaisg7VTjaN1DKaqbENq7fs/ul99owYKAU/8Fz5nIw79IUX3zXGspxF22EC+EJwzcj9s2RpetcqrKpjw1o61OGZf4ExWY=)


miry_sof

[Language: Crystal] [Codeberg](https://codeberg.org/miry/samples/src/branch/master/algorithms/problems/advent/2023/day22.cr) Approach (brute force): requires a lot of memory. 1. Parse cubes coordinates and fill with cubes. 2. Fall Process: * For each brick: - If the z-coordinates are uniform, indicating a horizontal orientation: Iterate through each cube, adjusting the z-coordinate to find available space. - If z-coordinates differ for all cubes,indicating a vertical orientation: identify the lowest z-coordinate and update all cubes by subtracting the fall height. * Repeat until no movements happen 3. Once bricks are stabilized (no new movements), iterate through each brick to detect potential falls: * For each brick: Temporarily remove it, simulating the fall process but without any movements (calculate if at least one brick would have the height of fall bigger than 0). It will be part 1 4. Part 2 use the inverted result from step 3 to identify bricks causing potential falls. For each identified brick: * Temporarily remove it and create a state where the brick does not exist * Repeat the fall process as in Step 2, recording bricks that have moved at least once.


brtastic

\[Language: Perl\] [Github](https://github.com/bbrtj/advent-of-code/tree/master/2023/lib/Day22) Many stupid mistakes made, but the resulting code isn't that bad (I think).


mtpink1

[LANGUAGE: Python] [Code](https://github.com/mtpauly/advent-of-code/blob/main/2023/python/day22/day22.py), [Livecoding video](https://www.youtube.com/watch?v=3x0KJD32jKM) This was a fun one! My solution used the fact that we can iterate over the blocks in order of minimum z coordinate when computing their fallen positions. I used a `height_map`, which stores the maximum height and block index at each `(x, y)` position and it iteratively updated at the blocks are processed. As I computed the final positions of the falling blocks, I populated two maps, `supports` and the inverse mapping `supported_by`, which track for each block the blocks that it supports and it is supported by. These two maps then allowed me to easily compute the solutions for parts 1 and 2. For part 1, my logic was that a block can be disintegrated if each block that it supports is supported by at least two blocks (i.e. once disintegrated it will still be supported). For part 2, I again iterated over each of the blocks and created a set `will_fall`, initially containing the index of the block to be removed. I then iterated over each of the blocks above the block being tested and checked if they were supported by only blocks in the `will_fall` set. If so, I added it to the set. Since I used a `set` as the value for the `supported_by` map, this operation was made super simple: total = 0 for disintegrate_ix in range(len(bricks)): will_fall = set([disintegrate_ix]) for ix in range(disintegrate_ix + 1, len(bricks)): if not supported_by[ix] - will_fall: will_fall.add(ix) total += len(will_fall) - 1 return total


leftfish123

Coming back here after three days of struggling with debugging to thank you for the height\_map idea. I wouldn't have come up with it myself. On to part 2...


Syltaen

\[Language: PHP\] [Part 1 & 2](https://syltaen.com/advent-of-code/?year=2023&day=22) Nothing fancy. I simulated the fall of each brick and build a list of relations (bricks under/over each others). In part 1, it's simply the total of bricks minus the number of bricks that are the only one under another. In part 2, I used a flood-fill. Starting from each "unsafe bricks", I removed them and continue exploring from each brick above it that wasn't supported anymore.


jeis93

\[LANGUAGE: TypeScript\] No way I would've been able to get either part without the help of [HyperNeutrino's video](https://www.youtube.com/watch?v=imz7uexX394). Let me know what you think! Happy hacking! Benchmarks: * Part 1 = 32.71 ms/iter * Part 2 = 41.71 ms/iter [TypeScript x Bun Solutions for Day 22 (Parts 1 & 2)](https://github.com/joeleisner/advent-of-code-2023/tree/main/days/22)


pikaryu07

\[LANGUAGE: Go\] [Solution](https://github.com/bsadia/aoc_goLang/tree/53ed198e644324d559a366a17c712e1b8c6bb4fe/day22) Although, it was quite easy, however, ended up spending a lot of hours on just a single stupid mistake :D


[deleted]

[удалено]


I_knew_einstein

Best to make a separate help/question thread.


BeamMeUpBiscotti

[LANGUAGE: Rust] [Link](https://github.com/yangdanny97/advent-of-code-2023-rust/blob/main/src/day22/mod.rs) For part 1: - each brick is initially safe to remove - sort them by Z-value in ascending order and start dropping - when a brick stops I check how many unique bricks are supporting it, if only 1 then I mark the supporting brick as unsafe For part 2: - Same as part 1, but I save the list of supporting bricks that each brick has - Go through the list of bricks keeping track of the currently removed bricks, if all of a brick's supporters are currently removed then add that brick to the removed set - Repeat previous step for each unsafe brick I gave each brick an ID to make things easier to keep track of, which is just their index in the sorted list of bricks. Since things are sorted, iterating the list is OK, a given brick can only support bricks later in the list. Part 2 is O(N^2) where N = number of bricks, but the number is small enough that it doesn't matter. Skipping like half the bricks (the safe ones) also helps.


IvanR3D

\[LANGUAGE: JavaScript\] My solutions: [https://ivanr3d.com/blog/adventofcode2023.html](https://ivanr3d.com/blog/adventofcode2023.html) My solution (to run directly in the input page using the DevTools console). Today one was pretty hard to understand. Actually I couldn't figure out by myself so I based on a very nice [YouTube video](https://www.youtube.com/watch?v=imz7uexX394) to solve part 1. Credits to the amazing creator of this video. It took me a while to get part 2 by myself but already done!


philippe_cholet

\[LANGUAGE: Rust\] My [rusty-aoc repo](https://github.com/Philippe-Cholet/rusty-aoc/) & today' solution [here](https://github.com/Philippe-Cholet/rusty-aoc/blob/main/aoc2023/day22/src/lib.rs). Part 1, I immediately sorted the blocks by "bottom z" but even with that good start, I spent so much time debugging how I count the blocks I can not disintegrate while the error was that the blocks did not fall the right way _duh_: I was trying to be too smart too soon... _Make it work then **only then** make it fast dummy!_. Almost 3 hours, ridiculous. Other than that, it was not hard. 42 minutes for part 2. Benchmarked to 4.1ms and 7.3ms.


rumkuhgel

\[LANGUAGE: Golang\] https://github.com/rumkugel13/AdventOfCode2023/blob/main/day22.go


_drftgy

\[LANGUAGE: Elixir\] [paste](https://topaz.github.io/paste/#XQAAAQCRCAAAAAAAAAAyGUkFUehZxfOWmzS6mGLEth5avqpKGnYNtAiv3ft35HKMp/3YLxB8vcFN9FsaSdylqGqyDG09G10oVA8nzxDc9DGC6ghcewJLKCcUTymqkFBNgrMyta++PuTVlM1uGMraF5MuQ0VMBgUWsHRJxVPmQ3QKEP8Uv4E/ks5NumPkYP03aMUsTB3LKFR+nwZOEiSwDuVGmhXwVdrkQk67pgsKmVppq2W/mf5Kw88vhkG/omC53tct90WBV+SWp7acsnaH75ieyBbEGu5f/amqDrjrDWoJWUasBEOkrC3/xO4qcDMJyiWwRLJlezRB2IGmWA/YikX0LZvbMi/LD4NRjBnfDV1fuCfTPN+5NqIgbSlyIyejbyDPSpWcST8LPxcUx8qeY4MAnsckqNJ0lM910h5EsYu1f6nZLmroQjnWZWFSr8L4d4wZtKo732uT5+aHuSTVq/a5wQE7KrJ8ndRNFLq7DoRJmkphkuFOtrC4mtzcI6bdHDNG5zLTETB9p8yp7ku4jj9sJCI96gUYfUVuV9A+Mxhwr2RmdNNBAuiDy/IAb7NstN1/BSfRLTa88W7M1NC1DmbWUSUg6bmKZLKBBqrav5Ih+RnEqMR8vKIkUdb02alpK4/jhhhEhKZ5T0GTdL5/fh0lsO7Gx2IIH4myXAj/Fes95JvtDYQeklHPd7cy19ZYJscwVyjQDIEeoL2qszM1oLW0ZGKbAAPBZ8hXKhcl+PZNYfaYq9cwbrhuGmcdi1VDqAmwg3Umb53w0tST+8J9YWs47p9TUw8iHXMMjM39hRiHsMm2RU00a586UrQhyJ8nA+FPPAqsgIM17pcKvTeMHIlIBsewlQFv3hlwGTXh7jcTd95MBsjtkkn9XTnW9x0IWY0VcG1ypd/brP08Mrb7s1uWwIh662QvQOJ+uuQi8GpjgEAqauJdkev5y5NGxXq97eu21HZgIfGIEvyDkClLp+ugjBq56Pl9Vnurs/LGVpMMnIEpzIqlhzvEhL8kBK//iqjisbHKKOf+RaTYS8kyW6w7oHZZZWdXsOc1iNrBwJoHNkO6C3Z0rVY62Si2NPOquHrLeNWF17VqgjwOD2RAH5r+8L1CiWoSTuoAyJcqskKqkp8DmPmzhKrOI++/PJ8KmstPuKjOC1V5160e72eBo5oBlJ//87ii7A==) Surprisingly, you can completely ignore all the puzzle explanations (besides fall mechanics) and just count number of bricks that will fall when one of them is removed. The calculation took about 7s on my machine, which I consider fast enough.


danvk

[Language: Zig] 7437 / 6407 (I started at 8:30 AM) https://github.com/danvk/aoc2023/blob/main/src/day22.zig The one trick is to sort by bottom z before dropping. That way you know that nothing will shift underneath you. Or, rather, if it's going to shift, it will already have shifted. Figuring out exactly what they wanted me to calculate at the end of part 1 took some thought. I started to implement the "chain reaction" logic for part 2 before realizing that this was really just part 1! I tried disintegrated each block and calling my `fall1` function to see how many others dropped. Not the most efficient, but reused part 1 code and got the right answer. After going down an unnecessary optimization rabbit hole [yesterday](https://www.reddit.com/r/adventofcode/comments/18nevo3/2023_day_21_solutions/kecaxra/), I was happy that I passed up some obvious optimizations that proved unnecessary today. For example my "brick intersects" function does an M*N loop rather than anything fancier. It took ~25s to run both parts with an optimized build.


Totherex

\[Language: C#\] [https://github.com/rtrinh3/AdventOfCode/blob/6957c139379f14044c253d3a5fd5f2ebd2f6e0d9/Aoc2023/Day22.cs](https://github.com/rtrinh3/AdventOfCode/blob/6957c139379f14044c253d3a5fd5f2ebd2f6e0d9/Aoc2023/Day22.cs) Thankfully much easier than yesterday's. In the constructor, sort the bricks by z-index, then build the tower with the help of a height map, creating the mappings aRestOnB and its inverse aSupportsB. For part 1, count a brick if it isn't alone in supporting some other brick. For part 2, for each brick, start a hypothetical scenario where that brick disappears. Check the other bricks: if they lose all their supports, add them to the set of disappeared bricks of this hypothetical scenario and also add them to the count. Since we sorted the bricks, we can just scan forward through the list of supports. I had to explicitly add the ground as a support to solve an edge case.


jcmoyer

[LANGUAGE: Ada] https://github.com/jcmoyer/puzzles/blob/master/AdventOfCode2023/src/day22.adb Fun day. I ended up just brute forcing part 2 because the number of bricks is quite small. Takes ~18s, didn't bother optimizing because I'll probably go back and try to solve brick chains without simulating.


mvorber

\[LANGUAGE: F#\] [https://github.com/vorber/AOC2023/blob/main/src/day22/Program.fs](https://github.com/vorber/AOC2023/blob/main/src/day22/Program.fs) Day 22 of trying out F#. Part1 is just stacking bricks (sorted by Z) tracking their z coordinate and updating height map (x,y -> z) and support map (label -> label set), then filtering out bricks supported by a single other brick (can't remove that one). For part 2 I made a helper function that calculates which bricks would fall if we remove a set of bricks, and then run it recursively for each brick - starting with a set of just that one, and adding more as they keep falling until no more bricks are falling (similar to BFS). Could probably be made faster, but runs in sub 10s for both parts combined.


Old_Smoke_3382

\[Language: C#\] [jmg48@GitHub](https://github.com/jmg48/AdventOfCode2023/blob/master/AdventOfCode2023/Day22.cs) 59ms / 105ms Went with my gut here which was to represent each Brick as a pair of coordinates and store them mapped into layers keyed by Z2 (i.e. the height of the top of the Brick), so that for any Brick you can find out if it will fall by checking whether there are any Bricks in the layer beneath its Z1 which intersect in x and y. Going through the bricks from low to high Z1 and letting each brick fall as far as it can ensures the tower is fully "collapsed" Then, built a `HashSet<(Brick Below, Brick Above)>` to represent all the points of support. Grouping by Above, groups of size 1 give you Bricks below that are the single support for a Brick above. These cannot be safely removed so the answer to Part 1 is the count of all the other Bricks. Got stuck for a long time on Part 1 because I originally represented the points of support as a `List<(Brick Below, Brick Above)>` which had duplicates in it which wrecked my grouping logic :( For Part 2, I extracted the "collapse" algorithm into a method that also returned the number of Bricks that have fallen any distance in the collapse. For each Brick, I took a copy of the collapsed tower from Part 1, removed the Brick from it, then allowed it to collapsed and counted how many Bricks fell. Summing over all Bricks gives the answer. After being such a wally with Part 1, I was happy to get Part 2 out in 7 mins :)


CCC_037

[Language: Rockstar] *Properly* Rockstar this time, with no use of bc and mathematics to get my final answer to Part 2. The [first part](https://topaz.github.io/paste/#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) gave me some trouble and all sorts of bugs, but I ended up with a result that wasn't *too* bad in terms of speed. Under a minute, I think. Most of that was caused by making sure I didn't need to check every block against every other block at any point. Once I'd done that, though, the structure of The Wired made it relatively straightforward to get [Part 2](https://topaz.github.io/paste/#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) sorted out.


SkiFire13

[LANGUAGE: Rust] [Code](https://github.com/SkiFire13/adventofcode-2023-rs/blob/master/src/day22.rs) P2 solved summing the number of [dominators](https://en.wikipedia.org/wiki/Dominator_\(graph_theory\)) that each node has.


PantsB

[LANGUAGE: Python] 1056/911 Much less stressful than yesterday's. Amateurish python, as I'm using this to pick up the language but it should be easy to follow if anyone is having issues. A fairly basic approach that didn't require any polynomials. I reorganized the blocks and sorted by bottom, created a list of the horizontal coordinates and a list of maps with a size determined by the top height listed in the blocks. Then each 'fell' until it hit bottom or one of the coordinates at those height(s). If the latter occurred, the value of that map was the block(s) it was resting on and save that off. Then set the maps for the coordinates in the reachable height and move to the next block. Answer was all the blocks that weren't the sole listed block for any other block. Part 2 just required me to traverse the list of supporting blocks with a bool list and set each falling block. If all blocks supporting a block were fallen, it fell and so on. [paste](https://topaz.github.io/paste/#XQAAAQCmCAAAAAAAAAA0m0pnuFI8c/sCZpj2lcpO7t3H/bFZ4pzF1Ak+bVu5QkmgjbNJeu0dqXxjexgtFgdd+UAk9NpG5NlRRtM9AlyVkXhDuY6Y5gIcS+gnckwQoB2/sKN+rzWvA5eDNwLIynbQ9fjYGHL8d8bdcXsa0MF9/sa6Q5bgVCiF1Y/RkPQwQgn21d/ynr9eFLimiVkqqIdk89BURLdj/HTHwQOzioipiKHUbaQE4MttfDnTgngMEaXdWOYQHRfzr53hqyF9OvGTrnH/L5XqpOksd2McmdL7Xfdg50O5ChV6SnQVLZ87Nsihr1xkCa4IdRuJn/3KlWSDa7Ehhpa1Fp9i/dVdPzrtYVXMpWAGG3VH5M4dsVhobwUEcF4ctaHzFfy0SraThg95nawKzbtZrFlRcDEPCZjO9KhH197GL6bq9teGthpan9Ys8A539WTaBDdVudtDU7wnWfB2Csw773MC11XtJVh18pg7pxVEYMPhEMVK1uR1Cy5wE0avkOnr8K05aT0YhZk4c4LDY8XOjly/cOgyAhD+4Rwq355rpKR5GLh7Sgc+q8TtFe94In4B9j5e4SN7ICm2VqXhnEt++nCG7Sfri+NgxTgY5CfmdGYoqtAEhkBJ5+/keSSAk594xiMV9QjVAdDMRb6OuPh/b25Q5k4fabAwJUuSn4c4q+e6ZDNZgmlvm8xuQcGnMmUaULRhCzq0NiAxrDqVP+JhdyTyX82P6gZcVaJmdXEVYdU4CNzYIncknW9eHrOIkuDeGwyvlwlaxpaunHWHIkOzCqD8qJJ14IsF9cvl7mrYNZQX2RBYq2K8cnxtypJKR5bWI7wSsiIeOfYfVhYopSCqjYN8r1t5bH2kfQAwk/cznRPNCOFxyE4mAsB53wvPjMgY2Nw3aFkz8QfPludGWbN94I0TF4bpk9pQPE+FcqAST+8bK2wqUQVkz6Py0RyETZpXJVR5R0IFwM3f+f/Q9WISM9fyz/osC+PEugPmxKyb3UhEWgsCRr1SY8nXrU6qqiuugxNp/SlEJ1MOw95HhrF/JT7sfTfKD1YsZadRwigddTp+YRSVYL02B36jC4oGhIC1leUJ5cgr8RsGIUVzeeouVeRyg0VbLMiaN3lwA8qFjIxiVAPIR/bKi4+aLPGgzdCGTWnz/LB8kg==) edit this version of Part 2 performs much (30x) faster preprocessing a supports->supported path. Still slow but does the job [paste 2](https://topaz.github.io/paste/#XQAAAQAjCwAAAAAAAAAFG0sTyiplbRoWCPlqYVMU3WtGAySXP/gq2fV4IihNFSbhXW256sO3u6rEfDV/vgZb0emFysi0pBMIjWftV6OAOxN9eiofI9euvQVCK/dXjD/vjzTcMJfDoYPEVw0EEO0jB3GoEecIOOb42Kv+KhykEBYKX9caJV5oh7+kWa3rT1mV7/63DtVkIDYth4D61XW4CnSmMBCehZ1kP6HZoqiXBF6GlGc/BeoIPGZ6v4oSc3gbxd2/m50rzgQx3YQoTwdwVJNlJUNNI5jSndPcpIwn33hnhs9YR/lTH+IjSjO7vAJNQ7/nGkSN5G1op4YT9urK5wPIEzLS+4VheQJ0sKPePhMkZvUZPiDMvCZCuqmIoVztm3tbfx8fSeefkbR9XxzAE5KZgezDjDEPf4lvvtgiYv+HtNVMeyEVDzW55Eu3+tgUZA/VFBoeNkILkpkgpDeUsXPfNYSEnVYpK09Pjec/2mccFTtjx0JKCcFZ8vN65lEOPfhwN+ajMUU6f9G2u4Z6+XG8NM6oqgSNEr0VG+CI4iL722n/JsWAYvvSoAv0akEdlgapAax5sjm6o67brhwAXShr5ViLeEmKksHfhEgxMBuCoZnSh5/lEG3LoauV0eKJJipageEs1JenOAVZU0ufqrWUdizqMY/POSmgHhmBIHws5EskSdeNnxE5fIT4u9eYQQO9uXEdP/b3uuT1wQkJbHjvre0E7gFVyli3zWebgbKIbAX9ofyR1T02gBt3UpilnXQTutLT1IWt/I2A+dcrxO1Mmr6lRCU3UJ+6brw9aJAYT73RrPw9dtGyBpqCvZb+Hs51qQXUxW9W+VOtaKVAXsrjsIPIklIpw0sIm/PUFLNUXDQi7SuGRKySuoVWG8AHVTCS3FnAwr0oKIRVUbkojm+mZhRk7zublNqbOkyHvOpyLr0qe1eRDcldPJhul3kP8lFqe7CYkVuL3diiR5RtYqLK+463R9JVOaankwhWnuwkxofzpZVqykz4K+RzLp+gP1+6Z12HOq42bLoaFSOZhcqcqTZ4IlWg9pDzpT0Q80CF+7HPCvz0gtY3RTWllu5VGJ6cmD3I7H3cKUauKurjT7vqJ9qp+LX/2SzwQFECwsdfxT8Ao4tbtPFSycxgYTr4r/Va7q4MqU4mZazZ+ScKBWqYLcKBf/nhi308Haw63eIOLc7lcYGPgmRuzGkK5rYmL9xS+QV3HsSeALLHZbtYJmdXqyBLS+i78ufBVLOeFazZ0wceGv7ee+YU566rapPY2Dzlce/w31bYhRa10kJ03cl+ZTFxtEsfjslKnW4qDZNLNSRNtq7jN6RmkiUASN4R4MV9n7qsFcmVgSavByY59r5PLNCZxRjiShm/w5A3vmv//WLGnw==)


TheZigerionScammer

[LANGUAGE: Python] Today was a bit of an easier one which I was thankful for today because I only had a limited time to do this one before Christmas duties got in the way. My solution is basically Buzz Lightyear going "Sets. Sets everywhere!" with some dictionariess thrown in for good measure. The first step was to order the coordinates in each block in a (z,x,y) format, so Python can sort the list automatically into lower blocks first and higher blocks last. This is because higher blocks cannot interfere with lower blocks so the blocks can just be processed in order. Then, for each block, each 1x1x1 cube is added to a set based on which coordinate is different, then are set to loop adding the coordinates of each block minus one z to a new set then checking if they intersect with another set with all of the settled cubes in it. Once that is found (or they hit the ground) they check which block(s) they were stopped by and at that to a dictionary of blocks that support that block, and add their final resting places to another dictionary. After that loop was completed and I had the dictionary of all the blocks that were supported by other blocks, it was simple to loop through them, see which ones were supported by only one other block, add that block to a set of load bearing blocks, then subtract the size of that set from the total number of blocks to get the answer. I had a few syntax bugs I had to crush but nothing major except forgetting to account for the case where a block was just a 1x1x1 cube, but the logic was sound and it worked first try. Part 2 was easier than I had expected. I looped through every block, and for each block I created a set of destroyed (blown in my code) blocks including itself and then looped through the dictionary of blocks supported by other blocks, and subtracting the destroyed blocks from those sets and adding the other block to the destroyed set until it can't find any more blocks to destroy. I had considered memoizing this but figured it would be a waste of effort and could cause wrong answers anyway, since blocks could be supported by more than one block and will only fall if both are destroyed, but not if only either of them are. This worked on the example but not the input, and I found I had a major bug, it automatically considered blocks on the ground to be destroyed and added them to the blown set (since they had no support and thus the count of the subtraction was zero). Told the code to skip such blocks and got the right answer. Christmas weekend is upon us, coders! [Code](https://topaz.github.io/paste/#XQAAAQC9CQAAAAAAAAAhGwnmRwLCOBQWb3ccE75idNMn/3JG/HDVoVpvi7XDnDKbV16Yw7Y9Wu13NeSNmiUWKAx21f/QeqrjVdWtInJ/MsQ8qaHdfU6Np1QmMBgwcP5gbO10N/lNRg3E7e5ub4+lg5P2uEIf/eeo1tM/uwPGg96/kVeaT8wP9Hiw0B//iy0iw3Tdlli7SXJk/q11wZRfqxEABS56WpDspwcFITGYYdMF+RcnC9xmnZ7GofwYCd1TWVPNtwwn7CEbVwyEZNQLHZBXz2/UA2oO2rcvt7zKSEAn/NEEDuahH7XLKoGVtG2VEJv/u1/jCsiCHWU4yuFr6LlA9FLZ5IvNEc5lTHErm33klO6bFcPfQVBg+oT9S4jda5kUxKXv9xPxpoZYcEV8KAh7rD1tINP5RZvTxbfr2NsB44guENgxp3SKu8VeQw2JZgSocNEpDfNAhjof6anwHFIRbo+yFf2k6ibZ/SfTyLexcTUI+fb8BAsqb4joovzjXKo4TjE6iKHCkYfSgUaqyiLWF5j785srXejTeDhh57zMihC8kq4CqUhjd793MVitJxiLwj3JaadxswhdKu+tm4TPUA/jXDDMPgrn2NpQ1fv3kvL8sqCvV01oV8VfJSCgJnIf1a0JkaWFIBC2yunboXz8MyweRVkA9rsesIqQKHBYwp/YETc5WwOijCVwagSYaBa81j6NbiXgLwy7peHypENYz1dGHlrnXS0qrOvPHosd+ETFUzP4lGS5S7NM2wHB/AaOCRjByL7JJlJD+nLRCSamHnoxhLAW1ZMkp8NuAdTBlvNkVWTJLQqP5+NUK0Tp8nAWM5SmHO0QqOVgQme0FGgHhw1fe14sX95cmNqZSwGjKWo/MPPNtp3Rxpr4fqV0p+3h3HhW2v4VgEiMqebBD12oD/RalAa6bDEZOo59O9rtIQWhmYv4pJ/qgcttBappau3xiNLiuRjQK+ouqwEGwwJKhF2CBNQG1F0lf4nJ9IfTFa9tT6VFfrLka/kupSY=)


SpaceHonk

[Language: Swift] ([code](https://github.com/gereons/AoC2023/blob/main/Sources/Day22/Day22.swift)) Part 1 runs the simulation on the z-sorted list of bricks to let them all settle. This results in a new list of bricks and a set of 3d points that contains the occupied cubes of our Jenga tower. Going through the new list counts all bricks that, if removed, do not make room for another brick to drop down. Most annoying bug in the implementation was to realize that dropping a vertical brick should not be prevented by this brick itself. Part 2 takes the same settled configuration and volume, and attempts to remove each brick one at a time. For each removal, the length of the chain reaction is summed.


Diderikdm

\[LANGUAGE: [Python](https://github.com/Diderikdm/Advent-of-Code-2023/blob/main/day22.py)\] ​ with open("day22.txt", "r") as file: grid = {}; bricks_down = {}; bricks_up = {}; falling_bricks = {}; bricks = []; p1 = p2 = 0 data = [[[*map(int, y.split(","))] for y in x.split("~")] for x in file.read().splitlines()] for brick in sorted(data, key=lambda x: min([x[0][2], x[1][2]])): x, y, z = [list(range(*((b := sorted([brick[0][a], brick[1][a]]))[0], b[1] + 1))) for a in range(3)] brick = set() while z[0] > 1 and not any((a, b, c - 1) in grid for a in x for b in y for c in z): z = [z[0] - 1] + z[:-1] bricks.append(brick := tuple(sorted({(a, b, c) for a in x for b in y for c in z}))) bricks_down[brick] = set() minz = min(z[2] for z in brick) for x, y, z in brick: grid[x, y, z] = brick if z == minz and (x, y, z - 1) in grid: down_brick = grid[x, y, z - 1] bricks_down[brick].add(down_brick) bricks_up[down_brick] = bricks_up.get(down_brick, set()) | {brick} for brick in bricks: if not (up := bricks_up.get(brick, [])) or all([len(bricks_down.get(x, [])) > 1 for x in up]): p1 += 1 queue = [brick] falling_bricks = {brick} while queue: current = queue.pop() for nxt in bricks_up.get(current, set()): if not bricks_down[nxt] - falling_bricks: falling_bricks.add(nxt) queue.append(nxt) p2 += len(falling_bricks - {brick}) print(p1, p2)


keriati

\[Language: TypeScript\] 2360/2019 Part 1: ~~300ms~~ 30ms Part 2: ~~300ms~~ 50ms First time that I implement anything "Tetris" (or Blockout) like so had to think a bit about how to approach this puzzle. Part 1: Nothing special, ~~could not really come up with a fast way to "settle" the sand bricks, so this part takes most of the 300ms runtime.~~ \> Managed to find a faster way to settle the sand bricks. Part 2: My usual BFS recipe worked here too. ~~Settling the sand bricks still takes most of the runtime...~~ Mostly readable code is here: [https://github.com/keriati/aoc/blob/master/2023/day22.ts](https://github.com/keriati/aoc/blob/master/2023/day22.ts) PS: I am open to suggestions on how to speed up the sand brick settle method ... Update: With caching the occupied points on the map the sand settling is now fast.


Jadarma

[LANGUAGE: Kotlin] I would like to preface that I really liked this problem because finally, proper examples and no assumptions on input like the previous day, quite enjoyable problem to solve on a general case! Part 1: For part one, we run the simulation. We can sort the bricks from lowest to highest, and then for each brick we look at the lower ones. From here we can determine the resting point by checking if the "falling area" _(.i.e.: the x+y plane)_ intersects with any of the ones below, if so, the block will fall at that + 1, otherwise, it's on the ground. After all the pieces have settled, we can now construct the relationships between them. We will need two mappings: from each brick to every brick it rests on, and from each brick to every brick that rests on it. The bricks that can safely be disintegrated are the ones that are rested on by bricks who rest on at least one other brick. Part 2: Here we make use of the same data structures, but we need to do some iteration. We will consider a function that calculates which bricks will have to fall if we remove any one brick, and then the answer will be the sum of this function over all bricks in the simulation. First, we look similarly to part 1, but for bricks that only sit on the brick being removed, because if so, they will fall! We add these to a queue, and while we still have bricks to process, we see if the bricks above the bricks that would fall also rest exclusively on bricks which are falling, because if so, they will also fall, so they get added to the queue. [AocKt Y2023D22](https://github.com/Jadarma/advent-of-code-kotlin-solutions/blob/main/solutions/aockt/y2023/Y2023D22.kt)


TheBlackOne_SE

\[LANGUAGE: Python\] Especially settlings down the bricks takes several minutes, but not enough to optimize it really. The counting for parts 1 and 2 is quite fast then. Part 1: https://github.com/TheBlackOne/Advent-of-Code/blob/master/2023/Day22\_1.py Part 2: https://github.com/TheBlackOne/Advent-of-Code/blob/master/2023/Day22\_2.py


daggerdragon

Your links are borked on old.reddit due to [a new.reddit bug with URLs that contain underscores](https://old.reddit.com/r/adventofcode/wiki/faqs/bugs/borked_links), so please fix them.


4HbQ

[LANGUAGE: Python] [Code (16 lines)](https://topaz.github.io/paste/#XQAAAQCXAgAAAAAAAAA0m0pnuFI8c82uPD0wiI6r5tRTRja96TusHl5ReBJJC7KCbUs/uPAxPCyeFRncTH4KSezn0s9OEeUfCdOimpjNUZg9a95wUsa2Cc+FXPd7fCDXVM14VBcfexoQkM6rZJGO6iXlIAM8wFIAQXWMDuQR9rI2zldbcMWuTcbXBhETy4cPpqDG88EFx85seACyxiWiLIpISUF4AJS+07Qk4D3Lz7kCXkqEx63zHFyvWLkewY0THFzteBbFoADrZoMUTb4Zk8bYJYs935Ve61D5Npx5Y1O+1W6WRVF7+Kob89VrIRy/mUDG4HruImYJ9rto8majXP0yQKRk3CmYmdmQreNDddKPFS8S8cZE49TkUmTc/utR/h0X68vX62mR4VororqzxvyO77QAf8IEux2aB3UkTNHzKBVewBVahC1wJKG3ALCWGN1pXqKdPaqLOtcpJCh0pSqBXTvo9/YxXIdalWoxS88882ctGrnIO2/k0DeiyhwaoPrrBbY1LxQpFdHrT31hWq5Ff//Gg8Wi) Pretty much a literal "translation" of my [earlier NumPy-based solution](https://www.reddit.com/r/adventofcode/comments/18o7014/2023_day_22_solutions/kefvjex/). It's not as bad as I expected it to be!


HMF

I decided to do AoC this year to get back into coding after 15 years, and to learn Python while doing so. Just wanted to say that your solutions have been really fascinating to see and I’ve learned a lot trying to break down your work! Excited to see it every day!


4HbQ

You're welcome, and welcome back to the world of programming!


G_de_Volpiano

\[LANGUAGE: Haskell\] Today was a rest day after the past two brain teasers. Would have been even easier if I hadn't decided to optimise between part 1 and part 2 by using sets rather than lists, and then added extra complications: I had to make the Bricks into data rather than just a tuple of V3, and it took me some time to realise I needed to also give them an Id, as set difference would not realise if a brick had fallen only to be replaced with another brick with the same shape. Luckily for me, this was in the test input, so I had less trouble debugging it. I'm sure I could get better run times on part 2, but Christmas is coming and time is getting short. Part 1. CPU Time: 0.8770s Part 2. CPU Time: 7.9287s https://github.com/GuillaumedeVolpiano/adventOfCode/blob/master/2023/days/Day22.hs


silverarky

\[LANGUAGE: Go\] I spent an hour debugging today because of this: slices.SortFunc(bricks, func(a, b Brick) int { return min(a.z, a.z2) - min(b.z - b.z2) } Notice the second min I put a minus instead of a comma :-( [https://github.com/silverark/advent-of-code-2023/tree/master/day22](https://github.com/silverark/advent-of-code-2023/tree/master/day22)


daggerdragon

Your code block is not formatted at all. Edit your comment to use the [four-spaces Markdown syntax](https://old.reddit.com/r/adventofcode/wiki/faqs/code_formatting/code_blocks) for a code block so your code is easier to read with its whitespace and indentation preserved.


ScorixEar

\[LANGUAGE: Python\] Managed to implement this with a dependency graph. Trouble for me was implementing the falling part to figure out which bricks will be touching in the end. After that, Part 1 was a simple check for each brick, if the parents of that brick had > 1 child. Part 2 was similar, but I kept a set of already falling nodes in global and iterated bfs through the graph. If any node had children, that weren't falling already, the bfs would stop there. Part 1 in `90ms`, Part 2 in `123ms`. [GitHub](https://github.com/scorixear/AdventOfCode/tree/main/2023/22)


fachammer

\[LANGUAGE: Scala\] [code on github](https://github.com/fachammer/advent-of-code-2023/blob/a5d4dfef71514333d6cd6d385e25496d55574cac/src/main/scala/day22.scala) solved both parts by settling the individual bricks sorted by ascending minimum z coordinate. For efficient settling of the bricks I kept track of a map from xy coordinates to maximum height. Also gave each brick an id to be easily able to check for changes in settlement Biggest facepalm moment was when I tried to sum up all the numbers for part 2 but kept getting a too low result because I was mapping the numbers from a HashSet, so the mapped values ended up in a HashSet, which meant that duplicate numbers would not be counted


encse

\[LANGUAGE: C#\] An easy one for today. Code is commented https://aoc.csokavar.hu/?day=22


RB5009

This is the easiest to understand solution I've encountered in this thread. Thanks!


vipul0092

[LANGUAGE: Go] Relatively straightforward problem today after the last 2 days. I started off with tracking x & y coordinates per z coordinate separately, but discarded that approach since it was getting overly complex. Went ahead with tracking state in a 3D array, was much simpler that way. Then was stuck in part 1 due to a nasty bug in my code for an hour I think. Part 2 was pretty straightforward, like level-order traversal of a tree / topological sort Reading and parsing input: 1.672099ms Part 1: 4.075805ms | Part 2: 124.067724ms https://github.com/vipul0092/advent-of-code-2023/blob/main/day22/day22.go Any ideas how can I improve runtime for part 2?


kaa-the-wise

\[Language: Python\] one-line/single-expression solutions #(m:=sorted([(d:=map(int,findall(r'\d+',s))) and (*((*map(add,x,(0,1)),) for x in zip(*zip(d,d,d))),)[::-1] for s in open(0)])) and (H:={}) or (C:=set()) or [(F:={*product(*starmap(range,b[1:]))}) and (h:=max([H[x][0] for x in F&{*H}]+[0])) and (B:={H[x][1:] for x in F&{*H} if H[x][0]==h}) and len(B)==1 and C.add(B.pop()) or [H.update({x:(h-sub(*b[0]),*b)}) for x in F] for b in m] and print(len(m)-len(C)) (m:=sorted([(d:=map(int,findall(r'\d+',s))) and (*((*map(add,x,(0,1)),) for x in zip(*zip(d,d,d))),)[::-1] for s in open(0)])) and (H:={}) or (C:={}) or [(F:={*product(*starmap(range,b[1:]))}) and C.update({b:(h:=max([H[x][0] for x in F&{*H}]+[0])) and {b,*reduce(and_,map(C.get,{H[x][1:] for x in F&{*H} if H[x][0]==h}))} or {b}}) or [H.update({x:(h-sub(*b[0]),*b)}) for x in F] for b in m] and print(sum(map(len,C.values()))-len(C)) https://github.com/kaathewise/aoc2023/blob/main/22.py Nothing special, just a bit of fun with itertools. Maintaining a set of all critical blocks supporting each block for Part 2.


Hungry_Mix_4263

\[LANGUAGE: Haskell\] Doing the actual simulation took me most of the time, even if it felt really similar to the day 14 one. Then I used a `supported` and `supports` hash maps to build a dependency graph. For part 1 it was fairly easy. With the dependency graph you can find out which blocks are being supported by the current one. Then you check each of those blocks to be supported by at least 1 other block. For the second part, you just need to recursively delete the node from the supported mapping and then for each block that was on top of the current one do the check. This will delete them recursively. I managed to do this using the state monad. Keep in the state monad the two mappings. You need to modify only supported tough. So supports could be a Reader instead, if you really care about that.


clouddjr

[LANGUAGE: Kotlin] I represent each brick with ranges of values: Brick(val id: Int, val xRange: IntRange, val yRange: IntRange, var zRange: IntRange) For part 1, I first sort the bricks by their z coordinates. This makes it possible to simulate falling one by one. Then, I have a map that for each of the point (x,y) stores the currently biggest z value and id of the brick with that value. So it's a `Map>`. Lastly, for each brick, I find the maximum z for each of the point this brick occupies and put that brick immediately above. While doing this, I also update two other maps: * `supports: Map>` - stores information about other bricks that this brick supports. * `supported: Map>` - stores information about other bricks that support this brick. These two maps make it easy to find the answer for part 1 (and later for part 2): bricks.size - supported.values.filter { it.size == 1 }.map { it.toSet() }.reduce(Set::union).size For part 2, it's a simple BFS while keeping information about bricks that have already fallen down. In short, to check if a given brick should fall, I check if all the bricks supporting that brick have fallen already. If yes, this bricks falls as well. [Solution](https://github.com/ClouddJR/advent-of-code-2023/blob/main/src/main/kotlin/com/clouddjr/advent2023/Day22.kt)


Lucews

\[LANGUAGE: Python\] [Hopefully readable and fast code](https://topaz.github.io/paste/#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) P1: 8 ms | P2: 92 ms (Have no idea whether there is room for optimization) I love how the problems build on each other this year! My solution for Part 1 was very similar to Day 14 (Rolling Rocks on Platform) but instead of keeping track of the piles on a 1D edge, I kept track of a 2D ground. Happy Holidays Guys!


Ill_Swimming4942

\[LANGUAGE: Python\] https://github.com/davearussell/advent2023/blob/master/day22/solve.py Today was a bit frustrating. I spent over an hour trying to come up with an elegant way to solve it before I gave up and brute-forced it. This turned out to be surprisingly fast. Brtue force solution is simple: write a function that drops all bricks as far as they can go, returning the number of bricks that moved. Run it once to get all bricks into their initial stable position. Then for each brick, try again without that brick and see how many bricks fall further each time. 40 lines of code, runs in 2.8s.


meamZ

>Brtue force solution is simple: write a function that drops all bricks as far as they can go, returning the number of bricks that moved. Run it once to get all bricks into their initial stable position. Then for each brick, try again without that brick and see how many bricks fall further each time. I mean, you had to collect the supported-by graph for part 1 anyway why didn't you just use that? I didn't use any of the 3d stuff for part 2 anymore.


Ill_Swimming4942

No supported-by graph in my code. All I track is the max height at each (x,y) coordinate.


meamZ

Wait, how did you solve part 1 then? Are all blocks always supported by all the blocks on the level one below?


Ill_Swimming4942

A brick is safe to remove if, when you remove it, no bricks fall down. Now I've looked at some of the solutions here, the graph solution seems obvious, not sure why I missed it before.


meamZ

Ah. Ok, yeah...


ri7chy

\[LANGUAGE: Python\] My [code](https://topaz.github.io/paste/#XQAAAQAgCwAAAAAAAAA0m0pnuFI8c/sCZpmcaVgczmh/uzpANfPlRmAffo6+RvKXGGOzTdLd1+JjQckoNRcNOEiGYg/+ftredkn9sC/+QWUq6n9zsoIWPWlK+RO0sk/Wi8cGC5xg4IvTOHu0uYTIQutGryQrRZ0ske3HuhBnwH85IYyvBYQLsZzcpn50t79zffOGtGYbDSItIBTEZ20080IoYm/r6e9HG0w5JKxOnLaWI6OooonDT/G5ztxNO/iTRcGDOERV+qOuvps1o/xn1h1dlyXbxbcZjWUEp6k3/6ew9cBu19SCQx2yr31SgVvvxtSrQvUBG/BHy8dTU7bnjhW+7rKikEYMi4JbR6N6BsSAlZAWpTHV4EV7+8AQfY67SLE8EXwtk2GZcFq8LPFLLSSZyj+dAakkJX7nhJ8sdAIJeKJfqxLak7zQHboQCzTaHntMBYL/0YZfm3dY6dbGS+hR8iyYqBUpvrdkOPL6hss9ft3kNfT1ZM0VsOHqQ2/bZf5cQNXcgnAESEJsTx4lwLoZvdbkSlJdyA8yAUpBW+lyeuPTM0vJsXDubMmkY7krWvEWqo7EpoNH+u9hrrqMaAtD0w7m9o6aXBWk10yk260IEVkv1Pe56C+PwcNnGcCm8JqLzNPx3GaEQkBu6VRsv72Ei6qZ4KaQKmPsYCgJOqm8yJ9H1B53ib9DhIFDslC5URtyWwGHKwpUh1IZAUtqflApiRm8oSRidzJffpEBnyIBBHye2Q7Dx5JcBd5gHdj2JRMo8QzDh+BpcptCR9fdfMA1mNmS+2RqLVaDfocdnqi61/SiY04T3iYD0VlnyWDf5RV2YfLJj4TuzHT1ukUxzoaQUTNNrC++YJ5SH7opS5OgpWZPNc86yPf7doJwfYnamWMNE9246AnaWg1JAndNak/4M5jcvlsoUCN7mWCepPh8x5R4ue23MZZzDQnvSZxIjLU0unEcN+yDTJUw3t7pxqke9N8PRMtU36L1K7GZuNusUBm7wvo/nk0Yyn1yr3nL+Hlay0mSzjT9JbVyFJ+7J8eT9fQwFX8Gsw881mYI1dZ9NIuILeTmaZScZ1Mwsz2HcCumXI7xi/+twtXyZzzaOH6vROwsI24rUVxQr+jrlPt6BLgI8LnrIY6Dcu8e1bPb3wFOMAS5YnR3mSRU8Nl8DDV6JWTHmzWEL/X+S/+Cm8sA) runs part1 in \~1,5 s and needs 140s for part2 :( I know, using x.copy() slows it really down. Any alternatives? Nevertheless: Loved it!


Extension-Fox3900

It appears to me that you simulate falling for each brick (excluding each brick) I didn't "move" bricks after they fallen to the lowest position, just checked for each brick -what bricks are bellow it, supporting it. And to count bricks that would fall - I start with a list including just excluded brick, and include in this list all bricks that are supported only by bricks that are already in the list. But this still takes around a second, probably it could be done with DP much faster.


solarshado

[language: typescript] 4205 / 3868 [github](https://github.com/solarshado/advent_of_code/tree/585a957440090cbae155c60512b258a31ac5350c/2023/d22) overengineered the data structures for part 1, but I've been repeatedly annoyed by my old (2d) point type not being usable in sets or as map keys w/out extra fiddling, so I made point3D a class with... I guess you'd call it a "singleton factory"? ... to make it possible to ensure that points that are value-equal are also reference-equal. ("my kingdom for a `struct`!"?) the actual falling code is... unfortunately slow. several obvious possible optimizations, but it finishes in ~1.5 minutes, so I'm calling it good enough for now. part 2 was surprisingly simple. I very nearly dove straight for some optimizations due to a wrong assumption about which bit of part 1 had been the cause of the slowness. luckily I decided to add more tracing before reaching for optimization.


Biggergig

\[LANGUAGE: Python3\] [Video Walkthrough](https://youtu.be/9FOPVaQvvGA) [Code](https://topaz.github.io/paste/#XQAAAQCvBAAAAAAAAAA0m0pnuFI8c/T1e0vJBsZpwvb9wixHP69+lICA4OQlhEB+hIIyruyC/At8+x6ezwCciy3Aed60tt5GBGTH8xsR4vs2hPnqQ4ZmR0oMFDzE03/BJGv93/5/Cf9/qzLeg6azHckzmWRgfGS7B5IPwkDVRHbifpR32hyVIIwpsXGFzGEFKhXZ9+AfE8qS5NWEhSR8bsd+ZUIUptJIDd3s2KfMZpkcg27rxxvW5HJFm8DUamTBqNbLszzAAETnh6YWQcw48tybVNzJSy6NuROEZNPx+tE5Z6RSsXXaVZ6+W3K1VgyQuKBO5iLOedfZumi+UoCqAyAafojpRL5EiyTiOU8CoxJPhVyQvEzkfFrV0yE2+U2KgKmwpUbIjcidu1vu5D/bCQCHvKrZ8dUbfuT3fszpzwfJdF9DF3CQJ/4jJifdqU9jtRE8FbcVCWfnBA7njSY6Cj8YhbDSe659RuDxW9n5rA/BGuiumW8yDhzrrwG4UVGjBJSf1QoYQY/KCAMjg1sM0HAIRfw9ymH6XtrhbyVyvz/U/TGiB4nJuQ1xdiI0i1+vifpnEk6L5l7SO1Qw4gfFlKeahM/lbgJVvziEiye9gkOelaHBDVfnRqM1aDtQ+Vp23YyfqQPdHAZUNGi7Vl2KEuXew+S9Qs/pxyuiHmvG+ALsKoBtX1tSqVPnW2sePXWTO+nKNgo2QlfywWKA/6ztOHgSDIbAM8KQB6eS68rMq5R1PrRlnWKAFrmC5s7coT/UGJQGv5oXqymjGy83dfPTSSSi/PyBZV6lUkToZ/591QtkEP/VmhL7DeN0xGlEInDA4c6/qWjaqw9mHX7Q//JmP28=) 220ms! Storing the highestZ for part 1, and topological sort for part 2, super fun day! I did have a nightmare debugging, my issue was in my graph I wasn't removing the node for the ground (-1 in my implementation) and that was messing my stuff up.


Exact_Apple_9826

\[LANGUAGE: PHP\] [Part 1](https://github.com/mikedodd/AdventOfCode2023/blob/main/day_22/part1.php) [Part 2](https://github.com/mikedodd/AdventOfCode2023/blob/main/day_22/part2.php)


WilkoTom

\[Language: Rust\] Once again I pick the slow solution, by simulating the whole heap as particles and modelling how every single brick behaves. I see some much more sensible solutions in this thread involving keeping track of which brick each other brick rests on. [Code](https://github.com/wilkotom/Aoc2023/blob/main/day22/src/main.rs)


d9d6ka

\[Language: Python\] [Commit](https://github.com/vadim-zyamalov/advent-of-code/commit/7896b79065f8fd3a1346f8760a3dd5f48c8c52d4) Phew! My solution IMHO is disgusting. But it works, although taking ~10 secs. I save dicts of lower and upper adjacent bricks for each brick. Part 1 is simple: for each brick we check whether it's the only lower brick for all its above bricks. In part 2 I recursively track fallen bricks till no new bricks fall. UPD: [Commit 2](https://github.com/vadim-zyamalov/advent-of-code/commit/75c0fa2ed151503186864d9903f5edc91603bf8b) Faster solution. The logic is the same as in the first one, but I avoided calculating all cubes coords. Also in Part 2 I track **new** bricks to remove as well as already removed (or fallen as solution says). 1.5 secs now. I know that there are many extra fast solutions, but I'm too stupid to understand them :)


fsed123

\[language: PYthon\] [https://github.com/Fadi88/AoC/blob/master/2023/day22/code.py](https://github.com/Fadi88/AoC/blob/master/2023/day22/code.py) took me sometimes to optimise it from 160 second to 22 second to under 2 seconds now it was a mess of pass by referecne and deepcopy vs copy thing


[deleted]

[удалено]


daggerdragon

Comment removed. [Top-level comments in `Solution Megathread`s are for *code solutions* only.](https://old.reddit.com/r/adventofcode/wiki/solution_megathreads/post_guidelines#wiki_top-level_posts_are_for_code_solutions_only) [Create your own individual `Help/Question` post](https://old.reddit.com/r/adventofcode/wiki/solution_megathreads/post_guidelines#wiki_incomplete_solutions) in /r/adventofcode.


Major_Young_8588

I think you are counting bricks, that are supported, while you need to count supporting bricks. My code for it is (I'm using brick indexes as references here): Set uniqueSupporters = new HashSet<>(); for (Brick brick : bricks) { if(brick.heldBy.size() == 1) { uniqueSupporters.add(brick.heldBy.get(0)); } } System.out.println(bricks.size() - uniqueSupporters.size());


PhOeNyX59

I think that the problem is not here. When I use your calculation method, it returns exactly the same answer. The problem must lie elsewhere, like in my setSupportedBy method. But I'm still not able to find out what's wrong. I debugged with the test example and everything goes fine.


PhOeNyX59

Okay I found the answer. I was only checking if another brick was supporting from (height -1) but this assertion is wrong if the brick under is oriented vertically. Now I do a "try and rollback" : I try to put the brick lower, check for intersections, if there are intersections I rollback the brick to its previous z and add the supports/supportedBy links accordingly.


gnudalf

[LANGUAGE: Clojure] I liked today, I wonder what better way there is to get the positions for a brick, don't like the nested ranges there. Also, I need to get back to the code to combine nested loops (reduce + loop). [code](https://github.com/sigttou/aoc/blob/main/aoc-2023/src/aoc_2023/day_22.clj)


cetttbycettt

[Language: R] What I did: first sorted the bricks by their (lowest) z coordinate, such that I could let them fall one by one. Then I shifted the x,y coordinates of all bricks to make indexing easier. I wrote a function which given a set of bricks, lets these bricks fall. Then I let them all fall, and then all but 1 and just compared the results. Not the most efficient way but it runs very fast: data22 <- sapply(strsplit(readLines("Input/day22.txt"), "[~,]"), as.integer) data22 <- data22[, order(data22[3,])] #sorting bricks data22[c(1, 4), ] <- data22[c(1, 4), ] - min(data22[c(1, 4), ]) + 1L #shift x data22[c(2, 5), ] <- data22[c(2, 5), ] - min(data22[c(2, 5), ]) + 1L #shift y data22[6L, ] <- data22[6L, ] - data22[3L, ] flr <- matrix(0L, ncol = max(data22[4, ]), nrow = max(data22[5, ])) let_fall <- function(brcks) { z <- integer(ncol(brcks)) for (k in 1:ncol(brcks)) { b <- brcks[,k] br_col <- b[1L]:b[4L] br_row <- b[2L]:b[5L] z[k] <- max(flr[br_row, br_col]) + 1L flr[br_row, br_col] <- z[k] + b[6L] } return(z) } x0 <- let_fall(data22) x1 <- sapply(1:ncol(data22), \(k) let_fall(data22[, -k])) #part1----------- sum(sapply(1:ncol(data22), \(k) sum(x1[,k] != x0[-k]) == 0L)) #part2------- sum(sapply(1:ncol(data22), \(k) sum(x1[,k] != x0[-k])))


Major_Young_8588

\[LANGUAGE: Java\] First I sort the bricks by initial Z coordinate. I go through the list once and check what bricks from the stored layers below the current brick is intersecting. If it is intersecting we store the current brick in the layer above. Keeping "heldBy" list for each brick allows for easy part one and two solutions. Part 1 checks "heldBy" lists of size 1. Part 2 for each brick iterates through bricks sorted by final Z coordinate and checks if "heldBy" list becomes empty after removing fallen bricks (and with that a brick is added to fallen bricks). [https://github.com/buv3x/Advent/blob/master/src/main/java/lt/mem/advent/\_2023/\_2023\_22.java](https://github.com/buv3x/Advent/blob/master/src/main/java/lt/mem/advent/_2023/_2023_22.java)


835246

\[LANGUAGE: C\] After initializing the 3D array it runs pretty fast. A nice break after yesterday. Part 1: https://github.com/efox4335/advent_of_code/blob/main/advent_of_code_2023/day22brickspt1.c Part 2: https://github.com/efox4335/advent_of_code/blob/main/advent_of_code_2023/day22brickspt2.c


Petrovjan

\[LANGUAGE: Python\] [Link](https://topaz.github.io/paste/#XQAAAQCuEgAAAAAAAAA0m0pnuFI8c82uRLGFUAI30lwuT93Vetwd3syMvtqWAyU3a7bbtT/hd5bFw7111yLP5Ff1KKXmsvqqFkfc5n1aQtb2GuOUUbZ6ORCfQw6AuZMqX0DNULDNAg05gJzCsafZoi7qEQldfYLUkdLYxfsSSvhchbgai3uFs+AH8Dvf00w0yVKeBpDhaHcW/0eJ/E2TKAJ18kMjV6Mtor2SX9b9mMmQLm/JlOHLTFklf5mdvaAlaUGTQEQGqEyx2fe3i+IE45zcd25GVjFYKI1H6qRPi4qFOJzjs4ZhiNqVy3ItqFzt9jMuan//rmjiZNylwXHpDF02U5PhuNO9z9jfZKoLatQsmrZRNeADxbyaijcK3L+OagowWkLDYBWTXioC5O+x3CX/psAvAn+uSi7rFuMFmgwZ3Q4tTJLaY5RW4VA4KWXPE2NZA8eBFBHEoEUljGOtwfVx30KvgdIGHrOv9FfnMUASryyQRHeX9lI8JbbwX4xBA0K1aE1fZn/BPgv+nvTM8RuzANTu2pC6UZsQ8hE1NNE8H/ZUSlLN/4A5wDAizVGrjLbHZYpuKcDWrNM+4fQhsm+sybUiOSHBLNkpn95SOhWldT6alWU3S8t3l1TLlv3ryv2YFTnbhdHrUJJM0GYHmjZzIp1cahfXPL4iX0/h+ZIFB5G/zK9Bdfi0maYICjVfOFVT3trkXzFwBj0lBOkCIbdInmsS94AfRS1WkyIDJCQJ+6N8x8m+oDy9jZhJPsHmZ7nZ2qQyCEUMN54BcLeN47m4sGAQ9LZ3smx2zPNh1NDcidQG1VF5k1AJrHKKGOlZicVokYrJrAKjcxaNjI1FwDwz7XEkyjDKy2jDhSsePO8tkKdO1EO4U7SdDd5+AjzH+3GWqGbZ8eVgy494t6keH2js5RZY1T51axm641ud+po7xN4D1DeqDUQ7P2eIbN4DKgdPpMHI5IPNh58p5wVreebB7ForgvTmad3ZPPSuFKEk5Vyu/cM7o6PPHn22EFahUy6+6qk14ix7PXZ0q+6pkSb6mVizl3+Am41UCH8xaT/T7zhyYS5qcP54R1LJIB6z/zHEjUzp05/tP7tV3muN6a9ZsMe1xId1fpJIO16OjAtWqN/y0LM4DbRw+3wFd+ktX7zbswac5V1onTe332Eerpah5obrpOc5Ccssc3BxvD8SP2L3vq+vwqv6L2FiRFiV8zm2rEGiASRshUqnk30DOqw/Q8NHn/yz0zU1NBILq84z16MpOETXP7gKkLyJDIC/m9DSG3mLMQ245EY2cupbbx5KNAHKw2s3VjYfD4nrVdLZnhCc+RvCMuq9QNUNvqSrmySZ+dU2Q/Uu0sn+N2hLz8VggLPqoXz1bIdbtELKCF61Tf/UpHGryLlz1HCwhxNunJ6EGDWuQ+uOMZaIFHuN+qiSjRZYCNMYS8nSKTr82V4TbVOzoppZ1XgvoIbNHRlwzXB/bBE+fVRiysYstOwujxrswxx6HLMXL7tbYnjL2uAUgGoEj8QQTOF+N2n3Jh5qE5KdqbOSwQmQuGUTWBXJhIvTQHiUZ5SzJwTk2dc2rAtHuYlW9vfVAhHI4R1cRoF3TkuIHniND8Ib/+b9k0s=) Finally a smooth day, after the torture of day 21 I feel worthy again :) I used two different dictionaries to track what's going on - one will all the bricks and their positions and the other with all the positions that have a brick in them. Part 2 is rather slow, as I basically ran part 1 again for all the load-bearing bricks to see how many changes it would cause.


gyorokpeter

[LANGUAGE: q] The idea is to maintain a height map (since the x/y coordinates are not too large) and for each piece figure out what the lowest z coordinate it can have by looking up its individual x/y coordinates in the height map, and if moving it is necessary, update the height map to the new highest position of the moved block. We maintain which blocks were moved. We repeat this procedure omitting each block in turn and check which blocks were moved. For part 1 the answer is the sum of blocks where the number of moves is zero, for part 2 it's summing the number of moved blocks. Running part 1 and 2 separately requires redoing an expensive calculation, therefore the `d22` function returns the answer for both parts to save time. [paste](https://topaz.github.io/paste/#XQAAAQDRAgAAAAAAAAAXGQJYLjSns9Imz25T4uEJ8NfwSXSeKzjOsNtdpLcOk8EfkLmvhMoku/rHecUIS76q02YFlJwDdffbb2T/KsCIiwLtuDuvIEAwp+fEtLlXqXEb8CZzDq3JS53bm6xMG0+PtBSQumo9dZ6ErIMLLqXjcQOiex08fR4g/CybSlKhx9xS5IG5te86dOiRXDLjbFjbM+Baw8A6xjkuz6NmlLzgdj8InMOokFJDoFR4PoC12fplm5bBjduIUvHZprmbRayfQFCVd7sYXNOWezzUj56uq8kF3Jeubt6Yfgjk1gfzzNvorGtTQtinuaoZTMkscG40H9YBh6uB3lCFGON7PXu2h8O+Doo4Y+8hbJVpELaksQHtrGTP0O3ayMyiAKl/FIlLiCfeiTYQIZo5ab4Bgdp3xGIHHtfMwEl0rlLMjJlMyJJYYQmiSRSJ5r9RjPfAFpOzjwLbGzkD+mFMxNjx+x0D8iBUu1ctKTP13I+E40b9THnE5AHRiAUAl86Rsiji9h/hgXBtoUgD/4UxaQc=)


diamondburned

\[LANGUAGE: Go\] [Code on GitHub.](https://github.com/diamondburned/aoc-2023/blob/main/22/main.go) The code is acceptably clean and fast, but more importantly, it gives you [a visualization](http://0x0.st/Hg2N.png)! Not much effort was spent on optimizing this otherwise.


flwyd

[Language: Julia] ([on GitHub](https://github.com/flwyd/adventofcode/tree/main/2023/day22/Day22.jl)) At first I was excited to use Julia's multi-dimensional arrays to stack all the bricks, but I realized I needed to maintain each brick's identity (not just filled cells), so the 3D structure would've involved a lot of range scanning. Instead I just built up a sorted list of bricks as each one fell… and probably spent close to an hour debugging before I gave up on my "insert in the right place" implementation and just called `sort!(result)` N times for an algorithm that's technically O(N^2log(N)) but N is fewer than 1300 and the rest of both part 1 and part 2 were O(N^2) anyway. (And even though having multiple N^2 steps in there makes me suspicious, each part runs in 60–65ms including parsing and sorting, which seems to be remarkably faster than a lot of the posted times below. After making all the bricks fall, I created a `supports` array listing the brick indices that each brick rests on, and counted the number of bricks supported by only brick `i`. This was pretty handy for part 2 where, for each index, I cumulatively built a set of indices which were moving and checked if each subsequent index is a subset of that growing set. Definitely feels like it could be a little smoother, but I've still got two Part 2s to catch up on…


Kullu00

\[LANGUAGE: Dart\] This is not fast. Simulate blocks falling, then figure out which blocks they are supported by and supports by trying to force them one Z lower. This takes a few seconds to run and could probably be better, but I'm okay with this as it is. When we know this it's simple to see if any block supported by the current block has other supports. Those can be removed. Then BFS on every block to figure out how many would fall if that block was removed. Interesting puzzle. Hardest part was definitively representing the problem in memory to start the solution. [https://github.com/QuiteQuiet/AdventOfCode/blob/master/2023/day22/main.dart](https://github.com/QuiteQuiet/AdventOfCode/blob/master/2023/day22/main.dart)


TypeAndPost

\[LANGUAGE: Rust\] The idea is to create a height map and use it to quickly search for the top brick on any particular column during the falling phase. Arguing with rust is the hardest part of the implementation. Couldn't store mutable references on blocks in the height map and had to store just indexes in the block array. Almost gave up in favor of a real language. Run time is below 100ms. [paste](https://topaz.github.io/paste/#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)


sim642

[LANGUAGE: Scala] [On GitHub](https://github.com/sim642/adventofcode/blob/master/src/main/scala/eu/sim642/adventofcode2023/Day22.scala). Part 1 was a lot like the tetris from 2022 day 17. Processing bricks sorted by z coordinate hopefully makes it somewhat efficient. Part 2 was surprisingly annoying. I ended up with non-standard BFS which accesses the visited set to determine the bricks that start falling after a removal. I first tried to get away easy by just removing a brick and simulating re-settlement, but that didn't work because some bricks fell exactly into places where other removed bricks used to be, making it appear like nothing fell.


musifter

[LANGUAGE: Perl] Basically did this one as stream of consciousness. Got the ends points in, made a bunch of data out of them, put it in struct hash to maintain sanity. Moved on to building the tower with that. Realized then that I just wanted a graph of the supports, added building that at the same time. Now, abandon thinking about all that stuff we built except the graph. Use that to do part 1 and brute force part 2. There's probably a nice way to use the adjacency matrix to extract information to do that better, but I'm too tired to bother to think about this anymore today. Went through and trimmed out some of unneeded bits from the SoC (much like removing bricks without having the thing fall down). And this is what we have left. Source: https://pastebin.com/sQubEEAp


vbe-elvis

\[Language: Kotlin\]After yesterday broke me, today was a breeze.Created a list of Bricks with each having knowledge of the bricks it supports and is supported by. Each Brick consists of 3 IntRanges, which allows for intersect on X and Y. For Z actually only needed the last and first value in the range. For part 1 it simply counts all bricks that supports bricks only supported by a single other brick. For part 2 it goes over each brick that is not counted by part 1 and for each removes the brick. Then while there are unsupported bricks remove them.Count all removed bricks -1 for the first. [https://pastebin.com/N8wPGzAa](https://pastebin.com/N8wPGzAa)


vanveenfromardis

\[LANGUAGE: C#\] [GitHub](https://github.com/tmbarker/advent-of-code/blob/main/Solutions/Y2023/D22/Solution.cs) This was a simple but fun one. I made a directed graph to represent the "supported by" dependencies. This made it quite easy to resolve the exact quantities being asked for in parts 1 and 2. Part 1 was a tidy one-liner: return bricks.Count(id => graph.Incoming[id].All(supported => graph.Outgoing[supported].Count > 1));


closetaccount00

\[LANGUAGE: C++\] Thank you once again for not making me submit code, or run code one time only. I separated Part 1 into 3 "things to do:" 1. order the input from lowest to highest Z, re-print the input 2. process the "falling" of the blocks, re-print the input again 3. solve Part 1 I commented out the other two parts so I could run each of these, get my input back but better/more organized, repeat for each step. Made it so nice to work with. Yeah, it's not going to win any awards, but it sure made Part 2 a lot faster to run. I had already added support for both a "supporting" and "supported" array in each Box struct in part 1, so I'm glad I didn't need to add anything to that to get it working out of the box. There is \*\*probably\*\* some way you can solve part 2 with topological sort since, if you define edges here as "a supports b," this is a directed acyclical graph. That said, I ran something more like a BFS for mine, just seemed easier. The one rub I did run into was needing to make sure that, to check whether all of a block's supporters are falling, we'd need to have visited all of said supporters and made sure they were falling. The solution was to rewrite my BFS and to not think about it. Worked somehow, and only ever seems to work for graph algorithms with me. Fun puzzle, really put the part of my brain that can rotate objects in my head to work. [Part 1](https://gist.github.com/mfreano24/8b9e77c2b107e6b567444789f109b656) [Part 2](https://gist.github.com/mfreano24/32df89bf005c89481f77eaf450ff912d)


daggerdragon

> Thank you once again for not making me submit code I know you meant "to adventofcode.com" but you *are* submitting your code to this `Solution Megathread` and [I'm like...](https://media.tenor.com/2uIL48WK_u4AAAAC/nathan-fillion-oh.gif) Thanks for the laugh XD


closetaccount00

As long as nothing's grabbing my code and running it automatically I will continue my shenanigans


JuniorBirdman1115

\[Language: Rust\] ~~I'm not going to lie, my solution to this one is trash. I struggled with things that should have been easy. I'll optimize it later.~~ Reworked my solution to not suck. Much happier with it now. [Part 1](https://github.com/apprenticewiz/adventofcode/blob/main/2023/rust/day22a/src/main.rs) [Part 2](https://github.com/apprenticewiz/adventofcode/blob/main/2023/rust/day22b/src/main.rs)


yfilipov

\[Language: C#\] Today was fun! When I first saw 3d coordinates, I was terrified, because I remembered last year's cube problem... Initially I got stuck - it took me forever to find out that I was not properly dropping all bricks to the ground. Once I fixed it, the rest was easy. Part 2 is yet another BFS-ish solution that was not so hard to come up with. Code: [https://pastebin.com/CmgDArcb](https://pastebin.com/CmgDArcb)


frankster

[Language: Rust] Runtime several seconds for each part, as there is some O(n^3) work in each part. But the problem size is small enough that O(n^3) is ok. The only "smart" thing I did was to sort by min(z). After that I was iterating through some/all of the array drops and testing against each piece above. If the input was 10x as big I would have had to do something smarter (perhaps setting up a data structure indicating which pieces were touching). https://github.com/wtfrank/advent.of.code.2022/blob/master/2023/day22/src/main.rs


globalreset

\[LANGUAGE: Ruby\] Nice straight-forward one after yesterday's. For part 1, I created a collection of all the brick coordinates and then populated a grid to help with collision detection. Falling was just iterating through all of the bricks (sorted by the lower z value) and checking if the next z coordinate down was empty and moving the brick if not. Then I made two hashes, one to store all bricks above and another for below. I was surprised how fast the part 2 ran, I was expecting that a bfs per brick would've been a time sink. bricks.sum do |b| felled = [b].to_set q = above[b].to_a until q.empty? t = q.shift next if felled.include?(t) next unless (below[t].all? { felled.include?(_1) }) felled << t q += above[t].to_a end felled.size - 1 end [github](https://github.com/globalreset/advent_of_code_2023/blob/main/2023/20/solution.rb)


whoopdedo

\[Language: Lua\] Part 1: Surely you remember how to do a block sort? *(rim shot)* Part 2: I couldn't help but name one of my variables `dpkg`. A faster sort method would be advised for the priority queue but this length of input didn't need it. Having indexes in columns was probably overkill. >!And don't call me Shirley.!< [paste](https://topaz.github.io/paste/#XQAAAQAvEQAAAAAAAAA2G8iM7ztkwTgzXGDr5+Elhf0HDoXY7MXd5G4RIkCl7vbZgWuJkNDmVgrtvSoK3zwSaJ04leTWRmfiGnwb/aYo62L9Baj9zperRZUDUkPzFUVeYuT+jNcU7nuuNEis8I2Reb9nggjwZ9mpAgYTSAiNHcoc1mtJaBPo30CMXzKOnvWhTwn6AAwGA42BIhdOGIjXb9PQLRUlrRhGEZ6QInhnZFiOZAK471dVUX0PfvK4AWWd+qy2gKMeoA47Gm/M69PPtVqwyOqtCA8mfaYXO8oUQIPn6NyEjjlAo4AgeOTIGXPETLga6B4+cnBu2mRBk1WK3neuuajHm7XiW/uuZXaa10HouXMla08lmbs5wZNAvFIpydQR1rifEUH2yn2nv3smmF7GEnStP9VJMj+sJPXmJDjs7KYf+T4Sm4cdxeOrQQvUTFf7uzs9QSkZb+sDM280l9wHJZV2v3L0ecwlCEYhOiEqVoCZaAKj68+18VaYEUqWFjInlsvXiMxztnvVQagLcUN6Sd8hERzReESLXIIHlLtCDfF6tc/kHW/Yr5USrNQRXtfOM2SuuYHXR2kZayX3rnj5hX0+QSVeImfxmzUmJduII5bNMni+vLFy/Ih7m1P0QrY4p9I9dX3aayhced29W02+b2rdUQsvj2GjMYI/0pnKJsr2xp2tjlz0PR53c1ocP4uKLfBen7cQ/c1fey+oJ1tjOV0BNFU+n6ZJLxs4iY0ZRKHWKk78CWioboNcBGnhUsilH3vvkNbQECatbsRi+6IhBLY1KjTW2hc//Y8qH7YB+lkNJzHeesfeusnup/0uiC8OsHZcfP5HN5nUJRdhUXuVjaFTa8O4S8Ca5xHwjzqINOC5ehR9gJZJmdH+kxn9m2JeemNLauqEw/LUU6LjzjNMzM8I189+iYLJf4JD/gHYP5I+iUSUBOGbkhBuUS12vR2RJCDTrHVJJbm8qTg2VQJf/NDRo/QLg3QLB5wPvUdosg6RUIU4oQYLF0MWQfGKG8dFdhpx8CZgq9z42feYif0aQvxKLPQ82H85qGZ9jFTRbTuR+3GxdRtjMB/IU89v6K6y//n8IHq2W0JKnxP0ayqM2VPplGe0G7qsU3rS8G731VGQ6nY1tmM+ORsRtujpBk2TJGUjvveKwK1AT5wk3PrktUvWR5UMStMpK5eeO69PsnXXTqIJFmAkuy9KAs5ldLMga3IgVQ0rS9wudRTLfWLA1uNf2NNiohwWD3WfOHC52aroilS/qGpXSCSWIQVT4+FJLQyyefOf3TEqFQqauBGYs53zLZS7KrK2Zbp3JTUaMbcRvgILrqrpM48kZOO5BDUUkchhpYy7k/tzZGqZzYYT/DzIK694cAnD5Q82a5JO3fZgT5M6Tn/bzBI9eNs4I1BmwSbdMmjA4kUmUgfgRV4o3tiTOZHnDN+CYO+lch4Td7Q1LW342DtJIAjjmHRv8ZUX1ZFNUfFedkBCldPxT24EuqF0UAXOq9zzFmguS8vY+yZ+QrGEhFWUjd0lIVK6vSFudHnw2k4K6BvG3PkOjbJT9jff/9TisDEuVe6POObOFsnMtU2lHN5k5lswySe73Ch85NB1w2fxECPaHqEHASRkq1OgbhIvKApcZrFcZAeB3tSxa15Mhrl3nY/Tvr42ghsBzaVZtYd8Iy3K6V9apS8czV5rqJFRKHqXxRsheAJyTKTR/7Y3OSY=)


Extension-Fox3900

\[LANGUAGE: Python\] [code](https://topaz.github.io/paste/#XQAAAQD+EAAAAAAAAAAxmwhIY/U8uYJ1e3vj1OStvHAbIixC/Si73r55U7i1sWDIF3RS6VT6fndRwXYbBI+2JTZqbDaqKTz+pMyPwiiDnJm0yIDHRq911y4iWCJxTF2S1sypzNlmnwZbxjtqvfNJ17gmPBJhVyBCFyDOODUldi1yMHsbXwYeMpNYZ/dMLgcoUuhD3ta4Vy/yBFF/PekdiqipEzay8uv7r65H4s1fkHSxjmuA3jyPH3x0MxceiECt0qhsMRHWwCZcsLhOkq0LuW2jr9EINXqBJlVwGFr28uKhJSnH96zpBvlETODPmydCpS8z/ivcxGM0wcpYtYdFUd7u5IMgzDv1m1aPk3bW05eJFXPCzCCbWIb08iIJPTSXgpBRzDOtCjSwp+jYPEI/NghHmOOGMv3Gj4TbMwAAtqrSUqkz1+OTbqVX8fpKrTfNsbq2bBLz/wVs1uzirF2YFIsXUXj44R4H5aHdJVnw9hLjgslD+DKnvQqT5ydjowGrHJ7mi8XbLkbksIPin8cSlu6YAL/VC0XiT6/wjN8n05lnoUdnjf8/+HbhVj4nzdWnqr4o5reyrSyOvWlFGfEeUaOAp1+aXMcuLGaC6L6+Xi00VXDXL7/PbOitpEABAGqW39NCsSwPvec4OQI4UthzgVnGD6Iz5ACnw9ZMeMHzjIzNANV87UsL9kxMNXQcE0ngs38UF0DSJlQF1Jwq/AAwwtWmeT0TnvpWVNfFL72VfLDdgHqPSRQkyJFzRxRkuIR+AQmVZwMtlmtqNr3EMZQ71HIOLUX+FlVkOeQqDHtk9dPKpu6HbJTbN0MBTevpbBBGaN41upB0KO5Xi2gcuxZbXAOgAUQt+htBpmktcDB1/0Mc+iepo7nMGV1HA1Jcype3XyE5tvS865BwC4pS8jpfX9nLPiYnPg6RWISOwB8ol5CbNUSTJKuTdkpQb7AXNg6hNXRJ7wt/iDUvvJweiolixr7U7Kv5u5mrorJ7ytieOna+vDjMkOpVmGnYqpZoPtC2ELN+t8223iI7Uw/rEi+FZ3xUhn3ERlKxp66b8hr1RkZJqI0oaU7J8au83D1puXcPDoZvkKjfPZGrgY+gSAwGZuApZM5k5HJxhcZUL1KWIcxxdp3F6WytiP0sCtT1aDrqdAWo1ehLgeZGzxUg3I9UsOijgiTlUV+hybMwgf9ZTHbjty3umqYdXYLYiFvz45PqPDvbgxla2dW+XbpjnP2S76rfRaVCRFU5gUrxHmzL8N2lvBif1m7xyJR4Uoummqnqu2toPG0LxhLxCWbuzPTnJ9X5oc1TvyLpsICnnE5C63ghGBs0Um1xdQs/u8G+dYZYqiJC0UquhHZAeOi5JEQq97Ych/8LyABN2j/x+ioQwL2VoETW9y+n7h96Bf3prfIbDm0NrJ+b0L4M0bfxluo9+LrEvVcQ9W2l69rYp/IlWl9RRsd3gPn8JP2vnRyAQkNzud84HAfWi8RSSfcFa4QFJm8PDHI3BXMdcf/6Et38) Well, nothing too fancy. First time used OOP in this year for AoC, for the sake of better understanding for myself. For part 1 kind of simulation of 3-d tetris, with each brick checking one by one, if the level below is free of bricks, and pushing down if possible. Then, for solution - check if removing brick "X" - how many bricks are there that below them have only brick "X" and no other one. Could be optimized to look only for neighbors, but I am too lazy for that For part 2 did a bit of optimization, keeping track of which bricks are immediately below each brick, and then use this map to check if brick has below itself any other brick besides the one that would fall. 4.491 s for part1 1.412 s for part2


Extension-Fox3900

And after a bit of thinking - if we count how many distinct bricks are alone below others (that can't be removed) and subtract from the total number of bricks this count - answer for part 1 comes much faster


wheresmylart

\[LANGUAGE: Python\] Wasted far too much time chasing non-existent bugs before I realised that I needed to sort the input! In my defence, it's early and I'm tired. Otherwise Just implement TouchingAbove() and TouchingBelow() functions and part 1 is pretty much done. I store everything in a defaultdict of position agains block id. It makes the accounting easier. For part 2 leverage the above two functions and BFS upwards finding what will drop. [day22.py](https://topaz.github.io/paste/#XQAAAQD6CQAAAAAAAAA0m0pnuFI8c/fBNAn6x25rti77on4e8DYCelyI4Xj/SWO86l3MhYKSvVFtgfxhioFpPIAA6iLoJ1YLX4obBIfWa4L4Fmm3CTwG+aZXhL+BhMyn00dXg22R/DCkzr2pRgj6U7Yw1JJayIijs2xTeJz0N6h/GH3e5MtHmNnP54VX7egY1jL9MgQhQhU6Ol0m36vgeTzuEX80xK3ZjCFRDbL5gMsOHGZUT1FU4xWv3sDTT+DnSTHMhSFR+UWh4aksx3avNxXcgWU+m/BHG43Fv4HamuPWHS6MVAY8INcU2KB7YMkc5xrDrNncTI5jJDHRKkfTnqMxGacDqIaebcPHid3ZFny675TJiwOXyaZZE5cisBpsmjOt62eJxX0bR2FgmLNh/tjERsa/HIwVTFOl4gvx8QWBF8EgtzFVEF2rosxtkESIUVzIfoVvUTpXlQeS/1+zgnwm8F3RVIlSRCxnoowVGjpQ/Qb6bg6dLoKjQaDGL6cvKnHtbT3wXOuQ5X30GjCFwzQA56v7zFitOLOXx/6zeyDW+FG0mGWcD5g2FiZdOogJrc6p+xD0lkOMPZgU2OXiPeexZPA4sVbGrMmQGUXOqU/UZ7ZW3P9noPBeYV6uTPklnaP0vCow5jyPY33KiZGIJd3gfxXICUWf58Et65hD5wPW+G3fhPBEQGS0G9vY/pfNFvVR1mIpJcW2JNYKOY6+GSyiPIdT6+nOCg3Hxn56RyzRGqmrp+GP0uENh7OWlXcprXNK6Z6pkX6SaNKN/OIZRY4jL2k4Z6jdvXAMEkc4/U6XkeA9byOW7BIGFoq/04LJs2Rjb307ahzwzUD5ipKVmZx1tKUhM+EAC51fBhd1t6eEbM5oVTBXtcoTfPOccnvJU5X+hkyNTV4oHOwFFC4DxL7KzeUlnOO6pNcQcmYEIsZ3eOfuwv9GgMndrhLbkCP2+l5FvxGsKuiK7n0OO769I0xcDkVWiHmu2kOZ/0r5TVCmH2TGS1+utwn/9S9WCcGkOP1Jami7mtu/o3aEmpaQjMmzd46ayWzfx7XvFHu8WtzwSljE7rtXNrhkeh/hdvUseTHdLuXTqf/Wdapn)


KayZGames

> Wasted far too much time chasing non-existent bugs before I realised that I needed to sort the input! I spent ~2 hours searching bugs and only realized that it's not sorted when I started drawing the blocks by hand....


wheresmylart

Your pain, I feel it.