summaryrefslogtreecommitdiffstats
path: root/src/bin
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2022-12-14 01:07:49 -0500
committerJesse Luehrs <doy@tozt.net>2022-12-14 01:07:49 -0500
commit41bd54af7fd1ebd28122584abe811c7076571bc0 (patch)
tree2e34eea0b7c613b9b2b940c79665346c3a2f85d9 /src/bin
parent08d25b19f75484fc2d036dec7d431910e75f7cad (diff)
downloadadvent-of-code-41bd54af7fd1ebd28122584abe811c7076571bc0.tar.gz
advent-of-code-41bd54af7fd1ebd28122584abe811c7076571bc0.zip
day 14
Diffstat (limited to 'src/bin')
-rw-r--r--src/bin/2022/day14.rs129
-rw-r--r--src/bin/2022/main.rs2
2 files changed, 131 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
+ );
+}
diff --git a/src/bin/2022/main.rs b/src/bin/2022/main.rs
index 90221d9..9cc2ba6 100644
--- a/src/bin/2022/main.rs
+++ b/src/bin/2022/main.rs
@@ -24,6 +24,7 @@ mod day8;
mod day9;
mod day12;
mod day13;
+mod day14;
// NEXT MOD
#[paw::main]
@@ -43,6 +44,7 @@ fn main(opt: Opt) -> Result<()> {
11 => advent_of_code::day!(2022, opt.day, opt.puzzle, day11),
12 => advent_of_code::day!(2022, opt.day, opt.puzzle, day12),
13 => advent_of_code::day!(2022, opt.day, opt.puzzle, day13),
+ 14 => advent_of_code::day!(2022, opt.day, opt.puzzle, day14),
// NEXT PART
_ => panic!("unknown day {}", opt.day),
}