diff options
Diffstat (limited to 'CLI/rust/src/game_of_life/generators/seed.rs')
| -rw-r--r-- | CLI/rust/src/game_of_life/generators/seed.rs | 114 |
1 files changed, 111 insertions, 3 deletions
diff --git a/CLI/rust/src/game_of_life/generators/seed.rs b/CLI/rust/src/game_of_life/generators/seed.rs index 41c8f5d..e3e3f12 100644 --- a/CLI/rust/src/game_of_life/generators/seed.rs +++ b/CLI/rust/src/game_of_life/generators/seed.rs @@ -1,6 +1,9 @@ use crate::game_of_life::opts::Opts; -use crate::game_of_life::simulation::universe::Universe; +use crate::game_of_life::simulation::{plane::Plane, universe::Universe}; use clap::Error; +use rand::rngs::StdRng; +use rand::{Rng, SeedableRng}; +use rand_distr::{Distribution, Uniform}; #[cfg(test)] use mocktopus::macros::mockable; @@ -10,6 +13,111 @@ use mocktopus::macros::mockable; /// The generation of the seed should be stable across different machines /// using the same language package, version, width and height. #[cfg_attr(test, mockable)] -pub(crate) fn new(_opts: Opts) -> Result<Universe, Error> { - unimplemented!() +pub(crate) fn new(opts: Opts) -> Result<Universe, Error> { + let range = generator(opts.seed); + Ok(populate(opts, range)) +} + +/// Create a StdRng using Uniform distribution for generating same data from +/// the same seed +fn generator(seed: usize) -> StdRng { + let mut range = StdRng::seed_from_u64(seed as u64); + Uniform::new_inclusive(0, 1).sample(&mut range); + range +} + +#[cfg(test)] +mod generator { + use super::*; + + #[test] + fn seed_1337() { + let mut rng = generator(1337); + assert_eq!(rng.gen::<bool>(), true); + assert_eq!(rng.gen::<bool>(), false); + assert_eq!(rng.gen::<bool>(), true); + assert_eq!(rng.gen::<bool>(), true); + assert_eq!(rng.gen::<bool>(), false); + } + + #[test] + fn seed_42() { + let mut rng = generator(42); + assert_eq!(rng.gen::<bool>(), true); + assert_eq!(rng.gen::<bool>(), false); + assert_eq!(rng.gen::<bool>(), true); + assert_eq!(rng.gen::<bool>(), true); + assert_eq!(rng.gen::<bool>(), true); + } +} + +/// Return a universe struct with populated data from the seedable range +fn populate(opts: Opts, mut range: StdRng) -> Universe { + let (width, height) = (opts.width as usize, opts.height as usize); + let mut current = Plane(vec![Plane(vec![false; width]); height]); + for i in 0..height { + for j in 0..width { + current[i as isize][j as isize] = range.gen() + } + } + Universe { + opts, + current, + future: Plane(vec![Plane(vec![false; width]); height]), + } +} + +#[cfg(test)] +mod populate { + use super::*; + + fn opts(seed: usize) -> Opts { + Opts { + seed, + input: None, + width: 5, + height: 3, + live_cell: 'L', + dead_cell: 'D', + delay: 13, + } + } + + #[test] + fn seed_1337() { + let rng = generator(1337); + let opts = opts(1337); + let universe = populate(opts.clone(), rng); + assert_eq!( + universe, + Universe { + opts, + future: Plane(vec![Plane(vec![false; 5]); 3]), + current: Plane(vec![ + Plane(vec![true, false, true, true, false]), + Plane(vec![true, false, true, false, true]), + Plane(vec![false, false, true, true, true]), + ]), + } + ) + } + + #[test] + fn seed_42() { + let rng = generator(42); + let opts = opts(42); + let universe = populate(opts.clone(), rng); + assert_eq!( + universe, + Universe { + opts, + future: Plane(vec![Plane(vec![false; 5]); 3]), + current: Plane(vec![ + Plane(vec![true, false, true, true, true]), + Plane(vec![true, false, true, false, true]), + Plane(vec![false, false, true, false, true]), + ]), + } + ) + } } |
