diff options
Diffstat (limited to 'CLI/rust/src')
| -rw-r--r-- | CLI/rust/src/game_of_life.rs | 11 | ||||
| -rw-r--r-- | CLI/rust/src/game_of_life/generators/input.rs | 2 | ||||
| -rw-r--r-- | CLI/rust/src/game_of_life/generators/seed.rs | 2 | ||||
| -rw-r--r-- | CLI/rust/src/game_of_life/simulation.rs | 48 | ||||
| -rw-r--r-- | CLI/rust/src/game_of_life/simulation/plane.rs | 72 | ||||
| -rw-r--r-- | CLI/rust/src/game_of_life/simulation/universe.rs | 80 | ||||
| -rw-r--r-- | CLI/rust/src/game_of_life/universe.rs | 191 |
7 files changed, 207 insertions, 199 deletions
diff --git a/CLI/rust/src/game_of_life.rs b/CLI/rust/src/game_of_life.rs index 96ec3d9..30da75d 100644 --- a/CLI/rust/src/game_of_life.rs +++ b/CLI/rust/src/game_of_life.rs @@ -3,16 +3,15 @@ use clap::{crate_authors, crate_version, App, Arg, Error}; /// Options module for validations and Opts struct -pub(crate) mod opts; -use opts::{validators, Opts}; +pub(crate) mod opts; use opts::{validators, Opts}; /// Generators Module to provide interface for generating universes /// using Seed or File input pub(crate) mod generators; -/// Universe module for running the simulation -pub(crate) mod universe; -use universe::Universe; +/// The different building blocks used in Universe simulations +pub(crate) mod simulation; +use simulation::universe::Universe; /// Define the Clap CLI App for running Game of Life simulation /// @@ -175,7 +174,7 @@ pub(crate) fn generate(opts: Opts) -> Result<Universe, Error> { mod generate { use super::*; use mocktopus::mocking::*; - use crate::game_of_life::universe::Plane; + use crate::game_of_life::simulation::plane::Plane; fn universe_mock(opts: Opts) -> Universe { Universe { diff --git a/CLI/rust/src/game_of_life/generators/input.rs b/CLI/rust/src/game_of_life/generators/input.rs index 710ac8f..cfa2784 100644 --- a/CLI/rust/src/game_of_life/generators/input.rs +++ b/CLI/rust/src/game_of_life/generators/input.rs @@ -1,5 +1,5 @@ use crate::game_of_life::opts::Opts; -use crate::game_of_life::universe::{Universe, Plane}; +use crate::game_of_life::simulation::{universe::Universe, plane::Plane}; use clap::{Error, ErrorKind}; use curl::easy::Easy; use regex::Regex; diff --git a/CLI/rust/src/game_of_life/generators/seed.rs b/CLI/rust/src/game_of_life/generators/seed.rs index d280eff..41c8f5d 100644 --- a/CLI/rust/src/game_of_life/generators/seed.rs +++ b/CLI/rust/src/game_of_life/generators/seed.rs @@ -1,5 +1,5 @@ use crate::game_of_life::opts::Opts; -use crate::game_of_life::universe::Universe; +use crate::game_of_life::simulation::universe::Universe; use clap::Error; #[cfg(test)] diff --git a/CLI/rust/src/game_of_life/simulation.rs b/CLI/rust/src/game_of_life/simulation.rs new file mode 100644 index 0000000..bac44a0 --- /dev/null +++ b/CLI/rust/src/game_of_life/simulation.rs @@ -0,0 +1,48 @@ +/// Implement memeory safe indexing (circular indexing) +/// +/// When the index is out of bound (being negative or out of bound), the index +/// will try to fetch the item from the other end of the vector as if it's a +/// cylinder or circular array +fn circular_index(mut idx: isize, length: isize) -> usize { + while idx.is_negative() { + idx += length; + } + (idx % length) as usize +} + +#[cfg(test)] +mod circular_index { + use super::*; + + #[test] + fn negative_index() { + assert_eq!(circular_index(-1, 3), 2); + assert_eq!(circular_index(-2, 3), 1); + assert_eq!(circular_index(-3, 3), 0); + assert_eq!(circular_index(-4, 3), 2); + assert_eq!(circular_index(-5, 3), 1); + assert_eq!(circular_index(-6, 3), 0); + assert_eq!(circular_index(-7, 3), 2); + assert_eq!(circular_index(-8, 3), 1); + assert_eq!(circular_index(-9, 3), 0); + } + + #[test] + fn positve_index() { + assert_eq!(circular_index(0, 3), 0); + assert_eq!(circular_index(1, 3), 1); + assert_eq!(circular_index(2, 3), 2); + assert_eq!(circular_index(3, 3), 0); + assert_eq!(circular_index(4, 3), 1); + assert_eq!(circular_index(5, 3), 2); + assert_eq!(circular_index(6, 3), 0); + assert_eq!(circular_index(7, 3), 1); + assert_eq!(circular_index(8, 3), 2); + } +} + +/// Circular Plane used in Universe traversing +pub(crate) mod plane; + +/// Universe object used for simulation +pub(crate) mod universe; diff --git a/CLI/rust/src/game_of_life/simulation/plane.rs b/CLI/rust/src/game_of_life/simulation/plane.rs new file mode 100644 index 0000000..10acd43 --- /dev/null +++ b/CLI/rust/src/game_of_life/simulation/plane.rs @@ -0,0 +1,72 @@ +use std::ops::{Index, IndexMut}; +use super::circular_index; + +/// Game of Life universe building blocks (a plane is a circular Vec) +/// +/// This is used internally in the implementation of the Universe to allow +/// more readable and safer traversing of the universe blocks +#[derive(Debug, Clone, PartialEq)] +pub(crate) struct Plane(pub Vec<bool>); + +impl Index<isize> for Plane { + type Output = bool; + fn index(&self, idx: isize) -> &bool { + let len = self.0.len() as isize; + &self.0[circular_index(idx, len)] + } +} + +impl IndexMut<isize> for Plane { + fn index_mut(&mut self, idx: isize) -> &mut Self::Output { + let len = self.0.len() as isize; + &mut self.0[circular_index(idx, len)] + } +} + +#[cfg(test)] +mod plane { + use super::*; + + mod index { + use super::*; + + #[test] + fn get_element() { + let p = Plane(vec![false, false, true, false, false]); + assert_eq!(p[0], false); + assert_eq!(p[1], false); + assert_eq!(p[3], false); + assert_eq!(p[4], false); + + assert_eq!(p[-3], true); + assert_eq!(p[2], true); + assert_eq!(p[7], true); + } + } + + #[cfg(test)] + mod index_mut { + use super::*; + + #[test] + fn set_negative_index_element() { + let mut p = Plane(vec![false, false, false, false, false]); + p[-3] = true; + assert_eq!(p, Plane(vec![false, false, true, false, false])); + } + + #[test] + fn set_element() { + let mut p = Plane(vec![false, false, false, false, false]); + p[2] = true; + assert_eq!(p, Plane(vec![false, false, true, false, false])); + } + + #[test] + fn set_out_of_bound_element() { + let mut p = Plane(vec![false, false, false, false, false]); + p[7] = true; + assert_eq!(p, Plane(vec![false, false, true, false, false])); + } + } +} diff --git a/CLI/rust/src/game_of_life/simulation/universe.rs b/CLI/rust/src/game_of_life/simulation/universe.rs new file mode 100644 index 0000000..5e5a921 --- /dev/null +++ b/CLI/rust/src/game_of_life/simulation/universe.rs @@ -0,0 +1,80 @@ +use crate::game_of_life::opts::Opts; +use crate::game_of_life::simulation::plane::Plane; +use std::ops::Index; +use super::circular_index; + + +/// Game of Life universe struct for running simulations +#[derive(Debug, Clone, PartialEq)] +pub(crate) struct Universe { + pub opts: Opts, + pub current: Vec<Plane>, + pub future: Vec<Plane>, +} + +impl Index<isize> for Universe +{ + type Output = Plane; + fn index(&self, idx: isize) -> &Plane { + let len = self.current.len() as isize; + &self.current[circular_index(idx, len)] + } +} + +#[cfg(test)] +mod universe { + use super::*; + + mod index { + use super::*; + + #[test] + fn get_element() { + let opts = Opts { + seed: 1337, + input: None, + width: 13, + height: 13, + live_cell: 'L', + dead_cell: 'D', + delay: 13, + }; + let u = Universe { + opts, + current: vec![ + Plane(vec![false; 5]), + Plane(vec![false, false, true, false, false]), + Plane(vec![false; 5]), + ], + future: vec![Plane(vec![])], + }; + + assert_eq!(u[-3][0], false); + assert_eq!(u[-3][1], false); + assert_eq!(u[-3][3], false); + assert_eq!(u[-3][4], false); + assert_eq!(u[0][0], false); + assert_eq!(u[0][1], false); + assert_eq!(u[0][3], false); + assert_eq!(u[0][4], false); + assert_eq!(u[2][0], false); + assert_eq!(u[2][1], false); + assert_eq!(u[2][3], false); + assert_eq!(u[2][4], false); + assert_eq!(u[5][0], false); + assert_eq!(u[5][1], false); + assert_eq!(u[5][3], false); + assert_eq!(u[5][4], false); + + assert_eq!(u[-2][-3], true); + assert_eq!(u[-2][2], true); + assert_eq!(u[-2][7], true); + assert_eq!(u[1][-3], true); + assert_eq!(u[1][2], true); + assert_eq!(u[1][7], true); + assert_eq!(u[4][-3], true); + assert_eq!(u[4][2], true); + assert_eq!(u[4][7], true); + } + } +} diff --git a/CLI/rust/src/game_of_life/universe.rs b/CLI/rust/src/game_of_life/universe.rs deleted file mode 100644 index 11912fd..0000000 --- a/CLI/rust/src/game_of_life/universe.rs +++ /dev/null @@ -1,191 +0,0 @@ -use crate::game_of_life::opts::Opts; -use std::ops::{Index, IndexMut}; - -/// Implement memeory safe indexing (circular indexing) -/// -/// When the index is out of bound (being negative or out of bound), the index -/// will try to fetch the item from the other end of the vector as if it's a -/// cylinder or circular array -fn circular_index(mut idx: isize, length: isize) -> usize { - while idx.is_negative() { - idx += length; - } - (idx % length) as usize -} - -#[cfg(test)] -mod circular_index { - use super::*; - - #[test] - fn negative_index() { - assert_eq!(circular_index(-1, 3), 2); - assert_eq!(circular_index(-2, 3), 1); - assert_eq!(circular_index(-3, 3), 0); - assert_eq!(circular_index(-4, 3), 2); - assert_eq!(circular_index(-5, 3), 1); - assert_eq!(circular_index(-6, 3), 0); - assert_eq!(circular_index(-7, 3), 2); - assert_eq!(circular_index(-8, 3), 1); - assert_eq!(circular_index(-9, 3), 0); - } - - #[test] - fn positve_index() { - assert_eq!(circular_index(0, 3), 0); - assert_eq!(circular_index(1, 3), 1); - assert_eq!(circular_index(2, 3), 2); - assert_eq!(circular_index(3, 3), 0); - assert_eq!(circular_index(4, 3), 1); - assert_eq!(circular_index(5, 3), 2); - assert_eq!(circular_index(6, 3), 0); - assert_eq!(circular_index(7, 3), 1); - assert_eq!(circular_index(8, 3), 2); - } -} - -/// Game of Life universe building blocks (a plane is a circular Vec) -/// -/// This is used internally in the implementation of the Universe to allow -/// more readable and safer traversing of the universe blocks -#[derive(Debug, Clone, PartialEq)] -pub(crate) struct Plane(pub Vec<bool>); - -impl Index<isize> for Plane { - type Output = bool; - fn index(&self, idx: isize) -> &bool { - let len = self.0.len() as isize; - &self.0[circular_index(idx, len)] - } -} - -impl IndexMut<isize> for Plane { - fn index_mut(&mut self, idx: isize) -> &mut Self::Output { - let len = self.0.len() as isize; - &mut self.0[circular_index(idx, len)] - } -} - -#[cfg(test)] -mod plane { - use super::*; - - mod index { - use super::*; - - #[test] - fn get_element() { - let p = Plane(vec![false, false, true, false, false]); - assert_eq!(p[0], false); - assert_eq!(p[1], false); - assert_eq!(p[3], false); - assert_eq!(p[4], false); - - assert_eq!(p[-3], true); - assert_eq!(p[2], true); - assert_eq!(p[7], true); - } - } - - #[cfg(test)] - mod index_mut { - use super::*; - - #[test] - fn set_negative_index_element() { - let mut p = Plane(vec![false, false, false, false, false]); - p[-3] = true; - assert_eq!(p, Plane(vec![false, false, true, false, false])); - } - - #[test] - fn set_element() { - let mut p = Plane(vec![false, false, false, false, false]); - p[2] = true; - assert_eq!(p, Plane(vec![false, false, true, false, false])); - } - - #[test] - fn set_out_of_bound_element() { - let mut p = Plane(vec![false, false, false, false, false]); - p[7] = true; - assert_eq!(p, Plane(vec![false, false, true, false, false])); - } - } -} - - -/// Game of Life universe struct for running simulations -#[derive(Debug, Clone, PartialEq)] -pub(crate) struct Universe { - pub opts: Opts, - pub current: Vec<Plane>, - pub future: Vec<Plane>, -} - -impl Index<isize> for Universe -{ - type Output = Plane; - fn index(&self, idx: isize) -> &Plane { - let len = self.current.len() as isize; - &self.current[circular_index(idx, len)] - } -} - -#[cfg(test)] -mod universe { - use super::*; - - mod index { - use super::*; - - #[test] - fn get_element() { - let opts = Opts { - seed: 1337, - input: None, - width: 13, - height: 13, - live_cell: 'L', - dead_cell: 'D', - delay: 13, - }; - let u = Universe { - opts, - current: vec![ - Plane(vec![false; 5]), - Plane(vec![false, false, true, false, false]), - Plane(vec![false; 5]), - ], - future: vec![Plane(vec![])], - }; - - assert_eq!(u[-3][0], false); - assert_eq!(u[-3][1], false); - assert_eq!(u[-3][3], false); - assert_eq!(u[-3][4], false); - assert_eq!(u[0][0], false); - assert_eq!(u[0][1], false); - assert_eq!(u[0][3], false); - assert_eq!(u[0][4], false); - assert_eq!(u[2][0], false); - assert_eq!(u[2][1], false); - assert_eq!(u[2][3], false); - assert_eq!(u[2][4], false); - assert_eq!(u[5][0], false); - assert_eq!(u[5][1], false); - assert_eq!(u[5][3], false); - assert_eq!(u[5][4], false); - - assert_eq!(u[-2][-3], true); - assert_eq!(u[-2][2], true); - assert_eq!(u[-2][7], true); - assert_eq!(u[1][-3], true); - assert_eq!(u[1][2], true); - assert_eq!(u[1][7], true); - assert_eq!(u[4][-3], true); - assert_eq!(u[4][2], true); - assert_eq!(u[4][7], true); - } - } -} |
