pub fn y22d14(input: &str, part: u32) -> u32
Expand description
The solution for the day fourteen challenge.
Given the input as a string and an integer to determine if we should run
part 1
, or part 2
of the puzzle, we start by building a
std::collections::HashSet
of the spaces that are currently occupied by
rocks based on parsing the puzzle input. The set contains the coordinates
that are currently occupied (right now by rocks, but also by sand once we
start the simulation). While doing this we also need to record the lowest
“Y” coordinate which we can treat as the floor. We do this using our usual
std::collections::BinaryHeap
. If we’re in part two we take this floor
and add two more spaces below as the prompt tells us there’s an actual
floor two spaces below the lowest rock.
Now we can start the simulation. We let sand fall until we’ve met the
condition to stop letting it fall: in part one when the sand would fall
forever, and in part two once it reaches the starting point of the sand
(coordinate 500
,0
). For each granule of sand we start at the entry
point. We then check the coordinate below (this is slightly tricky as the
“Y” coordinates actually count up) to see if there is a space either
directly below or below to the left or right where the sand can move. If
it can’t then we stop, add the sand into our occupied spaces set and move
on to the next sand granule. If we’re in part two and the sand didn’t move
from its starting position then we’re done. Otherwise on the next (and on
every) iteration of the sands movement we check to see if the sand is
below the floor which means that it would keep falling forever, so we’re
done. All that remains is to return the number of units of sand that fell.
§Example
// probably read this from the input file...
let input = "499,4 -> 499,5 -> 496,5\n503,4 -> 502,4 -> 502,7 -> 494,7";
assert_eq!(y22d14(input, 1), 19);
assert_eq!(y22d14(input, 2), 54);