1use std::ops::{Index, IndexMut};
2
3use grid::Grid;
4use itertools::Itertools;
5
6use crate::pos::{Pos, PosGet};
7
8#[inline]
10#[must_use]
11pub fn bytes_grid(input: &str) -> Grid<u8> {
12 Grid::from(
13 input
14 .lines()
15 .map(|line| line.bytes().collect())
16 .collect_vec(),
17 )
18}
19
20impl<V> PosGet<V> for Grid<V> {
24 #[inline]
25 fn pos_get(&self, pos: Pos) -> Option<&V> {
26 self.get(pos.x, pos.y)
27 }
28
29 #[inline]
30 fn pos_get_mut(&mut self, pos: Pos) -> Option<&mut V> {
31 self.get_mut(pos.x, pos.y)
32 }
33}
34
35impl<V> Index<Pos> for Grid<V> {
36 type Output = V;
37
38 fn index(&self, index: Pos) -> &Self::Output {
39 #[allow(clippy::cast_sign_loss)]
40 &self[(index.x as usize, index.y as usize)]
41 }
42}
43
44impl<V> IndexMut<Pos> for Grid<V> {
45 fn index_mut(&mut self, index: Pos) -> &mut Self::Output {
46 #[allow(clippy::cast_sign_loss)]
47 &mut self[(index.x as usize, index.y as usize)]
48 }
49}
50
51#[derive(Debug)]
56pub struct GridMask {
57 mask: Vec<bool>,
59
60 cols: usize,
62}
63
64impl GridMask {
65 #[must_use]
67 pub fn new((rows, cols): (usize, usize)) -> Self {
68 Self {
69 mask: vec![false; rows * cols],
70 cols,
71 }
72 }
73
74 #[inline]
78 pub fn set_false(&mut self, pos: Pos) -> bool {
79 if self[pos] {
80 self[pos] = false;
81 true
82 } else {
83 false
84 }
85 }
86
87 #[inline]
91 pub fn set_true(&mut self, pos: Pos) -> bool {
92 if self[pos] {
93 false
94 } else {
95 self[pos] = true;
96 true
97 }
98 }
99
100 #[inline]
102 pub fn toggle(&mut self, pos: Pos) {
103 self[pos] = !self[pos];
104 }
105}
106
107impl Index<Pos> for GridMask {
108 type Output = bool;
109
110 #[inline]
111 fn index(&self, pos: Pos) -> &Self::Output {
112 #[allow(clippy::cast_sign_loss)]
113 &self.mask[pos.x as usize * self.cols + pos.y as usize]
114 }
115}
116
117impl IndexMut<Pos> for GridMask {
118 #[inline]
119 fn index_mut(&mut self, pos: Pos) -> &mut Self::Output {
120 #[allow(clippy::cast_sign_loss)]
121 &mut self.mask[pos.x as usize * self.cols + pos.y as usize]
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use super::{GridMask, PosGet, bytes_grid};
128 use crate::pos::Pos;
129
130 #[test]
131 fn bytes_grid_basic() {
132 let input = ("abc\ndef", [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]);
133 let expected = (2, 3, b"abcdef");
134 let grid = bytes_grid(input.0);
135 let output = (grid.rows(), grid.cols(), &input.1.map(|c| grid[c]));
136 assert_eq!(expected, output, "\n input: {input:?}");
137 }
138
139 #[test]
143 fn grid_pos_get() {
144 let input = ("abc\ndef", [Pos::new(1, 1), Pos::new(0, 3)]);
145 let expected = [Some(&b'e'), None];
146 let grid = bytes_grid(input.0);
147 let output = input.1.map(|p| grid.pos_get(p));
148 assert_eq!(expected, output, "\n input: {input:?}");
149 }
150
151 #[test]
152 fn grid_pos_get_mut() {
153 let input = ("abc\ndef", (1, 1), b'x');
154 let expected = b'x';
155 let mut grid = bytes_grid(input.0);
156 *grid
157 .pos_get_mut(Pos::from(input.1))
158 .expect("Expected in-bound position") = input.2;
159 let output = grid[input.1];
160 assert_eq!(expected, output, "\n input: {input:?}");
161 }
162
163 #[test]
164 fn grid_index_pos() {
165 let input = ("abc\ndef", Pos::new(1, 1));
166 let expected = b'e';
167 let grid = bytes_grid(input.0);
168 let output = grid[input.1];
169 assert_eq!(expected, output, "\n input: {input:?}");
170 }
171
172 #[test]
173 fn grid_indexmut_pos() {
174 let input = ("abc\ndef", (1, 1), b'x');
175 let expected = b'x';
176 let mut grid = bytes_grid(input.0);
177 grid[Pos::from(input.1)] = input.2;
178 let output = grid[input.1];
179 assert_eq!(expected, output, "\n input: {input:?}");
180 }
181
182 #[test]
185 fn gridmask_new() {
186 let input = (2, 3);
187 let expected = (vec![false; 6], 3);
188 let gridmask = GridMask::new(input);
189 let output = (gridmask.mask, gridmask.cols);
190 assert_eq!(expected, output, "\n input: {input:?}");
191 }
192
193 #[test]
194 fn gridmask_set_false() {
195 let input = ((2, 3), Pos::new(1, 1));
196 let expected = (false, false, true, false);
197 let mut gridmask = GridMask::new(input.0);
198 let output = (
199 gridmask[input.1],
200 gridmask.set_false(input.1),
201 {
202 gridmask[input.1] = true;
203 gridmask.set_false(input.1)
204 },
205 gridmask[input.1],
206 );
207 assert_eq!(expected, output, "\n input: {input:?}");
208 }
209
210 #[test]
211 fn gridmask_set_true() {
212 let input = ((2, 3), Pos::new(1, 1));
213 let expected = (false, true, true, false);
214 let mut gridmask = GridMask::new(input.0);
215 let output = (
216 gridmask[input.1],
217 gridmask.set_true(input.1),
218 gridmask[input.1],
219 gridmask.set_true(input.1),
220 );
221 assert_eq!(expected, output, "\n input: {input:?}");
222 }
223
224 #[test]
225 fn gridmask_toggle() {
226 let input = ((2, 3), Pos::new(1, 1));
227 let expected = (false, true, false);
228 let mut gridmask = GridMask::new(input.0);
229 let output = (
230 gridmask[input.1],
231 {
232 gridmask.toggle(input.1);
233 gridmask[input.1]
234 },
235 {
236 gridmask.toggle(input.1);
237 gridmask[input.1]
238 },
239 );
240 assert_eq!(expected, output, "\n input: {input:?}");
241 }
242
243 #[test]
244 fn gridmask_index_pos() {
245 let input = ((2, 3), [Pos::new(0, 2), Pos::new(1, 1)]);
246 let expected = [true, false];
247 let mut gridmask = GridMask::new(input.0);
248 gridmask.set_true(input.1[0]);
249 let output = input.1.map(|p| gridmask[p]);
250 assert_eq!(expected, output, "\n input: {input:?}");
251 }
252
253 #[test]
254 fn gridmask_indexmut_pos() {
255 let input = ((2, 3), [Pos::new(0, 2), Pos::new(1, 1)]);
256 let expected = [true, false, false, true];
257 let mut gridmask = GridMask::new(input.0);
258 gridmask.set_true(input.1[0]);
259 let mut output = [false; 4];
260 output[0] = gridmask[input.1[0]];
261 output[1] = gridmask[input.1[1]];
262 gridmask[input.1[0]] = !gridmask[input.1[0]];
263 gridmask[input.1[1]] = !gridmask[input.1[1]];
264 output[2] = gridmask[input.1[0]];
265 output[3] = gridmask[input.1[1]];
266 assert_eq!(expected, output, "\n input: {input:?}");
267 }
268}