ca_rules/rules/
neumann.rs

1//! Totalistic rules with von Neumann neighborhood.
2
3use super::Gen;
4use crate::ParseRuleError;
5
6rule_struct!(Neumann);
7
8impl Neumann {
9    parse_bs!(4);
10    parse_rule!('V');
11}
12
13/// A trait for parsing totalistic rules with
14/// [von Neumann neighborhood](http://www.conwaylife.com/wiki/Von_Neumann_neighbourhood).
15///
16/// The `b` / `s` data of this type of rules consists of numbers of live neighbors
17/// that cause a cell to be born / survive.
18///
19/// # Examples
20///
21/// ```
22/// use ca_rules::ParseNeumann;
23///
24/// #[derive(Debug, Eq, PartialEq)]
25/// struct Rule {
26///     b: Vec<u8>,
27///     s: Vec<u8>,
28/// }
29///
30/// impl ParseNeumann for Rule {
31///     fn from_bs(b: Vec<u8>, s: Vec<u8>) -> Self {
32///         Rule { b, s }
33///     }
34/// }
35///
36/// let life = Rule::parse_rule("B2/S013V").unwrap();
37///
38/// assert_eq!(
39///     life,
40///     Rule {
41///         b: vec![2],
42///         s: vec![0, 1, 3],
43///     }
44/// )
45/// ```
46pub trait ParseNeumann {
47    /// Construct the rule from `b` / `s` data.
48    fn from_bs(b: Vec<u8>, s: Vec<u8>) -> Self;
49
50    /// The parser.
51    fn parse_rule(input: &str) -> Result<Self, ParseRuleError>
52    where
53        Self: Sized,
54    {
55        let Neumann { b, s } = Neumann::parse_rule(input)?;
56        Ok(Self::from_bs(b, s))
57    }
58}
59
60/// A trait for parsing totalistic [Generations](http://www.conwaylife.com/wiki/Generations) rules
61/// with [von Neumann neighborhood](http://www.conwaylife.com/wiki/Von_Neumann_neighbourhood).
62///
63/// The `b` / `s` data of this type of rules consists of numbers of live neighbors
64/// that cause a cell to be born / survive.
65///
66/// # Examples
67///
68/// ```
69/// use ca_rules::ParseNeumannGen;
70///
71/// #[derive(Debug, Eq, PartialEq)]
72/// struct Rule {
73///     b: Vec<u8>,
74///     s: Vec<u8>,
75///     gen: usize,
76/// }
77///
78/// impl ParseNeumannGen for Rule {
79///     fn from_bsg(b: Vec<u8>, s: Vec<u8>, gen: usize) -> Self {
80///         Rule { b, s, gen }
81///     }
82/// }
83///
84/// let life = Rule::parse_rule("B2/S013/3V").unwrap();
85///
86/// assert_eq!(
87///     life,
88///     Rule {
89///         b: vec![2],
90///         s: vec![0, 1, 3],
91///         gen: 3,
92///     }
93/// )
94/// ```
95pub trait ParseNeumannGen {
96    /// Construct the rule from `b` / `s` data and the number of states.
97    fn from_bsg(b: Vec<u8>, s: Vec<u8>, gen: usize) -> Self;
98
99    /// The parser.
100    fn parse_rule(input: &str) -> Result<Self, ParseRuleError>
101    where
102        Self: Sized,
103    {
104        let Gen {
105            rule: Neumann { b, s },
106            gen,
107        } = Neumann::parse_rule_gen(input)?;
108        Ok(Self::from_bsg(b, s, gen))
109    }
110}
111
112#[cfg(test)]
113mod tests {
114    use super::*;
115
116    struct Rule;
117
118    impl ParseNeumann for Rule {
119        fn from_bs(_b: Vec<u8>, _s: Vec<u8>) -> Self {
120            Rule
121        }
122    }
123
124    #[test]
125    fn valid_rules() -> Result<(), ParseRuleError> {
126        Rule::parse_rule("B3/S23V")?;
127        Rule::parse_rule("B3S23V")?;
128        Rule::parse_rule("b3s23v")?;
129        Rule::parse_rule("23/3V")?;
130        Rule::parse_rule("23/v")?;
131        Ok(())
132    }
133
134    #[test]
135    fn invalid_rules() {
136        assert_eq!(
137            Rule::parse_rule("B3/S23va").err(),
138            Some(ParseRuleError::ExtraJunk)
139        );
140        assert_eq!(
141            Rule::parse_rule("B3V/S23").err(),
142            Some(ParseRuleError::Missing('S'))
143        );
144        assert_eq!(
145            Rule::parse_rule("B3/S23").err(),
146            Some(ParseRuleError::Missing('V'))
147        );
148        assert_eq!(
149            Rule::parse_rule("B3/S25V").err(),
150            Some(ParseRuleError::Missing('V'))
151        );
152        assert_eq!(
153            Rule::parse_rule("233v").err(),
154            Some(ParseRuleError::Missing('/'))
155        );
156    }
157}