use std::fs; use std::path::Path; #[derive(PartialEq)] enum SeaCucumber { East, South, Empty } impl From for SeaCucumber { fn from(c: char) -> Self { match c { '>' => Self::East, 'v' => Self::South, '.' => Self::Empty, _ => unreachable!() } } } struct Field { steps: usize, field: Vec> } impl From<&str> for Field { fn from(s: &str) -> Self { let field = s.lines().map(|l| l.chars().map(|c| SeaCucumber::from(c)).collect::>()).collect(); Self::new(field) } } impl Field { fn new(field: Vec>) -> Self { Self { steps: 0, field } } fn step_east(&mut self) -> bool { let mut updated = false; for y in 0..self.field.len() { let len = self.field[y].len(); let to_update = (0..len).filter(|&x| { let n = (x + 1) % len; self.field[y][x] == SeaCucumber::East && self.field[y][n] == SeaCucumber::Empty }).collect::>(); to_update.iter().for_each(|&x| { let n = (x + 1) % len; self.field[y][x] = SeaCucumber::Empty; self.field[y][n] = SeaCucumber::East; }); updated |= to_update.len() > 0; } updated } fn step_south(&mut self) -> bool { let mut updated = false; let len = self.field.len(); for x in 0..self.field[0].len() { let to_update = (0..len).filter(|&y| { let n = (y + 1) % len; self.field[y][x] == SeaCucumber::South && self.field[n][x] == SeaCucumber::Empty }).collect::>(); to_update.iter().for_each(|&y| { let n = (y + 1) % len; self.field[y][x] = SeaCucumber::Empty; self.field[n][x] = SeaCucumber::South; }); updated |= to_update.len() > 0; } updated } fn step(&mut self) -> bool { self.steps += 1; let east = self.step_east(); let south = self.step_south(); east || south } fn evolve(&mut self) -> usize { while self.step() { } self.steps } } /* AOC21 Day 25: https://adventofcode.com/2021/day/25 */ fn main() { let input = Path::new("resources").join("input.txt"); let content = fs::read_to_string(input).expect("Unable to read input file"); let mut field = Field::from(&content[..]); println!("The result is {}", field.evolve()); } #[cfg(test)] mod tests { use super::*; const INPUT: &str = "v...>>.vv> .vv>>.vv.. >>.>v>...v >>v>>.>.v. v>v.vv.v.. >.>>..v... .vv..>.>v. v.v..>>v.v ....v..v.>"; #[test] fn example() { let mut field = Field::from(INPUT); assert_eq!(58, field.evolve()); } }