1use std::{
2 fmt::{self, Display},
3 ops::{Index, IndexMut},
4 str::FromStr,
5};
6
7use cell::Cell;
8use error::{GridError, GridParseError, GridSizeError};
9use Cell::*;
10
11pub(crate) mod cell;
12pub(crate) mod error;
13
14#[derive(Clone, Debug, Eq, PartialEq, Hash)]
25pub struct Grid {
26 cells: Box<[Cell]>,
27 size: usize,
28}
29
30impl Display for Grid {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 use std::fmt::Write;
33
34 for row in self.cells.chunks(self.size) {
35 for cell in row {
36 let c = match cell {
37 Zero => '0',
38 One => '1',
39 Empty => '.',
40 };
41 f.write_char(c)?;
42 }
43 writeln!(f)?;
44 }
45 Ok(())
46 }
47}
48
49impl Index<(usize, usize)> for Grid {
50 type Output = Cell;
51
52 fn index(&self, (i, j): (usize, usize)) -> &Self::Output {
53 &self.cells[i * self.size + j]
54 }
55}
56
57impl IndexMut<(usize, usize)> for Grid {
58 fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut Self::Output {
59 &mut self.cells[i * self.size + j]
60 }
61}
62
63impl FromStr for Grid {
64 type Err = GridParseError;
65
66 fn from_str(s: &str) -> Result<Self, Self::Err> {
67 use GridParseError::*;
68 use GridSizeError::*;
69
70 if s.is_empty() {
71 return Err(BadSize(EmptyGrid));
72 }
73 let lines: Vec<_> = s.lines().collect();
74 let size = lines.len();
75 if size % 2 == 1 {
76 return Err(BadSize(OddNumberSize(size)));
77 }
78 let mut cells = Vec::with_capacity(size * size);
79 for (i, line) in lines.iter().enumerate() {
80 let mut count: usize = 0;
81 for c in line.chars() {
82 cells.push(match c {
83 '0' => Zero,
84 '1' => One,
85 '.' => Empty,
86 _ => return Err(UnexpectedCharacter(c)),
87 });
88 count += 1;
89 }
90 if count != size {
91 return Err(BadSize(NotASquare { line: i + 1, found: count, expected: size }));
92 }
93 }
94 Ok(Self::from_parts(cells, size))
95 }
96}
97
98impl Grid {
99 pub fn new(size: usize) -> Result<Self, GridSizeError> {
105 use GridSizeError::*;
106
107 if size == 0 {
108 Err(EmptyGrid)
109 } else if size % 2 == 1 {
110 Err(OddNumberSize(size))
111 } else {
112 Ok(Self::from_parts(vec![Empty; size * size], size))
113 }
114 }
115
116 pub fn size(&self) -> usize {
118 self.size
119 }
120
121 pub fn as_slice(&self) -> &[Cell] {
123 &self.cells
124 }
125
126 pub fn as_mut_slice(&mut self) -> &mut [Cell] {
128 &mut self.cells
129 }
130
131 pub fn is_filled(&self) -> bool {
133 !self.cells.contains(&Empty)
134 }
135
136 pub fn is_legal(&self) -> bool {
140 self.check_rule1() && self.check_rule2() && self.check_rule3()
141 }
142
143 pub fn is_cell_legal(&self, coord: (usize, usize)) -> bool {
147 self[coord].is_empty() || {
148 self.check_cell_rule1(coord)
149 && self.check_cell_rule2(coord)
150 && self.check_cell_rule3(coord)
151 }
152 }
153
154 pub fn next_empty(&self) -> Option<(usize, usize)> {
157 for (i, cell) in self.cells.iter().enumerate() {
158 if cell.is_empty() {
159 let row = i / self.size;
160 let col = i % self.size;
161 return Some((row, col));
162 }
163 }
164 None
165 }
166
167 pub fn solve(&self) -> Result<Vec<Self>, GridError> {
178 if !self.is_legal() {
179 return Err(GridError::Illegal);
180 }
181 let (mut stack, mut solutions) = (Vec::new(), Vec::new());
182 let mut grid = self.clone();
183 while grid.apply_rules() {}
184 stack.push(grid);
185 while !stack.is_empty() {
186 let mut grid = stack.pop().unwrap();
187 match grid.next_empty() {
188 Some(coord) => {
189 grid[coord] = One;
190 if grid.is_cell_legal(coord) {
191 let mut grid = grid.clone();
192 while grid.apply_rules() {}
193 stack.push(grid);
194 }
195 grid[coord] = Zero;
196 if grid.is_cell_legal(coord) {
197 while grid.apply_rules() {}
198 stack.push(grid);
199 }
200 }
201 None => {
202 if grid.is_legal() {
203 solutions.push(grid);
204 }
205 }
206 }
207 }
208 Ok(solutions)
209 }
210}
211
212impl Grid {
213 fn from_parts(cells: Vec<Cell>, size: usize) -> Self {
224 assert!(size != 0, "attempted to create an empty grid");
225 assert!(size % 2 == 0, "attempted to create an odd sized grid");
226 assert!(
227 cells.len() == size * size,
228 "putative grid size does not match the number of cells"
229 );
230 Self { cells: cells.into_boxed_slice(), size }
231 }
232
233 fn check_rule1(&self) -> bool {
238 for row in self.cells.chunks(self.size) {
239 for triplet in row.windows(3) {
240 let cell = triplet[0];
241 if cell.is_filled() && cell == triplet[1] && cell == triplet[2] {
242 return false;
243 }
244 }
245 }
246 for i in 0..self.size - 2 {
247 for j in 0..self.size {
248 let cell = self[(i, j)];
249 if cell.is_filled() && cell == self[(i + 1, j)] && cell == self[(i + 2, j)] {
250 return false;
251 }
252 }
253 }
254 true
255 }
256
257 fn check_rule2(&self) -> bool {
262 let nmax = self.size / 2;
263 for row in self.cells.chunks(self.size) {
264 let count = row.iter().fold((0, 0), |mut count, cell| {
265 match cell {
266 Zero => count.0 += 1,
267 One => count.1 += 1,
268 Empty => {}
269 }
270 count
271 });
272 if count.0 > nmax || count.1 > nmax {
273 return false;
274 }
275 }
276 for i in 0..self.size {
277 let mut count = (0, 0);
278 for j in 0..self.size {
279 match self[(j, i)] {
280 Zero => count.0 += 1,
281 One => count.1 += 1,
282 Empty => {}
283 }
284 }
285 if count.0 > nmax || count.1 > nmax {
286 return false;
287 }
288 }
289 true
290 }
291
292 fn check_rule3(&self) -> bool {
296 for i in 0..self.size - 1 {
297 for j in i + 1..self.size {
298 if (0..self.size).all(|k| self[(i, k)].is_filled() && self[(i, k)] == self[(j, k)])
299 {
300 return false;
301 }
302 if (0..self.size).all(|k| self[(k, i)].is_filled() && self[(k, i)] == self[(k, j)])
303 {
304 return false;
305 }
306 }
307 }
308 true
309 }
310
311 fn check_cell_rule1(&self, (row, col): (usize, usize)) -> bool {
316 use std::cmp::min;
317
318 for i in row.saturating_sub(2)..min(row + 1, self.size - 2) {
319 let cell = self[(i, col)];
320 if cell.is_filled() && cell == self[(i + 1, col)] && cell == self[(i + 2, col)] {
321 return false;
322 }
323 }
324 for j in col.saturating_sub(2)..min(col + 1, self.size - 2) {
325 let cell = self[(row, j)];
326 if cell.is_filled() && cell == self[(row, j + 1)] && cell == self[(row, j + 2)] {
327 return false;
328 }
329 }
330 true
331 }
332
333 fn check_cell_rule2(&self, (row, col): (usize, usize)) -> bool {
338 let nmax = self.size / 2;
339 let mut count = (0, 0, 0, 0);
340 for k in 0..self.size {
341 match self[(row, k)] {
342 Zero => count.0 += 1,
343 One => count.1 += 1,
344 Empty => {}
345 }
346 match self[(k, col)] {
347 Zero => count.2 += 1,
348 One => count.3 += 1,
349 Empty => {}
350 }
351 }
352 count.0 <= nmax && count.1 <= nmax && count.2 <= nmax && count.3 <= nmax
353 }
354
355 fn check_cell_rule3(&self, (row, col): (usize, usize)) -> bool {
359 let rows_abide =
360 (0..self.size).filter(|&i| i != row && self[(i, col)] == self[(row, col)]).all(|i| !{
361 (0..self.size).all(|j| self[(row, j)].is_filled() && self[(row, j)] == self[(i, j)])
362 });
363 let cols_abide =
364 (0..self.size).filter(|&j| j != col && self[(row, j)] == self[(row, col)]).all(|j| !{
365 (0..self.size).all(|i| self[(i, col)].is_filled() && self[(i, col)] == self[(i, j)])
366 });
367 rows_abide && cols_abide
368 }
369}
370
371impl Grid {
372 fn apply_rules(&mut self) -> bool {
387 self.apply_rule1() || self.apply_rule2() || self.apply_rule3()
388 }
389
390 #[rustfmt::skip]
395 fn apply_rule1(&mut self) -> bool {
396 let mut rule_applied = false;
397 for i in 0..self.size {
398 for j in 0..self.size - 2 {
399 let trio = (self[(i, j)], self[(i, j + 1)], self[(i, j + 2)]);
400 match trio {
401 (Empty, Zero, Zero) => { self[(i, j )] = One; rule_applied = true; }
402 (Zero, Empty, Zero) => { self[(i, j+1)] = One; rule_applied = true; }
403 (Zero, Zero, Empty) => { self[(i, j+2)] = One; rule_applied = true; }
404 (Empty, One, One) => { self[(i, j )] = Zero; rule_applied = true; }
405 (One, Empty, One) => { self[(i, j+1)] = Zero; rule_applied = true; }
406 (One, One, Empty) => { self[(i, j+2)] = Zero; rule_applied = true; }
407 _ => {},
408 }
409 let trio = (self[(j, i)], self[(j + 1, i)], self[(j + 2, i)]);
410 match trio {
411 (Empty, Zero, Zero) => { self[(j , i)] = One; rule_applied = true; }
412 (Zero, Empty, Zero) => { self[(j+1, i)] = One; rule_applied = true; }
413 (Zero, Zero, Empty) => { self[(j+2, i)] = One; rule_applied = true; }
414 (Empty, One, One) => { self[(j , i)] = Zero; rule_applied = true; }
415 (One, Empty, One) => { self[(j+1, i)] = Zero; rule_applied = true; }
416 (One, One, Empty) => { self[(j+2, i)] = Zero; rule_applied = true; }
417 _ => {},
418 }
419 }
420 }
421 rule_applied
422 }
423
424 fn apply_rule2(&mut self) -> bool {
429 let mut rule_applied = false;
430 let nmax = self.size / 2;
431 for i in 0..self.size {
432 let mut count = (0, 0, 0, 0);
433 for j in 0..self.size {
434 match self[(i, j)] {
435 Zero => count.0 += 1,
436 One => count.1 += 1,
437 Empty => {}
438 }
439 match self[(j, i)] {
440 Zero => count.2 += 1,
441 One => count.3 += 1,
442 Empty => {}
443 }
444 }
445 if count.0 == nmax && count.1 != nmax {
446 rule_applied = true;
447 for j in 0..self.size {
448 if self[(i, j)].is_empty() {
449 self[(i, j)] = One;
450 }
451 }
452 } else if count.1 == nmax && count.0 != nmax {
453 rule_applied = true;
454 for j in 0..self.size {
455 if self[(i, j)].is_empty() {
456 self[(i, j)] = Zero;
457 }
458 }
459 }
460 if count.2 == nmax && count.3 != nmax {
461 rule_applied = true;
462 for j in 0..self.size {
463 if self[(j, i)].is_empty() {
464 self[(j, i)] = One;
465 }
466 }
467 } else if count.3 == nmax && count.2 != nmax {
468 rule_applied = true;
469 for j in 0..self.size {
470 if self[(j, i)].is_empty() {
471 self[(j, i)] = Zero;
472 }
473 }
474 }
475 }
476 rule_applied
477 }
478
479 fn apply_rule3(&mut self) -> bool {
483 macro_rules! row {
484 ($i:expr) => {
485 self.cells[$i * self.size..($i + 1) * self.size]
486 };
487 }
488
489 let size = self.size;
490 let mut rule_applied = false;
491 for i in 0..size {
492 if row!(i).iter().filter(|value| value.is_empty()).count() == 2 {
493 for l in 0..size {
494 if l != i
495 && !row!(l).contains(&Empty)
496 && row!(i)
497 .iter()
498 .zip(row!(l).iter())
499 .filter(|&(value, _)| value.is_filled())
500 .all(|(value, other)| value == other)
501 {
502 for j in 0..size {
503 if self[(i, j)].is_empty() {
504 self[(i, j)] = !self[(l, j)];
505 }
506 }
507 rule_applied = true;
508 break;
509 }
510 }
511 }
512 let j = i;
513 if (0..size).filter(|&l| self[(l, j)].is_empty()).count() == 2 {
514 for m in 0..size {
515 if m != j
516 && (0..size).all(|i| self[(i, m)].is_filled())
517 && (0..size)
518 .filter(|&i| self[(i, j)].is_filled())
519 .all(|i| self[(i, j)] == self[(i, m)])
520 {
521 for i in 0..size {
522 if self[(i, j)].is_empty() {
523 self[(i, j)] = !self[(i, m)];
524 }
525 }
526 rule_applied = true;
527 break;
528 }
529 }
530 }
531 }
532 rule_applied
533 }
534}