diff options
Diffstat (limited to 'src/bin/2022/day14.rs')
-rw-r--r-- | src/bin/2022/day14.rs | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/src/bin/2022/day14.rs b/src/bin/2022/day14.rs new file mode 100644 index 0000000..96c986c --- /dev/null +++ b/src/bin/2022/day14.rs @@ -0,0 +1,129 @@ +#![allow(dead_code)] +#![allow(unused_variables)] + +use advent_of_code::prelude::*; + +pub struct Map { + grid: Grid<bool>, + generator: (Row, Col), + abyss: Row, + sand_count: usize, +} + +impl Map { + fn filled(&self, pos: (Row, Col), floor: bool) -> bool { + self.grid[pos.0][pos.1] || (floor && (pos.0 > self.abyss)) + } + + fn fill(&mut self, pos: (Row, Col)) { + self.grid[pos.0][pos.1] = true; + } + + fn drop(&mut self, floor: bool) -> bool { + let mut pos = self.generator; + if self.filled(pos, floor) { + if floor { + return true; + } else { + panic!("generator filled but no floor"); + } + } + loop { + if !floor && pos.0 + 1 >= self.abyss { + return true; + } + let mut can_fall = false; + for next in [ + (pos.0 + 1, pos.1), + (pos.0 + 1, pos.1 - 1), + (pos.0 + 1, pos.1 + 1), + ] { + if !self.filled(next, floor) { + pos = next; + can_fall = true; + break; + } + } + if !can_fall { + break; + } + } + self.fill(pos); + self.sand_count += 1; + false + } +} + +pub fn parse(fh: File) -> Result<Map> { + let mut grid = Grid::default(); + for line in parse::raw_lines(fh) { + let coords: Vec<_> = line + .split(" -> ") + .map(|pos| { + let mut parts = pos.split(','); + let col = parts.next().unwrap(); + let row = parts.next().unwrap(); + (Row(row.parse().unwrap()), Col(col.parse().unwrap())) + }) + .collect(); + for pair in coords.windows(2) { + let (row, col) = pair[0]; + let (next_row, next_col) = pair[1]; + grid.grow(row + 1, col + 1); + grid.grow(next_row + 1, next_col + 1); + if row == next_row { + for col in + (col.0.min(next_col.0)..=col.0.max(next_col.0)).map(Col) + { + grid[row][col] = true; + } + } else if col == next_col { + for row in + (row.0.min(next_row.0)..=row.0.max(next_row.0)).map(Row) + { + grid[row][col] = true; + } + } else { + panic!("diagonal line?"); + } + } + } + let abyss = grid.rows(); + grid.grow(grid.rows() + grid.rows().0, grid.cols() + grid.cols().0); + Ok(Map { + grid, + generator: (Row(0), Col(500)), + abyss, + sand_count: 0, + }) +} + +pub fn part1(mut map: Map) -> Result<usize> { + loop { + let abyss = map.drop(false); + if abyss { + return Ok(map.sand_count); + } + } +} + +pub fn part2(mut map: Map) -> Result<usize> { + loop { + let blocked = map.drop(true); + if blocked { + return Ok(map.sand_count); + } + } +} + +#[test] +fn test() { + assert_eq!( + part1(parse(parse::data(2022, 14).unwrap()).unwrap()).unwrap(), + 737 + ); + assert_eq!( + part2(parse(parse::data(2022, 14).unwrap()).unwrap()).unwrap(), + 28145 + ); +} |