1#![deny(missing_docs, unsafe_code, unused_extern_crates, warnings)]
4
5use std::default::Default;
6use std::fmt;
7
8#[derive(Debug)]
10pub enum Data {
11 None,
13 Good(Position, u8)
15}
16
17#[derive(Debug)]
19pub enum Position {
20 Good,
22 Bad
24}
25
26#[derive(Debug)]
28pub struct Values(Vec<Value>);
29
30#[derive(Debug, Copy, Clone, PartialEq)]
32pub struct Value(u8, u8, u8);
33
34impl Default for Values {
35 fn default () -> Self {
36 let mut values: Vec<Value> = Vec::with_capacity(10 * 10 * 10);
37
38 for x in 0..10 {
39 for y in 0..10 {
40 for z in 0..10 {
41 values.push(Value(x, y, z))
42 }
43 }
44 }
45
46 Values(values)
47 }
48}
49
50impl Value {
51 pub fn has_some (&self, number: u8) -> bool {
53 self.0 == number || self.1 == number || self.2 == number
54 }
55
56 pub fn occurences(&self, position: &Position, numbers: Value) -> u8 {
58 let &Value(a, b, c) = self;
59 let Value(x, y, z) = numbers;
60
61 match position {
62 &Position::Good => {
63 vec![a == x, b == y, c == z].iter().filter(|&b| *b).count() as u8
64 },
65 &Position::Bad => {
66 vec![a == y || a == z, b == x || b == z || c == x || c == y].iter()
67 .filter(|&b| *b).count() as u8
68 }
69 }
70 }
71}
72
73impl Values {
74 pub fn apply (self, numbers: Value, data: Data) -> Self {
76 let Value(x, y, z) = numbers;
77 let Values(values) = self;
78
79 match data {
80 Data::None => {
81 let values: Vec<Value> = values.into_iter()
82 .filter(|&value| !(value.has_some(x) || value.has_some(y) || value.has_some(z)))
83 .collect();
84
85 Values(values)
86 },
87 Data::Good(position, number) => {
88 let values = values.into_iter()
89 .filter(|&value| value.occurences(&position, numbers) == number)
90 .collect();
91
92 Values(values)
93 }
94 }
95 }
96}
97
98impl fmt::Display for Value {
99 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
100 write!(f, "{}{}{}", self.0, self.1, self.2)
101 }
102}
103
104impl fmt::Display for Values {
105 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
106 write!(f, "The following values correspond to your criteria: {}",
107 self.0.iter()
108 .fold(String::new(), |acc, &value| format!("{}{} ", acc, value)))
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[test]
117 fn it_works() {
118 let values = Values::default()
119 .apply(Value(9,4,2), Data::None)
120 .apply(Value(0,8,4), Data::Good(Position::Good, 1))
121 .apply(Value(4,7,9), Data::Good(Position::Bad, 1))
122 .apply(Value(8,3,7), Data::Good(Position::Bad, 2))
123 .apply(Value(2,6,0), Data::Good(Position::Bad, 1));
124
125 println!("{}", values);
126 assert!(values.0[0] == Value(7, 8, 6))
127 }
128}