Lots of code in this one, TIL about creating my generative iterators in Rust. Made me feel smart :). Boring parsing code is redacted. Full stuff on: github.com/benwtrent/advent-of-cod...
struct CoordinateDirection<'a> { coordinates: (usize, usize), direction: (i8, i8), maximum: &'a (usize, usize), } impl Iterator for CoordinateDirection<'_> { type Item = (usize, usize); fn next(&mut self) -> Option<(usize, usize)> { if (self.direction.0 < 0 && self.coordinates.0 == 0) || (self.direction.0 > 0 && self.coordinates.0 >= self.maximum.0) || (self.direction.1 < 0 && self.coordinates.1 == 0) || (self.direction.1 > 0 && self.coordinates.1 >= self.maximum.1) { return None; } self.coordinates = ( (self.coordinates.0 as i8 + self.direction.0) as usize, (self.coordinates.1 as i8 + self.direction.1) as usize, ); Some(self.coordinates) } } fn all_coordinate_generators<'a>( seat: &'a Seat, maximum: &'a (usize, usize), ) -> Vec<CoordinateDirection<'a>> { let iterator_generator = |(dx, dy)| CoordinateDirection { coordinates: seat.coordinates.clone(), maximum: &maximum, direction: (dx, dy), }; vec![ iterator_generator((1, 0)), iterator_generator((1, 1)), iterator_generator((1, -1)), iterator_generator((-1, 0)), iterator_generator((-1, 1)), iterator_generator((-1, -1)), iterator_generator((0, 1)), iterator_generator((0, -1)), ] } fn new_state(seat: &Seat, arrangement: &Vec<Vec<Seat>>) -> Seat { if seat.state == State::Floor { return seat.clone(); } let maximum = (arrangement[0].len() - 1, arrangement.len() - 1); let mut visual_iters = all_coordinate_generators(seat, &maximum); let mut occupied_count = 0; for coor_iter in visual_iters.iter_mut() { if let Some((x, y)) = coor_iter.next() { if arrangement[y][x].state == State::Occupied { occupied_count += 1; } } } let state = if occupied_count >= 4 && seat.state == State::Occupied { State::Unoccupied } else if occupied_count == 0 && seat.state == State::Unoccupied { State::Occupied } else { seat.state.clone() }; Seat { coordinates: seat.coordinates.clone(), state, } } fn new_state_visually(seat: &Seat, arrangement: &Vec<Vec<Seat>>) -> Seat { if seat.state == State::Floor { return seat.clone(); } let maximum = (arrangement[0].len() - 1, arrangement.len() - 1); let mut visual_iters = all_coordinate_generators(seat, &maximum); let mut occupied_count = 0; for coor_iter in visual_iters.iter_mut() { if let Some((x, y)) = coor_iter .skip_while(|(x, y)| arrangement[*y][*x].state == State::Floor) .next() { if arrangement[y][x].state == State::Occupied { occupied_count += 1; } } } let state = if occupied_count > 4 && seat.state == State::Occupied { State::Unoccupied } else if occupied_count == 0 && seat.state == State::Unoccupied { State::Occupied } else { seat.state.clone() }; Seat { coordinates: seat.coordinates.clone(), state, } } fn reach_stability_count( input: &Vec<Vec<Seat>>, state_check: &dyn Fn(&Seat, &Vec<Vec<Seat>>) -> Seat, ) -> usize { let mut old_arrangement = input.clone(); loop { let mut new_arrangement = vec![]; for row in old_arrangement.iter() { let mut new_row = vec![]; for seat in row.iter() { new_row.push(state_check(&seat, &old_arrangement)); } new_arrangement.push(new_row); } if new_arrangement == old_arrangement { break; } old_arrangement = new_arrangement; } old_arrangement .iter() .flat_map(|v| v) .filter(|s| (*s).state == State::Occupied) .count() }
Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink.
Hide child comments as well
Confirm
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
Lots of code in this one, TIL about creating my generative iterators in Rust. Made me feel smart :). Boring parsing code is redacted. Full stuff on: github.com/benwtrent/advent-of-cod...