The sand is falling in compacted bricks.
They are stacking on top of each other!
Today’s input is a snapshot of the bricks while they were still falling.
An example input looks like this:
Each line of the input represent a single brick.
It is represented by 2 points, one for each end of the brick/stick/whetever you want to call them.
The bricks will never rotate, and are very strong (something, something, magic).
Even if only one piece of a brick is supporting all other bricks, the tower will not fall.
The bricks cannot pass through eachother, so a falling brick will come to rest when it encounters a space that is either occupied by an other brick, or the ground.
The ground is located at z=0, a higher z means the brick is up in the air higher.
Parsing
The 2 points for a brick are separated by a tilde ~, and each coordinate within it is separated by a comma ,.
I used the word coordinate, so I made a Coord structure.
One that can handle 3D space this time.
Paired with a method that can turn a string like "1,2,3" into a Coord { x: 1, y: 2, z: 3}:
A Brick has 2 Coords, one for from, and one for to.
Using that to parse the input into a list of bricks:
The question asks how many bricks can be safely disintegrated.
A brick can be safely disintegrated if removing it causes no other bricks to fall.
The pseudocode I want to work towards:
Preparation
To let every brick fall, I sorted all bricks by z first, then made them fall one by one, starting at the lowest one.
The occupied map keeps track of every single Coord that is occupied by bricks that have come to rest.
After a Brick has fallen, all its coordinates are added to the occupied map, and the next Brick can start falling.
The fall method lets a Brick fall as far as possible while respecting the positions that are already occupied.
Now that the bricks have fallen, I want to build up some data structure that keeps track of which bricks are supporting/supported by other bricks.
This can be done while letting the bricks fall!
For every brick, I kept track if the index in that sorted list to identify it.
When a brick has fallen, I add every Coord the brick occupies to 2 maps.
Above map - given the index of a brick, return all bricks it supports
Below map - given the index of a brick, return all bricks it is supported by.
To achieve this, some minor changes:
And to the methods on Brick:
Helpers
Using those 2 maps I can write a helper function to determine if a brick is safe to disintegrate.
The function takes in an id (index in the list of resting bricks) along with those 2 maps.
For every id that gets passed to the function:
If no bricks are above it, it is safe to disintegrate.
If there are bricks above it, removing it should not cause any of those bricks to fall.
Code
Part 2
It’s not fast enough!
We’ll have to take risks and set off a chain reaction.
For every individual brick, calculate how many bricks would fall if you remove it.
The question asks what the sum is of all those bricks.
The pseudocode I want to work towards:
Helpers
The parsing and preparating are identical to part1.
A function that takes in the id of a Brick, removes it, and recurses with the ids of all Bricks that no longer have any Brick supporting them:
The id of every removed Brick is remembered in a set.
So the length of that set - 1 is the amount of every other brick the first brick caused to fall.
(minus 1 because it includes the brick that was originally removed, and the question doesn’t ask for that)