cell_automata_1d/
cellauto.rs

1use crate::rule::*;
2
3pub struct CellAutomata1D {
4    state: Vec<bool>,
5    rule: Rule
6}
7
8impl CellAutomata1D {
9    pub fn new(init_state: &str, rule_num: u8) -> Self {
10        CellAutomata1D { 
11            state: Self::str_state_to_vec(init_state), 
12            rule: Rule::new(rule_num) 
13        }
14    }
15
16    pub fn with_rule(rule_num: u8) -> Self {
17        CellAutomata1D { 
18            state: Vec::new(), 
19            rule: Rule::new(rule_num) 
20        }
21    }
22
23    pub fn set_state(&mut self, state: &str) {
24        self.state = Self::str_state_to_vec(state);
25    }
26
27    pub fn set_rule(&mut self, number: u8) {
28        self.rule = Rule::new(number);
29    }
30
31    pub fn next(&mut self) {
32        let mut next_state: Vec<bool> = Vec::with_capacity(self.state.len());
33        next_state.resize(self.state.len(), false);
34        for i in 0..self.state.len() {
35            let triad = self.triad_for(i);
36            next_state[i] = self.rule.result_of(triad);
37        }
38        self.state = next_state;
39    }
40
41    pub fn string_state(&self) -> String {
42        let mut state_str = String::with_capacity(self.state.len());
43        for cell in self.state.iter() {
44            state_str.push(if *cell {'#'} else {' '});
45        }
46        state_str
47    }
48
49    pub fn get_state(&self) -> Vec<bool> {
50        self.state.clone()
51    }
52
53    fn triad_for(&self, ind: usize) -> [bool; 3] {
54        let ind = ind as isize;
55        let mut triad = [false; 3];
56        let mut bit_ind = 0;
57        for i in ind-1..=ind+1 {
58            triad[bit_ind] = self.cycle_at(i);
59            bit_ind += 1;
60        }
61        triad
62    }
63
64    fn cycle_at(&self, ind: isize) -> bool {
65        if ind >= self.state.len() as isize {
66            self.state[0]
67        } else if ind < 0 {
68            *self.state.last().unwrap()
69        } else {
70            self.state[ind as usize]
71        }
72    }
73
74    fn str_state_to_vec(str: &str) -> Vec<bool> {
75        let mut vec: Vec<bool> = Vec::with_capacity(str.len());
76        for ch in str.chars() {
77            vec.push(if ch != '0' {true} else {false});
78        }
79        vec
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use crate::cellauto::*;
86
87    #[test]
88    fn automata_work() {
89        let mut automata = CellAutomata1D::new("00001001", 2);
90        automata.next();
91        assert_eq!(automata.string_state(), "   #  # ");
92        automata.next();
93        assert_eq!(automata.string_state(), "  #  #  ");
94    }
95
96    #[test]
97    fn setting_state_works() {
98        let mut automata = CellAutomata1D::new("00001001", 2);
99        automata.next();
100        assert_eq!(automata.string_state(), "   #  # ");
101        automata.set_state("10000100");
102        automata.next();
103        assert_eq!(automata.string_state(), "    #  #");
104
105        let mut automata = CellAutomata1D::with_rule(18);
106        automata.set_state("00010000");
107        automata.next();
108        assert_eq!(automata.string_state(), "  # #   ");
109    }
110
111    #[test]
112    fn printing_state() {
113        let automata = CellAutomata1D::new("11100101", 0b00000100);
114        assert_eq!(automata.string_state(), "###  # #");
115    }
116
117    #[test]
118    fn triad_creating() {
119        let automata = CellAutomata1D::new("10000101", 0xff);
120        assert_eq!(automata.triad_for(0), [true, true, false]);
121        assert_eq!(automata.triad_for(7), [false, true, true]);
122        assert_eq!(automata.triad_for(4), [false, false, true]);
123    }
124
125    #[test]
126    fn cycle_state_indexing() {
127        let automata = CellAutomata1D::new("00000101", 0xff);
128        assert_eq!(automata.cycle_at(-1), true);
129        assert_eq!(automata.cycle_at(8), false);
130        assert_eq!(automata.cycle_at(5), true);
131        assert_eq!(automata.cycle_at(4), false);
132    }
133
134    #[test]
135    fn reading_state_from_str() {
136        let readed = CellAutomata1D::str_state_to_vec("11100101");
137        assert_eq!(readed, vec![true, true, true, false, false, true, false, true]);
138    }
139}