diff --git a/src/main.rs b/src/main.rs index 038a460..fe03964 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,25 @@ -use std::{fmt::Display, future::Future, ops::Index, time::Duration}; +use std::{ + fmt::Display, + future::Future, + ops::{Index, IndexMut}, + time::Duration, +}; use rand::Rng; use tokio::{signal, time}; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] struct State([bool; 8]); +impl State { + fn rule_iterator(&self, rule: u8) -> impl Iterator { + StateIterator { + rule: rule, + state: *self, + } + } +} + impl Index for State { type Output = bool; @@ -14,17 +28,35 @@ impl Index for State { } } -fn map_state(rule: u8, state: &State) -> State { - let mut new_state: [bool; 8] = [false; 8]; - - for i in 0..8 { - let pattern = ((i != 0 && state[i - 1]) as u8 * 4) - | (state[i] as u8 * 2) - | ((i != 7 && state[i + 1]) as u8); - new_state[i] = (rule >> pattern & 1) == 1; +impl IndexMut for State { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + &mut self.0[index] } +} - State(new_state) +struct StateIterator { + rule: u8, + state: State, +} + +impl Iterator for StateIterator { + type Item = State; + + fn next(&mut self) -> Option { + let old_state = self.state; + let mut new_state = State::default(); + + for i in 0..8 { + let pattern = ((i != 0 && self.state[i - 1]) as u8 * 4) + | (self.state[i] as u8 * 2) + | ((i != 7 && self.state[i + 1]) as u8); + new_state[i] = (self.rule >> pattern & 1) == 1; + } + + self.state = new_state; + + Some(old_state) + } } impl Display for State { @@ -72,14 +104,11 @@ fn send_status( fn generate(seed: u16) -> String { let rule: u8 = (seed & 0xff) as u8; - let init_state = ((seed >> 8 & 0xff) as u8).into(); - - (0..8) - .scan(init_state, |state, _i| { - let old_state = *state; - *state = map_state(rule, state); - Some(old_state) - }) + let init_state: State = ((seed >> 8 & 0xff) as u8).into(); + + init_state + .rule_iterator(rule) + .take(8) .map(|state| state.to_string()) .collect::>() .join("\n")