Function aoc::y22d14::y22d14

source ·
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);