fast_tak/
colors.rs

1use takparse::Color;
2
3type BitVec = u64;
4
5#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
6pub struct Colors {
7    bits: BitVec,
8}
9
10impl Default for Colors {
11    fn default() -> Self {
12        Self { bits: 1 }
13    }
14}
15
16impl Colors {
17    #[inline]
18    #[must_use] 
19    pub const fn of_one(color: Color) -> Self {
20        Self {
21            bits: 0b10 + from_color(color),
22        }
23    }
24
25    #[inline]
26    #[must_use] 
27    pub const fn is_empty(self) -> bool {
28        self.bits == 1
29    }
30
31    #[inline]
32    #[must_use] 
33    pub const fn len(self) -> u32 {
34        BitVec::BITS - (self.bits.leading_zeros() + 1)
35    }
36
37    #[inline]
38    #[must_use] 
39    pub const fn top(self) -> Option<Color> {
40        if self.is_empty() {
41            return None;
42        }
43        Some(to_color(self.bits & 1))
44    }
45
46    #[inline]
47    pub fn push(&mut self, color: Color) {
48        self.bits = (self.bits << 1) | BitVec::from(color == Color::White);
49    }
50
51    #[inline]
52    pub fn pop(&mut self) -> Option<Color> {
53        if self.is_empty() {
54            return None;
55        }
56        let color = to_color(self.bits & 1);
57        self.bits >>= 1;
58        Some(color)
59    }
60
61    #[inline]
62    pub fn take(&mut self, amount: u32) -> Option<Self> {
63        if amount > self.len() {
64            return None;
65        }
66        let mask: BitVec = !(!0 << amount);
67        let bits = (1 << amount) | (self.bits & mask);
68        let taken = Self { bits };
69        self.bits >>= amount;
70        Some(taken)
71    }
72
73    #[inline]
74    #[must_use] 
75    pub const fn reverse(self) -> Self {
76        let len = self.len();
77        let bits = (1 << len) | (self.bits.reverse_bits() >> (BitVec::BITS - len));
78        Self { bits }
79    }
80}
81
82impl IntoIterator for Colors {
83    type IntoIter = ColorsIter;
84    type Item = Color;
85
86    #[inline]
87    fn into_iter(self) -> Self::IntoIter {
88        ColorsIter(self.reverse())
89    }
90}
91
92pub struct ColorsIter(Colors);
93
94impl Iterator for ColorsIter {
95    type Item = Color;
96
97    #[inline]
98    fn next(&mut self) -> Option<Self::Item> {
99        self.0.pop()
100    }
101
102    #[inline]
103    fn size_hint(&self) -> (usize, Option<usize>) {
104        let len = self.0.len() as usize;
105        (len, Some(len))
106    }
107}
108
109const fn to_color(n: BitVec) -> Color {
110    if n == 0 {
111        Color::Black
112    } else {
113        Color::White
114    }
115}
116
117const fn from_color(color: Color) -> BitVec {
118    match color {
119        Color::White => 1,
120        Color::Black => 0,
121    }
122}
123
124impl FromIterator<Color> for Colors {
125    fn from_iter<T: IntoIterator<Item = Color>>(iter: T) -> Self {
126        let mut colors = Self::default();
127        for color in iter {
128            colors.push(color);
129        }
130        colors
131    }
132}
133
134#[cfg(test)]
135mod tests {
136    use takparse::Color;
137
138    use super::{from_color, to_color, Colors};
139
140    #[test]
141    fn color_num() {
142        assert_eq!(Color::White, to_color(from_color(Color::White)));
143        assert_eq!(Color::Black, to_color(from_color(Color::Black)));
144        assert_eq!(from_color(Color::White), 1);
145        assert_eq!(from_color(Color::Black), 0);
146    }
147
148    #[test]
149    fn push_pop() {
150        let mut colors = Colors::default();
151        colors.push(Color::White);
152        colors.push(Color::White);
153        colors.push(Color::Black);
154        colors.push(Color::White);
155        colors.push(Color::Black);
156
157        assert_eq!(colors.len(), 5);
158        assert_eq!(colors.pop(), Some(Color::Black));
159        assert_eq!(colors.pop(), Some(Color::White));
160        assert_eq!(colors.pop(), Some(Color::Black));
161        assert_eq!(colors.pop(), Some(Color::White));
162        assert_eq!(colors.pop(), Some(Color::White));
163        assert_eq!(colors.pop(), None);
164    }
165
166    #[test]
167    fn iter() {
168        let mut colors = Colors::of_one(Color::White);
169        colors.push(Color::Black);
170        colors.push(Color::Black);
171        colors.push(Color::White);
172        colors.push(Color::White);
173        colors.push(Color::Black);
174
175        assert_eq!(colors.len(), 6);
176        let v: Vec<_> = colors.into_iter().collect();
177        assert_eq!(v, [
178            Color::White,
179            Color::Black,
180            Color::Black,
181            Color::White,
182            Color::White,
183            Color::Black
184        ]);
185    }
186
187    #[test]
188    fn take() {
189        let mut colors = Colors::of_one(Color::White);
190        colors.push(Color::Black);
191        colors.push(Color::White);
192        colors.push(Color::Black);
193        colors.push(Color::Black);
194        colors.push(Color::White);
195
196        assert_eq!(colors.len(), 6);
197        let mut a = colors.take(5).unwrap();
198        assert_eq!(colors.len(), 1);
199        assert_eq!(a.len(), 5);
200
201        assert_eq!(a.pop(), Some(Color::White));
202        assert_eq!(a.pop(), Some(Color::Black));
203        assert_eq!(a.pop(), Some(Color::Black));
204        assert_eq!(a.pop(), Some(Color::White));
205        assert_eq!(a.pop(), Some(Color::Black));
206        assert_eq!(a.pop(), None);
207
208        assert_eq!(colors.pop(), Some(Color::White));
209        assert_eq!(colors.pop(), None);
210    }
211
212    #[test]
213    fn reverse() {
214        let mut colors = Colors::of_one(Color::White);
215        colors.push(Color::White);
216        colors.push(Color::Black);
217        colors.push(Color::Black);
218        colors.push(Color::Black);
219        colors.push(Color::White);
220
221        assert_eq!(colors.len(), 6);
222        assert_eq!(colors, colors.reverse().reverse());
223        let v: Vec<_> = colors.reverse().into_iter().collect();
224        assert_eq!(v, [
225            Color::White,
226            Color::Black,
227            Color::Black,
228            Color::Black,
229            Color::White,
230            Color::White
231        ]);
232
233        // Check that iterator goes from bottom to top.
234        let mut iter = colors.into_iter();
235        let mut reverse = colors.reverse();
236        assert_eq!(reverse.len(), 6);
237        while let (Some(x), Some(y)) = (iter.next(), reverse.pop()) {
238            assert_eq!(x, y);
239        }
240        assert_eq!(iter.count(), 0);
241        assert!(reverse.is_empty());
242    }
243}