diff options
author | Jesse Luehrs <doy@tozt.net> | 2021-12-25 00:29:43 -0500 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2021-12-25 00:29:43 -0500 |
commit | 3dfa5bd6227ce8654f75371bd7de06b0cbe92f87 (patch) | |
tree | a81539784e9c1d8e93e9b93ff3fcd32aa9d80ae1 /src | |
parent | efd2635dd73b7806d75d23e21f37bd82288820c1 (diff) | |
download | advent-of-code-3dfa5bd6227ce8654f75371bd7de06b0cbe92f87.tar.gz advent-of-code-3dfa5bd6227ce8654f75371bd7de06b0cbe92f87.zip |
day 25
Diffstat (limited to 'src')
-rw-r--r-- | src/2021/25/mod.rs | 99 | ||||
-rw-r--r-- | src/2021/mod.rs | 4 | ||||
-rw-r--r-- | src/grid.rs | 47 | ||||
-rw-r--r-- | src/parse.rs | 18 |
4 files changed, 151 insertions, 17 deletions
diff --git a/src/2021/25/mod.rs b/src/2021/25/mod.rs new file mode 100644 index 0000000..67d589e --- /dev/null +++ b/src/2021/25/mod.rs @@ -0,0 +1,99 @@ +#![allow(dead_code)] +#![allow(unused_variables)] + +use crate::prelude::*; + +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum Cell { + Down, + Right, + None, +} + +impl Default for Cell { + fn default() -> Self { + Self::None + } +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct Map { + grid: Grid<Cell>, +} + +impl Map { + fn step(&self) -> Self { + self.step_east().step_south() + } + + fn step_east(&self) -> Self { + let mut step = self.clone(); + for ((Row(row), Col(col)), cell) in self.grid.indexed_cells() { + if *cell == Cell::Right { + let mut next = col + 1; + if next >= self.grid.cols().0 { + next = 0; + } + if self.grid[Row(row)][Col(next)] == Cell::None { + step.grid[Row(row)][Col(next)] = Cell::Right; + step.grid[Row(row)][Col(col)] = Cell::None; + } + } + } + step + } + + fn step_south(&self) -> Self { + let mut step = self.clone(); + for ((Row(row), Col(col)), cell) in self.grid.indexed_cells() { + if *cell == Cell::Down { + let mut next = row + 1; + if next >= self.grid.rows().0 { + next = 0; + } + if self.grid[Row(next)][Col(col)] == Cell::None { + step.grid[Row(next)][Col(col)] = Cell::Down; + step.grid[Row(row)][Col(col)] = Cell::None; + } + } + } + step + } +} + +pub fn parse(fh: File) -> Result<Map> { + Ok(Map { + grid: parse::grid(parse::lines(fh), |b| match b { + b'v' => Cell::Down, + b'>' => Cell::Right, + b'.' => Cell::None, + _ => panic!("unknown cell {}", b), + }), + }) +} + +pub fn part1(map: Map) -> Result<i64> { + let mut prev = map; + let mut i = 0; + loop { + i += 1; + let next = prev.step(); + if next == prev { + break; + } + prev = next; + } + Ok(i) +} + +pub fn part2(_: Map) -> Result<i64> { + todo!() +} + +#[test] +fn test() { + assert_eq!( + part1(parse(parse::data(2021, 25).unwrap()).unwrap()).unwrap(), + 482 + ); +} diff --git a/src/2021/mod.rs b/src/2021/mod.rs index e5cdeb2..e7a838b 100644 --- a/src/2021/mod.rs +++ b/src/2021/mod.rs @@ -48,6 +48,8 @@ mod day22; mod day23; #[path = "24/mod.rs"] mod day24; +#[path = "25/mod.rs"] +mod day25; // NEXT MOD pub fn run(day: u8, puzzle: u8) -> Result<i64> { @@ -100,6 +102,8 @@ pub fn run(day: u8, puzzle: u8) -> Result<i64> { (23, 2) => day23::part2(day23::parse(parse::data(2021, 23)?)?), (24, 1) => day24::part1(day24::parse(parse::data(2021, 24)?)?), (24, 2) => day24::part2(day24::parse(parse::data(2021, 24)?)?), + (25, 1) => day25::part1(day25::parse(parse::data(2021, 25)?)?), + (25, 2) => day25::part2(day25::parse(parse::data(2021, 25)?)?), // NEXT PART _ => Err(anyhow!("unknown puzzle {}-{}", day, puzzle)), } diff --git a/src/grid.rs b/src/grid.rs index 46f6263..b84e1b7 100644 --- a/src/grid.rs +++ b/src/grid.rs @@ -59,12 +59,12 @@ impl std::ops::Sub<Col> for usize { } } -#[derive(Default, Clone, Debug)] -pub struct GridRow<T: Default + Clone> { +#[derive(Default, Clone, Debug, Eq, PartialEq)] +pub struct GridRow<T: Default + Clone + Eq + PartialEq> { cells: Vec<T>, } -impl<T: Default + Clone> GridRow<T> { +impl<T: Default + Clone + Eq + PartialEq> GridRow<T> { pub fn iter(&self) -> impl Iterator<Item = &T> + Clone { self.cells.iter() } @@ -74,25 +74,29 @@ impl<T: Default + Clone> GridRow<T> { } } -impl<T: Default + Clone> std::ops::Index<Col> for GridRow<T> { +impl<T: Default + Clone + Eq + PartialEq> std::ops::Index<Col> + for GridRow<T> +{ type Output = T; fn index(&self, col: Col) -> &Self::Output { &self.cells[col.0] } } -impl<T: Default + Clone> std::ops::IndexMut<Col> for GridRow<T> { +impl<T: Default + Clone + Eq + PartialEq> std::ops::IndexMut<Col> + for GridRow<T> +{ fn index_mut(&mut self, col: Col) -> &mut Self::Output { &mut self.cells[col.0] } } -#[derive(Default, Clone, Debug)] -pub struct Grid<T: Default + Clone> { +#[derive(Default, Clone, Debug, Eq, PartialEq)] +pub struct Grid<T: Default + Clone + Eq + PartialEq> { rows: Vec<GridRow<T>>, } -impl<T: Default + Clone> Grid<T> { +impl<T: Default + Clone + Eq + PartialEq> Grid<T> { pub fn grow(&mut self, rows: Row, cols: Col) { self.rows .resize_with(rows.0.max(self.rows.len()), GridRow::default); @@ -154,7 +158,7 @@ impl<T: Default + Clone> Grid<T> { } } -impl<T: Default + Clone + std::fmt::Display> Grid<T> { +impl<T: Default + Clone + Eq + PartialEq + std::fmt::Display> Grid<T> { pub fn display_packed<F: Fn(&T) -> char>( &self, f: F, @@ -163,7 +167,9 @@ impl<T: Default + Clone + std::fmt::Display> Grid<T> { } } -impl<T: Default + Clone + std::fmt::Display> std::fmt::Display for Grid<T> { +impl<T: Default + Clone + Eq + PartialEq + std::fmt::Display> + std::fmt::Display for Grid<T> +{ fn fmt( &self, f: &mut std::fmt::Formatter<'_>, @@ -178,20 +184,22 @@ impl<T: Default + Clone + std::fmt::Display> std::fmt::Display for Grid<T> { } } -impl<T: Default + Clone> std::ops::Index<Row> for Grid<T> { +impl<T: Default + Clone + Eq + PartialEq> std::ops::Index<Row> for Grid<T> { type Output = GridRow<T>; fn index(&self, row: Row) -> &Self::Output { &self.rows[row.0] } } -impl<T: Default + Clone> std::ops::IndexMut<Row> for Grid<T> { +impl<T: Default + Clone + Eq + PartialEq> std::ops::IndexMut<Row> + for Grid<T> +{ fn index_mut(&mut self, row: Row) -> &mut Self::Output { &mut self.rows[row.0] } } -impl<T: Default + Clone> FromIterator<Vec<T>> for Grid<T> { +impl<T: Default + Clone + Eq + PartialEq> FromIterator<Vec<T>> for Grid<T> { fn from_iter<I>(iter: I) -> Self where I: IntoIterator<Item = Vec<T>>, @@ -202,7 +210,9 @@ impl<T: Default + Clone> FromIterator<Vec<T>> for Grid<T> { } } -impl<T: Default + Clone> FromIterator<((Row, Col), T)> for Grid<T> { +impl<T: Default + Clone + Eq + PartialEq> FromIterator<((Row, Col), T)> + for Grid<T> +{ fn from_iter<I>(iter: I) -> Self where I: IntoIterator<Item = ((Row, Col), T)>, @@ -218,12 +228,15 @@ impl<T: Default + Clone> FromIterator<((Row, Col), T)> for Grid<T> { pub struct DisplayPacked< 'a, - T: Default + Clone + std::fmt::Display, + T: Default + Clone + Eq + PartialEq + std::fmt::Display, F: Fn(&'a T) -> char, >(&'a Grid<T>, F); -impl<'a, T: Default + Clone + std::fmt::Display, F: Fn(&'a T) -> char> - std::fmt::Display for DisplayPacked<'a, T, F> +impl< + 'a, + T: Default + Clone + Eq + PartialEq + std::fmt::Display, + F: Fn(&'a T) -> char, + > std::fmt::Display for DisplayPacked<'a, T, F> { fn fmt( &self, diff --git a/src/parse.rs b/src/parse.rs index 903ad2f..3674a25 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -63,3 +63,21 @@ pub fn digit_grid(lines: impl Iterator<Item = String>) -> Grid<u8> { }) .collect() } + +// false positive, doing its suggestion gives borrow checker errors +#[allow(clippy::redundant_closure)] +pub fn grid<F, T>(lines: impl Iterator<Item = String>, f: F) -> Grid<T> +where + F: Fn(u8) -> T, + T: Clone + Default + Eq + PartialEq, +{ + lines + .map(|s| { + s.as_bytes() + .iter() + .copied() + .map(|b| f(b)) + .collect::<Vec<_>>() + }) + .collect() +} |