1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
use crate::game_of_life::opts::Opts;
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;
/// Generate a new Universe/Board from a seed number
///
/// 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> {
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]),
]),
}
)
}
}
|