1use std::cmp::Ordering;
2use std::collections::BTreeMap;
3use pathfinding::prelude::Matrix;
4use crate::cats::Colour::*;
5use crate::cats::Direction::*;
6use crate::cats::Transformation::*;
7use crate::cats::Transformation;
8use crate::cats::{Colour, Direction};
9use crate::utils::*;
10use crate::cell::*;
11use crate::shape::*;
12
13#[derive(Debug, Hash, Clone, PartialEq, Eq)]
14pub struct Grid {
15 pub colour: Colour,
16 pub cells: Matrix<Cell>,
17 }
19
20impl Ord for Grid {
21 fn cmp(&self, other: &Self) -> Ordering {
22 (&self.to_json(), &self.colour).cmp(&(&other.to_json(), &other.colour))
23 }
25}
26
27impl PartialOrd for Grid {
28 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
29 Some(self.cmp(other))
30 }
31}
32
33impl Grid {
34 pub fn new(rows: usize, cols: usize, colour: Colour) -> Self {
35 if cols > 100 || rows > 100 {
36 return Self::trivial();
37 }
38
39 let cells: Matrix<Cell> = Matrix::from_fn(rows, cols, |(x, y)| Cell::new_colour(x, y, colour));
40
41 Self { colour, cells }
42 }
43
44 pub fn trivial() -> Self {
45 let cells: Matrix<Cell> = Matrix::new(0, 0, Cell::new_empty());
46
47 Self { colour: Black, cells }
48 }
49
50 pub fn dummy() -> Self {
51 Self::new(2, 2, Black)
52 }
53
54 pub fn is_trivial(&self) -> bool {
55 self.cells.rows == 0 && self.cells.columns == 0 && self.colour == Black
56 }
57
58 pub fn is_dummy(&self) -> bool {
59 self.cells.rows == 2 && self.cells.columns == 2 && self.colour == Black
60 }
61
62 pub fn new_from_matrix(cells: &Matrix<Cell>) -> Self {
63 let mut colour = NoColour;
64
65 for c in cells.values() {
66 if c.colour != Black {
67 if colour == NoColour {
68 colour = c.colour;
69 } else if colour != c.colour {
70 colour = Mixed;
71 break;
72 }
73 }
74 }
75
76 Self { colour, cells: cells.clone() }
77 }
78
79 pub fn rip(&self, colour: Colour) -> Self {
94 let mut starts = Shapes::new_sized(self.cells.rows, self.cells.columns);
95 let mut top = true;
96 let mut left = true;
97 let mut updown = true;
98
99 for s in self.to_shapes().shapes.iter() {
100 if s.orow > 0 && s.ocol > 0 {
101 top = s.orow < self.cells.rows / 2;
102 left = s.ocol < self.cells.columns / 2;
103 } else {
104 updown = s.ocol == 0;
105 }
106 }
107
108 let dir = if top && !left && updown {
109 Up
110 } else if !top && left && !updown {
111 Left
112 } else if !top && !left && !updown {
113 Right
114 } else {
115 Down
116 };
117
118 let mut grid = match dir {
119 Up => self.clone(),
120 Right => self.rot_rect_270(),
121 Down => self.rot_rect_180(),
122 Left => self.rot_rect_90(),
123 _ => todo!(),
124 };
125
126 for s in grid.to_shapes().shapes.iter() {
127 if s.orow > 0 && s.ocol > 0 || s.size() < self.cells.rows && s.size() < self.cells.columns && (s.orow == 0 || s.ocol == 0) {
128 starts.shapes.push(s.clone());
129 }
130 }
131
132 for c in 0 .. grid.cells.columns {
133 if starts.in_range(c, true) {
134 let mut nc = NoColour;
135 let mut nc2 = NoColour;
136 let mut nc3 = NoColour;
137 let mut cnt = 0;
138
139 for r in 0 .. grid.cells.rows {
140 if starts.in_range(r, false) {
141 if grid.cells[(r,c)].colour != Black {
142 nc = grid.cells[(r,c)].colour;
143 grid.cells[(r,c)].colour = colour;
144 } else if nc != NoColour {
145 grid.cells[(r,c)].colour = nc;
146 }
147 } else if nc != NoColour && nc2 == NoColour {
148 if grid.cells[(r,c)].colour != Black {
149 nc2 = grid.cells[(r,c)].colour;
150 } else {
151 grid.cells[(r,c)].colour = nc;
152 }
153 } else if nc2 != NoColour {
154 if grid.cells[(r,c)].colour != Black {
155 nc3 = grid.cells[(r,c)].colour;
156 cnt += 1;
157 }
158 if r >= grid.cells.rows - cnt {
159 grid.cells[(r,c)].colour = nc3;
160 } else {
161 grid.cells[(r,c)].colour = nc2;
162 }
163 }
164 }
165 }
166 }
167
168 match dir {
169 Up => grid.clone(),
170 Right => grid.rot_rect_90(),
171 Down => grid.rot_rect_180(),
172 Left => grid.rot_rect_270(),
173 _ => todo!(),
174 }
175 }
176
177 pub fn duplicate(grid: &[Vec<usize>]) -> Self {
178 let x: usize = grid.len();
179 let y: usize = grid[0].len();
180 let mut colour = NoColour;
181 let cells: Matrix<Cell> = Matrix::from_fn(x, y, |(x, y)| Cell::new(x, y, grid[x][y]));
182
183 for c in cells.values() {
184 if c.colour != Black {
185 if colour == NoColour {
186 colour = c.colour;
187 } else if colour != c.colour {
188 colour = Mixed;
189 break;
190 }
191 }
192 }
193
194 Self { colour, cells }
195 }
196
197 pub fn is_empty(&self) -> bool {
198 for c in self.cells.values() {
199 if c.colour != Black {
200 return false
201 }
202 }
203
204 true
205 }
206
207 pub fn to_origin(&self) -> Self {
208 let mut grid = self.clone();
209
210 grid.to_origin_mut();
211
212 grid
213 }
214
215 pub fn to_origin_mut(&mut self) {
216 for r in 0 .. self.cells.rows {
217 for c in 0 .. self.cells.columns {
218 self.cells[(r,c)].row = r;
219 self.cells[(r,c)].col = c;
220 }
221 }
222 }
223
224 pub fn find_colour_pixel_coords(&self, colour: Colour) -> (usize, usize) {
225 for ((r, c), cell) in self.cells.items() {
226 if cell.colour == colour {
227 return (r, c);
228 }
229 }
230
231 (0, 0)
232 }
233
234 pub fn find_different_pixel_coords(&self) -> (usize, usize) {
235 let colour = self.minority_colour();
236
237 self.find_colour_pixel_coords(colour)
238 }
239
240 pub fn find_colour(&self, colour: Colour) -> Vec<Cell> {
241 self.cells.values().filter(|c| c.colour == colour).cloned().collect()
242 }
243
244 pub fn in_to_squared_out(&self) -> Self {
245 let rows = self.cells.rows;
246 let cols = self.cells.columns;
247
248 if rows != cols {
249 return Self::trivial();
250 }
251
252 let mut g = Self::new(rows * rows, cols * cols, Black);
253
254 for r in (0 .. rows * rows).step_by(rows) {
255 for c in (0 .. cols * cols).step_by(cols) {
256 g.copy_to_position_mut(self, r, c);
257 }
258 }
259
260 g
261 }
262
263 pub fn find_all_colours(&self) -> BTreeMap<Colour, usize> {
264 let mut c: BTreeMap<Colour, usize> = BTreeMap::new();
265
266 for cell in self.cells.values() {
267 *c.entry(cell.colour).or_insert(0) += 1;
268 }
269
270 c
271 }
272
273 pub fn find_min_colour(&self) -> Colour {
274 let cols = self.find_all_colours();
275 let col = cols.iter()
276 .filter(|&(&col, _)| col != Black)
277 .min_by(|col, c| col.1.cmp(c.1))
278 .map(|(col, _)| col);
279
280 if let Some(col) = col {
281 *col
282 } else {
283 NoColour
284 }
285 }
286
287 pub fn find_max_colour(&self) -> Colour {
288 let cols = self.find_all_colours();
289 let col = cols.iter()
290 .filter(|&(&col, _)| col != Black)
291 .max_by(|col, c| col.1.cmp(c.1))
292 .map(|(col, _)| col);
293
294 if let Some(col) = col {
295 *col
296 } else {
297 NoColour
298 }
299 }
300
301 pub fn stretch_down(&self) -> Self {
303 let mut m = Matrix::new(self.cells.rows, self.cells.columns, Cell::new(0, 0, 0));
304
305 for y in 0 .. self.cells.columns {
306 let mut colour = NoColour;
307
308 for x in 1 .. self.cells.rows {
309 if self.cells[(x - 1,y)].colour != Black {
310 if colour == NoColour {
311 colour = self.cells[(x - 1,y)].colour;
312 m[(x - 1,y)].colour = colour;
313 } else {
314 continue;
315 }
316 }
317 m[(x,y)].row = x;
318 m[(x,y)].col = y;
319 m[(x,y)].colour = if colour == NoColour {
320 self.cells[(x,y)].colour
321 } else {
322 colour
323 };
324 }
325 }
326
327 Self::new_from_matrix(&m)
328 }
329
330 pub fn is_diag_origin(&self) -> bool {
331 if !self.is_square() || self.colour == Mixed {
332 return false;
333 }
334
335 for ((r, c), cell) in self.cells.items() {
336 if r != c && cell.colour != Black {
337 return false;
338 }
339 }
340
341 true
342 }
343
344 pub fn is_diag_not_origin(&self) -> bool {
345 self.rot_90().is_diag_origin()
346 }
347
348 pub fn gravity_down(&self) -> Self {
355 self.gravity_down_colour(Black)
356 }
357
358 pub fn gravity_down_colour(&self, colour: Colour) -> Self {
359 let mut values: Vec<Colour> = vec![colour; self.cells.columns];
360 let mut counts: Vec<usize> = vec![0; self.cells.columns];
361
362 for ((r, c), cell) in self.cells.items() {
363 if self.cells[(r,c)].colour != colour {
364 if values[c] == colour {
365 values[c] = cell.colour;
366 }
367
368 counts[c] += 1;
369 }
370 }
371
372 let mut m = self.cells.clone();
373
374 for (r, c) in self.cells.keys() {
375 if self.cells[(r,c)].colour == colour {
376 m[(r,c)].colour = values[c];
377 }
378 if self.cells.rows - r > counts[c] {
379 m[(r,c)].colour = colour;
380 }
381 }
382
383 Self::new_from_matrix(&m)
384 }
385
386 pub fn gravity_up(&self) -> Self {
387 self.mirrored_rows().gravity_down().mirrored_rows()
388 }
389
390 pub fn gravity_right(&self) -> Self {
391 self.rot_rect_90().gravity_down().rot_rect_270()
392 }
393
394 pub fn gravity_left(&self) -> Self {
395 self.rot_rect_270().gravity_down().rot_rect_90()
396 }
397
398 pub fn move_down(&self) -> Self {
399 let mut m = Matrix::new(self.cells.rows, self.cells.columns, Cell::new(0, 0, 0));
400
401 for r in 1 .. self.cells.rows {
402 for c in 0 .. self.cells.columns {
403 m[(r,c)].row = r;
404 m[(r,c)].col = c;
405 m[(r,c)].colour = self.cells[(r - 1,c)].colour;
406 }
407 }
408
409 Self::new_from_matrix(&m)
410 }
411
412 pub fn move_up(&self) -> Self {
419 let mut m = Matrix::new(self.cells.rows, self.cells.columns, Cell::new(0, 0, 0));
420
421 for r in 1 .. self.cells.rows {
422 for c in 0 .. self.cells.columns {
423 m[(r,c)].row = r;
424 m[(r,c)].col = c;
425 m[(r - 1,c)].colour = self.cells[(r,c)].colour;
426 }
427 }
428
429 Self::new_from_matrix(&m)
430 }
431
432 pub fn move_right(&self) -> Self {
433 let mut m = Matrix::new(self.cells.rows, self.cells.columns, Cell::new(0, 0, 0));
434
435 for r in 0 .. self.cells.rows {
436 for c in 1 .. self.cells.columns {
437 m[(r,c)].row = r;
438 m[(r,c)].col = c;
439 m[(r,c)].colour = self.cells[(r,c - 1)].colour;
440 }
441 }
442
443 Self::new_from_matrix(&m)
444 }
445
446 pub fn move_left(&self) -> Self {
447 let mut m = Matrix::new(self.cells.rows, self.cells.columns, Cell::new(0, 0, 0));
448
449 for r in 0 .. self.cells.rows {
450 for c in 1 .. self.cells.columns {
451 m[(r,c)].row = r;
452 m[(r,c)].col = c;
453 m[(r,c - 1)].colour = self.cells[(r,c)].colour;
454 }
455 }
456
457 Self::new_from_matrix(&m)
458 }
459
460 pub fn trim(&self, r: usize, c: usize) -> Self {
461 if self.cells.rows <= r && self.cells.columns <= c {
462 return self.clone();
463 }
464
465 let mut grid = Self::new(r, c, Black);
466
467 for ((r, c), cell) in self.cells.items() {
468 if r < grid.cells.rows && c < grid.cells.columns {
469 grid.cells[(r,c)].row = cell.row;
470 grid.cells[(r,c)].col = cell.col;
471 grid.cells[(r,c)].colour = cell.colour;
472 }
473 }
474
475 grid
476 }
477
478 pub fn free_border(&self, dir: Direction) -> bool {
479 match dir {
480 Up => {
481 for i in 0 .. self.cells.columns {
482 if self.cells[(0, i)].colour != Black {
483 return false;
484 }
485 }
486 true
487 },
488 Down => {
489 for i in 0 .. self.cells.columns {
490 if self.cells[(self.cells.rows - 1, i)].colour != Black {
491 return false;
492 }
493 }
494 true
495 },
496 Left => {
497 for i in 0 .. self.cells.rows {
498 if self.cells[(i, 0)].colour != Black {
499 return false;
500 }
501 }
502 true
503 },
504 Right => {
505 for i in 0 .. self.cells.rows {
506 if self.cells[(i, self.cells.columns - 1)].colour != Black {
507 return false;
508 }
509 }
510 true
511 },
512 _ => false
513 }
514 }
515
516 pub fn negative_mut(&mut self, colour: Colour) {
517 self.negative_dir_mut(colour, vec![]);
518 }
519
520 pub fn negative_dir_all_mut(&mut self, colour: Colour) {
521 self.negative_dir_mut(colour, vec![Up, Down, Left, Right]);
522 }
523
524 pub fn negative_dir_mut(&mut self, colour: Colour, exclude: Vec<Direction>) {
525 for r in 0 .. self.cells.rows {
526 for c in 0 .. self.cells.columns {
527 if r == 0 && exclude.contains(&Up) || c == 0 && exclude.contains(&Left) || r == self.cells.rows - 1 && exclude.contains(&Down) || c == self.cells.columns - 1 && exclude.contains(&Right) {
528 continue;
529 }
530
531 if self.cells[(r,c)].colour != Black {
532 self.cells[(r,c)].colour = Black;
533 } else {
534 self.cells[(r,c)].colour = colour;
535 }
536 }
537 }
538 }
539
540 pub fn background_border_mut(&mut self) {
541 let (rs, cs) = self.dimensions();
542
543 for r in 0 .. rs {
544 self.cells[(r,0)].colour = Black;
545 self.cells[(r,cs-1)].colour = Black;
546 }
547
548 for c in 0 .. cs {
549 self.cells[(0,c)].colour = Black;
550 self.cells[(rs-1,c)].colour = Black;
551 }
552 }
553
554 pub fn row_dividers_mut(&mut self, rs: usize) {
555 let mut r = rs + 1;
556
557 while r < self.cells.rows {
558 for c in 0 .. self.cells.columns {
559 self.cells[(r,c)].colour = Black;
560 }
561
562 r += rs + 1;
563 }
564 }
565
566 pub fn col_dividers_mut(&mut self, cs: usize) {
567 let mut c = cs + 1;
568
569 while c < self.cells.columns {
570 for r in 0 .. self.cells.rows {
571 self.cells[(r,c)].colour = Black;
572 }
573
574 c += cs + 1;
575 }
576 }
577
578 pub fn recolour(&self, from: Colour, to: Colour) -> Self {
579 let mut grid = self.clone();
580
581 grid.recolour_mut(from, to);
582
583 grid
584 }
585
586 pub fn recolour_mut(&mut self, from: Colour, to: Colour) {
587 for c in self.cells.values_mut() {
588 if c.colour == from || from == NoColour {
592 c.colour = to;
593 } else if from == Mixed {
594 if c.colour != Black {
595 c.colour = Black;
596 } else {
597 c.colour = to;
598 }
599 }
600 }
601 }
602
603 pub fn force_recolour(&self, to: Colour) -> Self {
604 let mut grid = self.clone();
605
606 grid.colour = to;
607
608 for c in grid.cells.values_mut() {
609 c.colour = to;
610 }
611
612 grid
613 }
614
615 pub fn copy_to_position(&self, grid: &Self, r: usize, c: usize) -> Self {
616 let mut i = self.clone();
617
618 i.copy_to_position_mut(grid, r, c);
619
620 i
621 }
622
623 pub fn copy_to_position_mut(&mut self, grid: &Self, rp: usize, cp: usize) {
624 if rp + grid.cells.rows > self.cells.rows || cp + grid.cells.columns > self.cells.columns {
625 return;
626 }
627
628 for ((r, c), cell) in grid.cells.items() {
629 self.cells[(rp + r, cp + c)] = cell.clone();
630 }
631 }
632
633 pub fn copy_shape_to_grid_mut(&mut self, shape: &Shape) {
634 self.copy_shape_to_grid_position_mut(shape, shape.orow, shape.ocol)
635 }
636
637 pub fn copy_shape_to_grid_position_mut(&mut self, shape: &Shape, row: usize, col: usize) {
638 for (r, c) in shape.cells.keys() {
639 if row+r >= self.cells.rows || col+c >= self.cells.columns {
641 continue;
642 }
643
644 self.cells[(row+r, col+c)].colour = shape.cells[(r,c)].colour;
645 }
646 }
647
648 pub fn connect_dots_pairs(&mut self) {
649 self.connect_dots_dir(Other, NoColour);
650 }
651
652 pub fn connect_dots(&mut self) {
653 self.connect_dots_dir(CalcDir, NoColour);
654 }
655
656 pub fn connect_dots_colour(&mut self, colour: Colour) {
657 self.connect_dots_dir(CalcDir, colour);
658 }
659
660 pub fn connect_dots_colour_pairs(&mut self, colour: Colour) {
661 self.connect_dots_dir(Other, colour);
662 }
663
664 pub fn connect_dots_dir(&mut self, dir: Direction, col: Colour) {
666 let posns = self.cell_colour_posn_map();
667
668 for (colour, vp) in posns.iter() {
669 let col = if col == NoColour { *colour } else { col };
670
671 if vp.len() == 1 {
672 if dir != Other {
673 let dir = if dir == CalcDir {
674 let (r, c) = vp[0];
675
676 if r == 0 {
677 Down
678 } else if c == 0 {
679 Right
680 } else if r == self.cells.rows - 1 {
681 Up
682 } else {
683 Left
684 }
685 } else {
686 dir
687 };
688 self.draw_mut(dir, vp[0].0, vp[0].1, *colour);
689 }
690 } else {
691 let mut line: BTreeMap<usize,(Direction, usize, usize, usize)> = BTreeMap::new();
692 let mut done: Vec<(Direction, usize, usize, usize)> = Vec::new();
693
694 for (r1, c1) in vp.iter() {
695 for (r2, c2) in vp.iter() {
696 if r1 != r2 && c1 == c2 {
697 let pmin = *r1.min(r2);
698 let pmax = *r1.max(r2);
699 let val = (Vertical, *c1, pmin, pmax);
700
701 if pmax - pmin > 1 && !done.contains(&val) {
702 line.insert(pmax - pmin, val);
703 done.push(val);
704 }
705 }
706 if r1 == r2 && c1 != c2 {
707 let pmin = *c1.min(c2);
708 let pmax = *c1.max(c2);
709 let val = (Horizontal, *r1, pmin, pmax);
710
711 if pmax - pmin > 1 && !done.contains(&val) {
712 line.insert(pmax - pmin, val);
713 done.push(val);
714 }
715 }
716 }
717 if let Some((_, (dir, rc, pmin, pmax))) = line.pop_first() {
718 line.clear();
719
720 match dir {
721 Vertical => {
722 for r in pmin .. pmax {
723 if self.cells[(r,rc)].colour != *colour {
724 self.cells[(r,rc)].colour = col;
725 }
726 }
727 },
728 Horizontal => {
729 for c in pmin .. pmax {
730 if self.cells[(rc,c)].colour != *colour {
731 self.cells[(rc,c)].colour = col;
732 }
733 }
734 },
735 _ => todo!()
736 }
737 }
738 }
739 }
740 }
741 }
742
743 pub fn draw_lines_from_shapes(&mut self, shapes: &[Shape], overwrite: bool, hv: bool) {
744 let v: Vec<&Shape> = shapes.iter().collect();
745
746 self.draw_lines(&v, overwrite, hv);
747 }
748
749 pub fn draw_lines(&mut self, shapes: &[&Shape], overwrite: bool, hv: bool) {
750 for (j, s) in shapes.iter().enumerate() {
751 for shape in shapes.iter().skip(j) {
752 if s != shape {
753 if hv {
754 self.draw_line_row(s, shape, s.colour, false, false);
755 } else {
756 self.draw_line_col(s, shape, s.colour, false, false);
757 }
758 }
759 }
760 }
761 for (j, s) in shapes.iter().enumerate() {
762 for shape in shapes.iter().skip(j) {
763 if s != shape {
764 if hv {
765 self.draw_line_col(s, shape, s.colour, overwrite, false);
766 } else {
767 self.draw_line_row(s, shape, s.colour, overwrite, false);
768 }
769 }
770 }
771 }
772 }
773
774 pub fn draw_mut(&mut self, dir: Direction, r: usize, c: usize, colour: Colour) {
775 self.draw_bg_mc_term_mut(dir, r, c, colour, Black, false, false);
776 }
777
778 pub fn draw_bg_mut(&mut self, dir: Direction, r: usize, c: usize, colour: Colour, bg: Colour) {
779 self.draw_bg_mc_term_mut(dir, r, c, colour, bg, false, false);
780 }
781
782 pub fn draw_mc_mut(&mut self, dir: Direction, r: usize, c: usize, colour: Colour) {
783 self.draw_bg_mc_term_mut(dir, r, c, colour, Black, true, false);
784 }
785
786 pub fn draw_term_mut(&mut self, dir: Direction, r: usize, c: usize, colour: Colour) {
787 self.draw_bg_mc_term_mut(dir, r, c, colour, Black, false, true);
788 }
789
790 pub fn draw_bg_mc_mut(&mut self, dir: Direction, r: usize, c: usize, colour: Colour, bg: Colour) {
791 self.draw_bg_mc_term_mut(dir, r, c, colour, bg, true, false)
792 }
793
794 pub fn draw_bg_term_mut(&mut self, dir: Direction, r: usize, c: usize, colour: Colour, bg: Colour) {
795 self.draw_bg_mc_term_mut(dir, r, c, colour, bg, false, true)
796 }
797
798 pub fn draw_bg_mc_term_mut(&mut self, dir: Direction, r: usize, c: usize, colour: Colour, bg: Colour, mc: bool, term: bool) {
799 self.draw_bg_mc_term_other_mut(dir, r, c, colour, bg, mc, term, NoColour)
800 }
801
802 pub fn draw_bg_mc_term_other_mut(&mut self, dir: Direction, r: usize, c: usize, colour: Colour, bg: Colour, mc: bool, term: bool, other_colour: Colour) {
803 fn change_colour(cell_colour: &mut Colour, colour: Colour, bg: Colour, mc: bool, term: bool, other_colour: Colour) -> bool {
804 if term && *cell_colour != bg && *cell_colour != other_colour {
808 return true;
809 } else if mc && *cell_colour != bg && *cell_colour != colour {
810 *cell_colour = colour + ToBlack;
811 } else if *cell_colour == bg || *cell_colour == colour {
812 *cell_colour = colour;
813 }
814
815 false
816 }
817
818 match dir {
819 Up => {
820 for r in 0 ..= r {
821 if change_colour(&mut self.cells[(r,c)].colour, colour, bg, mc, term, other_colour) { break; }
822 }
823 },
824 Down => {
825 for r in r .. self.cells.rows {
826 if change_colour(&mut self.cells[(r,c)].colour, colour, bg, mc, term, other_colour) { break; }
827 }
828 },
829 Left => {
830 for c in 0 ..= c {
831 if change_colour(&mut self.cells[(r,c)].colour, colour, bg, mc, term, other_colour) { break; }
832 }
833 },
834 Right => {
835 for c in c .. self.cells.columns {
836 if change_colour(&mut self.cells[(r,c)].colour, colour, bg, mc, term, other_colour) { break; }
837 }
838 },
839 UpRight => {
840 for (r, c) in ((0 ..= r).rev()).zip(c ..= self.cells.columns) {
841 if r < self.cells.rows && c < self.cells.columns {
842 if change_colour(&mut self.cells[(r,c)].colour, colour, bg, mc, term, other_colour) { break; }
843 }
844 }
845 },
846 UpLeft => {
847 for (r, c) in ((0 ..= r).rev()).zip((0 ..= c).rev()) {
848 if r < self.cells.rows && c < self.cells.columns {
849 if change_colour(&mut self.cells[(r,c)].colour, colour, bg, mc, term, other_colour) { break; }
850 }
851 }
852 },
853 DownRight => {
854 for (r, c) in (r .. self.cells.rows).zip(c .. self.cells.columns) {
855 if r < self.cells.rows && c < self.cells.columns {
856 if change_colour(&mut self.cells[(r,c)].colour, colour, bg, mc, term, other_colour) { break; }
857 }
858 }
859 },
860 DownLeft => {
861 for (r, c) in (r .. self.cells.rows).zip((0 ..= c).rev()) {
862 if r < self.cells.rows && c < self.cells.columns {
863 if change_colour(&mut self.cells[(r,c)].colour, colour, bg, mc, term, other_colour) { break; }
864 }
865 }
866 },
867 FromUpRight => {
868 for (r, c) in (0 ..= r).rev().zip(c-1 .. self.cells.columns) {
869 if change_colour(&mut self.cells[(r,c)].colour, colour, bg, mc, term, other_colour) { break; }
870 }
871 },
872 FromUpLeft => {
873 for (r, c) in (0 ..= r).zip(0 ..= c) {
874 if change_colour(&mut self.cells[(r,c)].colour, colour, bg, mc, term, other_colour) { break; }
875 }
876 },
877 FromDownRight => {
878 for (r, c) in (r .. self.cells.rows).zip(c .. self.cells.columns) {
879 if change_colour(&mut self.cells[(r,c)].colour, colour, bg, mc, term, other_colour) { break; }
880 }
881 },
882 FromDownLeft => {
883 for (r, c) in (r-1 .. self.cells.rows).zip((0 ..= c).rev()) {
884 if change_colour(&mut self.cells[(r,c)].colour, colour, bg, mc, term, other_colour) { break; }
885 }
886 },
887 _ => {},
888 }
889 }
890
891 pub fn skip_to(&self, dir: Direction, r: usize, c: usize) -> (usize, usize) {
892 self.skip_to_bg(dir, r, c, Black)
893 }
894
895 pub fn skip_to_bg(&self, dir: Direction, r: usize, c: usize, bg: Colour) -> (usize, usize) {
896 match dir {
897 Up => {
898 for r in 0 ..= r {
899 if self.cells[(r,c)].colour == bg { return (r, c); }
900 }
901 },
902 Down => {
903 for r in r .. self.cells.rows {
904 if self.cells[(r,c)].colour == bg { return (r, c); }
905 }
906 },
907 Left => {
908 for c in 0 ..= c {
909 if self.cells[(r,c)].colour == bg { return (r, c); }
910 }
911 },
912 Right => {
913 for c in c .. self.cells.columns {
914 if self.cells[(r,c)].colour == bg { return (r, c); }
915 }
916 },
917 UpRight => {
918 for (r, c) in ((0 ..= r).rev()).zip(c ..= self.cells.columns) {
919 if r < self.cells.rows && c < self.cells.columns {
920 if self.cells[(r,c)].colour == bg { return (r, c); }
921 }
922 }
923 },
924 UpLeft => {
925 for (r, c) in ((0 ..= r).rev()).zip((0 ..= c).rev()) {
926 if r < self.cells.rows && c < self.cells.columns {
927 if self.cells[(r,c)].colour == bg { return (r, c); }
928 }
929 }
930 },
931 DownRight => {
932 for (r, c) in (r .. self.cells.rows).zip(c .. self.cells.columns) {
933 if r < self.cells.rows && c < self.cells.columns {
934 if self.cells[(r,c)].colour == bg { return (r, c); }
935 }
936 }
937 },
938 DownLeft => {
939 for (r, c) in (r .. self.cells.rows).zip((0 ..= c).rev()) {
940 if r < self.cells.rows && c < self.cells.columns {
941 if self.cells[(r,c)].colour == bg { return (r, c); }
942 }
943 }
944 },
945 FromUpRight => {
946 for (r, c) in (0 ..= r).rev().zip(c-1 .. self.cells.columns) {
947 if self.cells[(r,c)].colour == bg { return (r, c); }
948 }
949 },
950 FromUpLeft => {
951 for (r, c) in (0 ..= r).zip(0 ..= c) {
952 if self.cells[(r,c)].colour == bg { return (r, c); }
953 }
954 },
955 FromDownRight => {
956 for (r, c) in (r .. self.cells.rows).zip(c .. self.cells.columns) {
957 if self.cells[(r,c)].colour == bg { return (r, c); }
958 }
959 },
960 FromDownLeft => {
961 for (r, c) in (r-1 .. self.cells.rows).zip((0 ..= c).rev()) {
962 if self.cells[(r,c)].colour == bg { return (r, c); }
963 }
964 },
965 _ => {},
966 }
967
968 (r, c)
969 }
970
971 pub fn calc_direction(r1: usize, c1: usize, r2: usize, c2: usize) -> Direction {
972 if r1 == r2 && c1 == c2 {
973 return Other;
974 }
975
976 let l1 = (r1 as isize - r2 as isize).abs() as usize;
977 let l2 = (c1 as isize - c2 as isize).abs() as usize;
978
979 if l1 != 0 && l2 != 0 && l1 != l2 {
980 return Other;
981 }
982
983 if l1 == 0 || l2 == 0 {
984 if r1 < r2 { Down }
985 else if r1 > r2 { Up }
986 else if c1 < c2 { Right }
987 else if c1 > c2 { Left }
988 else { Other }
989 } else if r1 < r2 && c1 < c2 {
990 DownRight
991 } else if r1 < r2 && c1 > c2 {
992 DownLeft
993 } else if r1 > r2 && c1 < c2 {
994 UpRight
995 } else if r1 > r2 && c1 > c2 {
996 UpLeft
997 } else {
998 Other
999 }
1000 }
1001
1002 pub fn shape_in_line(&self, shape: &Shape) -> Colour {
1003 let r = shape.orow;
1004 let c = shape.ocol;
1005
1006 if self.cells[(r,c)].colour == shape.colour {
1007 let mut cnt = 0;
1008 let mut colour = NoColour;
1009 fn func(col: Colour, colour: &mut Colour, cnt: &mut usize) {
1010 if *colour == NoColour || col == *colour {
1011 *cnt += 1;
1012 if col != NoColour {
1013 *colour = col;
1014 }
1015 }
1016 }
1017
1018 if r == 0 {
1019 func(NoColour, &mut colour, &mut cnt);
1020 } else {
1021 let col = self.cells[(r-1,c)].colour;
1022
1023 if col != shape.colour && col != Black {
1024 func(col, &mut colour, &mut cnt);
1025 }
1026 }
1027 if c == 0 {
1028 func(NoColour, &mut colour, &mut cnt);
1029 } else {
1030 let col = self.cells[(r,c-1)].colour;
1031
1032 if col != shape.colour && col != Black {
1033 func(col, &mut colour, &mut cnt);
1034 }
1035 }
1036 if r == self.cells.rows - 1 {
1037 func(NoColour, &mut colour, &mut cnt);
1038 } else {
1039 let col = self.cells[(r+1,c)].colour;
1040
1041 if col != shape.colour && col != Black {
1042 func(col, &mut colour, &mut cnt);
1043 }
1044 }
1045 if c == self.cells.columns - 1 {
1046 func(NoColour, &mut colour, &mut cnt);
1047 } else {
1048 let col = self.cells[(r,c+1)].colour;
1049
1050 if col != shape.colour && col != Black {
1051 func(col, &mut colour, &mut cnt);
1052 }
1053 }
1054
1055 if cnt == 2 { colour } else { NoColour }
1056 } else {
1057 NoColour
1058 }
1059 }
1060
1061 pub fn trim_excess_mut(&mut self) {
1063 for r in 0 .. self.cells.rows {
1064 for c in 0 .. self.cells.columns {
1065 let colour = self.cells[(r,c)].colour;
1066
1067 if colour == Black {
1068 continue;
1069 }
1070
1071 let rs = self.cells.rows;
1072 let cs = self.cells.columns;
1073 let mut state = 0;
1074
1075 if r == 0 {
1076 for r in 0 .. rs {
1077 if self.cells[(r,c)].colour != Black && self.cells[(r,c-1)].colour == Black && self.cells[(r,c+1)].colour == Black {
1078 self.cells[(r,c)].colour = if state == 0 {
1079 Black
1080 } else {
1081 Colour::from_usize(state * 10) + self.cells[(r,c)].colour
1082 };
1083 } else {
1084 state += 1;
1085 }
1086 }
1087 } else if r == rs - 1 {
1088 for r in (0 .. rs).rev() {
1089 if self.cells[(r,c)].colour != Black && self.cells[(r,c-1)].colour == Black && self.cells[(r,c+1)].colour == Black {
1090 self.cells[(r,c)].colour = if state == 0 {
1091 Black
1092 } else {
1093 Colour::from_usize(state * 10) + self.cells[(r,c)].colour
1094 };
1095 } else {
1096 state += 1;
1097 }
1098 }
1099 } else if c == 0 {
1100 for c in 0 .. cs {
1101 if self.cells[(r,c)].colour != Black && self.cells[(r-1,c)].colour == Black && self.cells[(r+1,c)].colour == Black {
1102 self.cells[(r,c)].colour = if state == 0 {
1103 Black
1104 } else {
1105 Colour::from_usize(state * 10) + self.cells[(r,c)].colour
1106 };
1107 } else {
1108 state += 1;
1109 }
1110 }
1111 } else if c == cs - 1 {
1112 for c in (0 .. cs).rev() {
1113 if self.cells[(r,c)].colour != Black && self.cells[(r-1,c)].colour == Black && self.cells[(r+1,c)].colour == Black {
1114 self.cells[(r,c)].colour = if state == 0 {
1115 Black
1116 } else {
1117 Colour::from_usize(state * 10) + self.cells[(r,c)].colour
1118 };
1119 } else {
1120 state += 1;
1121 }
1122 }
1123 }
1124 }
1125 }
1126 }
1127
1128 pub fn draw_line_row(&mut self, s1: &Shape, s2: &Shape, colour: Colour, overwrite: bool, fill: bool) {
1129 let r1 = s1.orow;
1130 let c1 = s1.ocol;
1131 let r2 = s2.orow;
1132 let c2 = s2.ocol;
1133
1134 self.draw_line_row_coords(r1, c1, r2, c2, colour, overwrite, fill, s1.cells.columns);
1135 }
1136
1137 #[allow(clippy::too_many_arguments)]
1138 pub fn draw_line_row_coords(&mut self, r1: usize, c1: usize, r2: usize, c2: usize, colour: Colour, overwrite: bool, fill: bool, thick: usize) {
1139 if r1 == r2 && c1 != c2 {
1140 for y in c1.min(c2)+1 .. c1.max(c2) {
1141 for t in 0 .. thick {
1142 if self.cells.rows <= r1+t || self.cells.columns <= y {
1143 break;
1144 }
1145 if overwrite || self.cells[(r1+t,y)].colour == Black {
1146 if overwrite && fill && self.cells[(r1+t,y)].colour != Black {
1147 self.flood_fill_bg_mut(r1+t, y, self.cells[(r1+t,y)].colour, NoColour, colour);
1148 } else {
1149 if overwrite && fill && self.cells[(r1+t-1,y)].colour != Black {
1150 self.flood_fill_bg_mut(r1+t-1, y, self.cells[(r1+t-1,y)].colour, NoColour, colour);
1151 }
1152 self.cells[(r1+t,y)].colour = colour;
1153 if overwrite && fill && self.cells[(r1+t+1,y)].colour != Black {
1154 self.flood_fill_bg_mut(r1+t+1, y, self.cells[(r1+t+1,y)].colour, NoColour, colour);
1155 }
1156 }
1157 }
1158 }
1159 }
1160 }
1161 }
1162
1163 pub fn draw_line_col(&mut self, s1: &Shape, s2: &Shape, colour: Colour, overwrite: bool, fill: bool) {
1164 let r1 = s1.orow;
1165 let c1 = s1.ocol;
1166 let r2 = s2.orow;
1167 let c2 = s2.ocol;
1168
1169 self.draw_line_col_coords(r1, c1, r2, c2, colour, overwrite, fill, s1.cells.rows);
1170 }
1171
1172 #[allow(clippy::too_many_arguments)]
1173 pub fn draw_line_col_coords(&mut self, r1: usize, c1: usize, r2: usize, c2: usize, colour: Colour, overwrite: bool, fill: bool, thick: usize) {
1174 if c1 == c2 && r1 != r2 {
1175 for x in r1.min(r2)+1 .. r1.max(r2) {
1176 for t in 0 .. thick {
1177 if self.cells.rows <= x || self.cells.columns <= c1+t {
1178 break;
1179 }
1180
1181 if overwrite || self.cells[(x,c1+t)].colour == Black {
1182 if overwrite && fill && self.cells[(x,c1+t)].colour != Black {
1183 self.flood_fill_bg_mut(x, c1+t, self.cells[(x,c1+t)].colour, NoColour, colour);
1184 } else {
1185 if overwrite && fill && self.cells[(x,c1+t-1)].colour != Black {
1186 self.flood_fill_bg_mut(x, c1+t-1, self.cells[(x,c1+t-1)].colour, NoColour, colour);
1187 }
1188 self.cells[(x,c1+t)].colour = colour;
1189 if overwrite && fill && self.cells[(x,c1+t+1)].colour != Black {
1190 self.flood_fill_bg_mut(x, c1+t+1, self.cells[(x,c1+t+1)].colour, NoColour, colour);
1191 }
1192 }
1193 }
1194 }
1195 }
1196 }
1197 }
1198
1199 pub fn extend_border(&self) -> Self {
1200 let mut grid = Self::new(self.cells.rows + 2, self.cells.columns + 2, Black);
1201
1202 for ((r, c), cell) in self.cells.items() {
1203 grid.cells[(r + 1,c + 1)].row = r + 1;
1204 grid.cells[(r + 1,c + 1)].col = c + 1;
1205 grid.cells[(r + 1,c + 1)].colour = cell.colour;
1206 }
1207
1208 grid.colour = self.colour;
1209
1210 let rows = grid.cells.rows;
1211 let cols = grid.cells.columns;
1212
1213 for r in 0 .. rows {
1214 grid.cells[(r,0)].row = r;
1215 grid.cells[(r,0)].col = 0;
1216 grid.cells[(r,0)].colour = grid.cells[(r,1)].colour;
1217
1218 grid.cells[(r,cols-1)].row = r;
1219 grid.cells[(r,cols-1)].col = cols-2;
1220 grid.cells[(r,cols-1)].colour = grid.cells[(r,cols-2)].colour;
1221 }
1222
1223 for c in 0 .. cols {
1224 grid.cells[(0,c)].row = 0;
1225 grid.cells[(0,c)].col = c;
1226 grid.cells[(0,c)].colour = grid.cells[(1,c)].colour;
1227
1228 grid.cells[(rows-1,c)].row = rows-2;
1229 grid.cells[(rows-1,c)].col = c;
1230 grid.cells[(rows-1,c)].colour = grid.cells[(rows-2,c)].colour;
1231 }
1232
1233 grid
1234 }
1235
1236 fn extend(&self, lr: bool) -> Self {
1237 self.extend_by(lr, 2)
1238 }
1239
1240 fn extend_by(&self, lr: bool, amount: usize) -> Self {
1241 let rows = self.cells.rows;
1242 let cols = self.cells.columns;
1243 let mut grid = if lr {
1244 Self::new(rows, cols * amount, Black)
1245 } else {
1246 Self::new(rows * amount, cols, Black)
1247 };
1248
1249 for ((r, c), cell) in self.cells.items() {
1250 grid.cells[(r,c)].row = r;
1251 grid.cells[(r,c)].col = c;
1252 grid.cells[(r,c)].colour = cell.colour;
1253 }
1254
1255 grid.colour = self.colour;
1256
1257 grid
1258 }
1259
1260 pub fn extend_right(&self) -> Self {
1283 self.extend(true)
1284 }
1285
1286 pub fn extend_left(&self) -> Self {
1287 self.mirrored_cols().extend(true).mirrored_cols()
1288 }
1289
1290 pub fn extend_down(&self) -> Self {
1291 self.extend(false)
1292 }
1293
1294 pub fn extend_up(&self) -> Self {
1295 self.mirrored_rows().extend(false).mirrored_rows()
1296 }
1297
1298 pub fn extend_right_by(&self, amount: usize) -> Self {
1299 self.extend_by(true, amount)
1300 }
1301
1302 pub fn extend_left_by(&self, amount: usize) -> Self {
1303 self.mirrored_cols().extend_by(true, amount).mirrored_cols()
1304 }
1305
1306 pub fn extend_down_by(&self, amount: usize) -> Self {
1307 self.extend_by(false, amount)
1308 }
1309
1310 pub fn extend_up_by(&self, amount: usize) -> Self {
1311 self.mirrored_rows().extend_by(false, amount).mirrored_rows()
1312 }
1313
1314 pub fn dup_func(&self, lr: bool, func: &dyn Fn(&Self) -> Self) -> Self {
1315 let rows = self.cells.rows;
1316 let cols = self.cells.columns;
1317
1318 let mut grid = if lr {
1320 let temp = self.mirrored_cols().extend_right();
1321 let temp = &func(&temp);
1322
1323 temp.mirrored_cols()
1324 } else {
1325 let temp = self.mirrored_rows().extend_down();
1326 let temp = &func(&temp);
1327
1328 temp.mirrored_rows()
1329 };
1330
1331 for r in 0 .. rows {
1332 for c in 0 .. cols {
1333 grid.cells[(r,c)].row = r;
1334 grid.cells[(r,c)].col = c + cols;
1335 grid.cells[(r,c)].colour = self.cells[(r,c)].colour;
1336 }
1337 }
1338
1339 grid.colour = self.colour;
1340
1341 grid
1342 }
1343
1344 fn dup(&self, lr: bool) -> Self {
1345 self.dup_func(lr, &|g| g.clone())
1346 }
1347
1348 pub fn dup_right(&self) -> Self {
1349 self.dup(true)
1350 }
1351
1352 pub fn dup_left(&self) -> Self {
1353 self.mirrored_cols().dup(true).mirrored_cols()
1354 }
1355
1356 pub fn dup_down(&self) -> Self {
1357 self.dup(false)
1358 }
1359
1360 pub fn dup_up(&self) -> Self {
1361 self.mirrored_rows().dup(false).mirrored_rows()
1362 }
1363
1364 pub fn dup_right_func(&self, func: &dyn Fn(&Self) -> Self) -> Self {
1365 self.dup_func(true, &func)
1366 }
1367
1368 pub fn dup_left_func(&self, func: &dyn Fn(&Self) -> Self) -> Self {
1369 self.mirrored_cols().dup_func(true, &func).mirrored_cols()
1370 }
1371
1372 pub fn dup_down_func(&self, func: &dyn Fn(&Self) -> Self) -> Self {
1373 self.dup_func(false, &func)
1374 }
1375
1376 pub fn dup_up_func(&self, func: &dyn Fn(&Self) -> Self) -> Self {
1377 self.mirrored_rows().dup_func(false, &func).mirrored_rows()
1378 }
1379
1380 pub fn mirror_dir_func(&self, lr: bool, func: &dyn Fn(&Self) -> Self) -> Self {
1381 let rows = self.cells.rows;
1382 let cols = self.cells.columns;
1383
1384 let mut grid = if lr {
1385 let temp = self.extend_right();
1386 let temp = &func(&temp);
1387
1388 temp.mirrored_cols()
1389 } else {
1390 let temp = self.extend_down();
1391 let temp = &func(&temp);
1392
1393 temp.mirrored_rows()
1394 };
1395
1396 for r in 0 .. rows {
1397 for c in 0 .. cols {
1398 if r < grid.cells.rows && c < grid.cells.columns {
1399 grid.cells[(r,c)].row = r;
1400 grid.cells[(r,c)].col = c;
1401 grid.cells[(r,c)].colour = self.cells[(r,c)].colour;
1402 }
1403 }
1404 }
1405
1406 grid.colour = self.colour;
1407
1408 grid
1409 }
1410
1411 pub fn mirror_dir(&self, lr: bool) -> Self {
1412 self.mirror_dir_func(lr, &|g| g.clone())
1413 }
1414
1415 pub fn mirror_right(&self) -> Self {
1416 self.mirror_dir(true)
1417 }
1418
1419 pub fn mirror_left(&self) -> Self {
1420 self.mirrored_cols().mirror_dir(true).mirrored_cols()
1421 }
1422
1423 pub fn mirror_down(&self) -> Self {
1424 self.mirror_dir(false)
1425 }
1426
1427 pub fn mirror_up(&self) -> Self {
1428 self.mirrored_rows().mirror_dir(false).mirrored_rows()
1429 }
1430
1431 pub fn mirror_right_func(&self, func: &dyn Fn(&Self) -> Self) -> Self {
1432 self.mirror_dir_func(true, &func)
1433 }
1434
1435 pub fn mirror_left_func(&self, func: &dyn Fn(&Self) -> Self) -> Self {
1436 self.mirrored_cols().mirror_dir_func(true, &func).mirrored_cols()
1437 }
1438
1439 pub fn mirror_down_func(&self, func: &dyn Fn(&Self) -> Self) -> Self {
1440 self.mirror_dir_func(false, &func)
1441 }
1442
1443 pub fn mirror_up_func(&self, func: &dyn Fn(&Self) -> Self) -> Self {
1444 self.mirrored_rows().mirror_dir_func(false, &func).mirrored_rows()
1445 }
1446
1447 pub fn pixels(&self) -> usize {
1448 self.cells.values()
1449 .filter(|c| c.colour != Black).
1450 count()
1451 }
1452
1453 pub fn transform(&self, trans: Transformation) -> Self {
1454 match trans {
1455 NoTrans => self.clone(),
1456 MirrorRow => self.mirrored_rows(),
1457 MirrorCol => self.mirrored_cols(),
1458 Trans => self.transposed(),
1459 Rotate90 => self.rot_rect_90(),
1460 Rotate180 => self.rot_rect_180(),
1461 Rotate270 => self.rot_rect_270(),
1462 Rotate90MirrorRow => self.rot_rect_90().mirrored_rows(),
1463 Rotate180MirrorRow => self.rot_rect_180().mirrored_rows(),
1464 Rotate270MirrorRow => self.rot_rect_270().mirrored_rows(),
1465 Rotate90MirrorCol => self.rot_rect_90().mirrored_cols(),
1466 Rotate180MirrorCol => self.rot_rect_180().mirrored_cols(),
1467 Rotate270MirrorCol => self.rot_rect_270().mirrored_cols(),
1468 MirrorRowRotate90 => self.mirrored_rows().rot_rect_90(),
1469 MirrorRowRotate180 => self.mirrored_rows().rot_rect_180(),
1470 MirrorRowRotate270 => self.mirrored_rows().rot_rect_270(),
1471 MirrorColRotate90 => self.mirrored_cols().rot_rect_90(),
1472 MirrorColRotate180 => self.mirrored_cols().rot_rect_180(),
1473 MirrorColRotate270 => self.mirrored_cols().rot_rect_270(),
1474 }
1475 }
1476
1477 pub fn inverse_transform(&self, trans: Transformation) -> Self {
1478 let trans = Transformation::inverse(&trans);
1479
1480 self.transform(trans)
1481 }
1482
1483 pub fn inverse_colour(&self) -> Self {
1484 let colour = self.colour();
1485 let mut inv = self.clone();
1486
1487 for cell in inv.cells.values_mut() {
1488 if cell.colour == Black {
1489 cell.colour = colour;
1490 } else {
1491 cell.colour = Black;
1492 }
1493 }
1494
1495 inv
1496 }
1497
1498 pub fn colour(&self) -> Colour {
1499 let mut colour = Black;
1500
1501 for c in self.cells.values() {
1502 if colour == Black && c.colour != Black {
1503 colour = c.colour;
1504 } else if c.colour != Black && c.colour != colour {
1505 return self.colour;
1506 }
1507 }
1508
1509 colour
1510 }
1511
1512 pub fn size(&self) -> usize {
1513 self.cells.columns * self.cells.rows
1514 }
1515
1516 pub fn same_size(&self, other: &Self) -> bool {
1517 self.size() == other.size()
1518 }
1519
1520 pub fn same_shape(&self, other: &Self) -> bool {
1521 self.cells.rows == other.cells.rows && self.cells.columns == other.cells.columns
1522 }
1523
1524 pub fn dimensions(&self) -> (usize, usize) {
1525 (self.cells.rows, self.cells.columns)
1526 }
1527
1528 pub fn add_border(&self, n: usize) -> Self {
1529 self.add_border_colour(n, Black)
1530 }
1531
1532 pub fn add_border_colour(&self, n: usize, colour: Colour) -> Self {
1533 let mut g = Self::new(self.cells.rows + n * 2, self.cells.columns + n * 2, colour);
1534
1535 g.copy_to_position_mut(self, n, n);
1536
1537 g
1538 }
1539
1540 pub fn remove_border(&self, n: usize) -> Self {
1541 if self.cells.rows < n * 2 || self.cells.columns < n * 2 {
1542 return self.clone();
1543 }
1544
1545 self.subgrid(n, self.cells.rows - n * 2, n, self.cells.columns - n * 2)
1546 }
1547
1548 pub fn max_dim(&self) -> usize {
1549 self.cells.rows.max(self.cells.columns)
1550 }
1551
1552 pub fn derive_missing_rule(&self, other: &Self) -> Self {
1553 if self.cells.rows == 1 || self.cells.columns == 0 ||other.cells.rows % self.cells.rows != 0 || other.cells.columns % self.cells.columns != 0 {
1554 return Self::trivial();
1555 }
1556
1557 let sg = other.subgrid(0, self.cells.rows, 0, self.cells.columns);
1558
1559 match self.diff(&sg) {
1560 Some(diff) => diff,
1561 None => Self::trivial(),
1562 }
1563 }
1564
1565 pub fn apply_missing_rule(&self, other: &Self) -> Self {
1566 let mut grid = self.clone();
1567
1568 for ((r, c), cell) in self.cells.items() {
1569 if cell.colour != Black {
1570 grid.copy_centre(r, c, other);
1571 }
1572 }
1573
1574 grid
1575 }
1576
1577 pub fn copy_centre(&mut self, cr: usize, cc: usize, other: &Self) {
1578 if other == &Self::trivial() {
1579 return;
1580 }
1581 let centre_r = (other.cells.rows / 2) as isize;
1582 let centre_c = (other.cells.columns / 2) as isize;
1583
1584 let or = centre_r - cr as isize;
1585 let oc = centre_c - cc as isize;
1586 let rs = if or < 0 { 0 } else { or as usize };
1587 let re = if or < 0 {
1588 let incdec = if or < -1 { 1 } else { -1 };
1590 (other.cells.rows as isize + or + incdec) as usize
1591 } else {
1592 other.cells.rows
1593 };
1594 let cs = if oc < 0 { 0 } else { oc as usize };
1595 let ce = if oc < 0 {
1596 let incdec = if oc < -1 { 1 } else { -1 };
1598 (other.cells.columns as isize + oc + incdec) as usize
1599 } else {
1600 other.cells.columns
1601 };
1602
1603 for r in rs .. re {
1604 for c in cs .. ce {
1605 let colour = other.cells[(r, c)].colour;
1606 let sr = (r as isize - or) as usize;
1607 let sc = (c as isize - oc) as usize;
1608
1609 if sr >= self.cells.rows || sc >= self.cells.columns {
1611 continue;
1612 }
1613
1614 if !colour.is_same() && colour != Black && self.cells[(sr, sc)].colour == Black {
1615 self.cells[(sr, sc)].colour = colour.to_base();
1616 }
1617 }
1618 }
1619 }
1620
1621 pub fn fill_border(&mut self) {
1622 let hr = self.cells.rows / 2;
1623 let hc = self.cells.columns / 2;
1624
1625 for layer in 0 .. hr.min(hc) {
1626 let mut cc = NoColour;
1627
1628 for i in layer .. self.cells.rows - layer {
1629 let c = self.cells[(i,layer)].colour;
1630
1631 if c != Black && cc == NoColour {
1632 cc = c;
1633 } else if c != Black && c != cc {
1634 return;
1635 }
1636 }
1637 for i in layer .. self.cells.columns - layer {
1638 let c = self.cells[(layer,i)].colour;
1639
1640 if c != Black && cc == NoColour {
1641 cc = c;
1642 } else if c != Black && c != cc {
1643 return;
1644 }
1645 }
1646for i in layer .. self.cells.rows - layer {
1649 let c = self.cells[(i,layer)].colour;
1650
1651 if c == Black {
1652 self.cells[(i,layer)].colour = cc;
1653 }
1654 }
1655 for i in layer .. self.cells.columns - layer {
1656 let c = self.cells[(layer, i)].colour;
1657
1658 if c == Black {
1659 self.cells[(layer,i)].colour = cc;
1660 }
1661 }
1662 }
1663 }
1664
1665 pub fn has_colour(&self, tlr: usize, tlc: usize, rlen: usize, clen: usize, colour: Colour) -> bool {
1701 for r in tlr .. rlen {
1702 for c in tlc .. clen {
1703 if self.cells[(r,c)].colour == colour {
1704 return true;
1705 }
1706 }
1707 }
1708
1709 false
1710 }
1711
1712 pub fn find_row_seq(&self, sr: usize, sc: usize, seq: &[Colour], width: usize) -> (usize, usize) {
1713 let mut cnt = 0;
1714 let mut xp = 0;
1715 let mut rs = usize::MAX;
1716 let mut cs = usize::MAX;
1717
1718 'outer:
1719 for r in 0 .. self.cells.columns - width {
1720 for c in 0 .. self.cells.rows - seq.len() {
1721 if c == sr+1 && r <= sc { continue 'outer};
1722 let cell = self.cells[(c,r)].clone();
1723 if xp != r {
1724 xp = r;
1725 cnt = 0;
1726 rs = usize::MAX;
1727 cs = usize::MAX;
1728 }
1729 if seq[cnt] == cell.colour {
1730 if !self.has_colour(c, r, seq.len(), width, Black) {
1731 if cnt == 0 {
1732 rs = c;
1733 cs = r;
1734 }
1735if cnt == seq.len() - 1 {
1738 break 'outer;
1739 }
1740 cnt += 1;
1741 }
1742 } else if cnt > 0 {
1743 cnt = 0;
1744 rs = usize::MAX;
1745 cs = usize::MAX;
1746 }
1747 }
1748 }
1749
1750 (rs, cs)
1751 }
1752
1753 pub fn find_col_seq(&self, sr: usize, sc: usize, seq: &[Colour], length: usize) -> (usize, usize) {
1754 let mut cnt = 0;
1755 let mut rp = 0;
1756 let mut rs = usize::MAX;
1757 let mut cs = usize::MAX;
1758
1759 'outer:
1760 for r in 0 .. self.cells.rows - length {
1761 for c in 0 .. self.cells.columns - seq.len() {
1762 if c == sc+1 && r <= sr { continue 'outer};
1763 let cell = self.cells[(r,c)].clone();
1764 if rp != r {
1765 rp = r;
1766 cnt = 0;
1767 rs = usize::MAX;
1768 cs = usize::MAX;
1769 }
1770 if seq[cnt] == cell.colour {
1771 if !self.has_colour(r, c, length, seq.len(), Black) {
1772 if cnt == 0 {
1773 rs = r;
1774 cs = c;
1775 }
1776 cnt += 1;
1777 if cnt == seq.len() {
1778 break 'outer;
1779 }
1780 }
1781 } else if cnt > 0 {
1782 cnt = 0;
1783 rs = usize::MAX;
1784 cs = usize::MAX;
1785 }
1786 }
1787 }
1788
1789 (rs, cs)
1790 }
1791
1792 pub fn colour_every_nxn_for_m(colour: Colour, side: usize, n: usize, m: usize) -> Self {
1793 if m == 0 || n == 0 {
1794 return Self::trivial();
1795 }
1796 let mut grid = Self::new(side, side, Black);
1797 let mut count = 0;
1798
1799 'outer:
1800 for r in 0 .. side {
1801 for c in 0 .. side {
1802 if (r + grid.cells.rows * c) % n == 0 {
1803 grid.cells[(r, c)].colour = colour;
1804 count += 1;
1805 }
1806 if count == m {
1807 break 'outer;
1808 }
1809 }
1810 }
1811
1812 grid
1813 }
1814
1815 pub fn colour_dimensions(&self, colour: Colour) -> (usize, usize) {
1816 let mut min_r: usize = usize::MAX;
1817 let mut max_r: usize = 0;
1818 let mut min_c: usize = usize::MAX;
1819 let mut max_c: usize = 0;
1820
1821 for ((x, y), c) in self.cells.items() {
1822 if c.colour == colour {
1823 min_r = x.min(min_r);
1824 max_r = x.max(max_r);
1825 min_c = y.min(min_c);
1826 max_c = y.max(max_c);
1827 }
1828 }
1829
1830 (max_r - min_r + 1, max_c - min_c + 1)
1831 }
1832
1833 pub fn bigger(&self, other: &Self) -> bool {
1834 self.size() > other.size()
1835 }
1836
1837 pub fn smaller(&self, other: &Self) -> bool {
1838 self.size() < other.size()
1839 }
1840
1841 pub fn cell_count(&self) -> usize {
1842 self.cell_count_colour(Black)
1843 }
1844
1845 pub fn cell_count_colour(&self, colour: Colour) -> usize {
1846 self.cells.values().filter(|c| c.colour != colour).count()
1847 }
1848
1849 pub fn flood_fill(&self, x: usize, y: usize, ignore_colour: Colour, new_colour: Colour) -> Self {
1850 self.flood_fill_bg(x, y, ignore_colour, Black, new_colour)
1851 }
1852
1853 pub fn flood_fill_bg(&self, r: usize, c: usize, ignore_colour: Colour, bg: Colour, new_colour: Colour) -> Self {
1854 let mut grid = self.clone();
1855
1856 grid.flood_fill_bg_mut(r, c, ignore_colour, bg, new_colour);
1857
1858 grid
1859 }
1860
1861 pub fn flood_fill_mut(&mut self, r: usize, c: usize, ignore_colour: Colour, new_colour: Colour) {
1862 self.flood_fill_bg_mut(r, c, ignore_colour, Black, new_colour)
1863 }
1864
1865 pub fn flood_fill_border_mut(&mut self, ignore_colour: Colour, new_colour: Colour) {
1866 let rows = self.cells.rows;
1867 let cols = self.cells.columns;
1868
1869 for r in 0 .. rows {
1870 for c in 0 .. cols {
1871 if (r == 0 || c == 0 || r == rows - 1 || c == cols - 1) && self.cells[(r, c)].colour == Black {
1872 self.flood_fill_mut(r, c, ignore_colour, new_colour);
1873 }
1874 }
1875 }
1876 }
1877
1878 pub fn flood_fill_bg_mut(&mut self, r: usize, c: usize, ignore_colour: Colour, bg: Colour, new_colour: Colour) {
1879 let reachable = self.cells.bfs_reachable((r, c), false, |i| self.cells[i].colour == bg || self.cells[i].colour == ignore_colour);
1880
1881 reachable.iter().for_each(|&i| self.cells[i].colour = new_colour);
1882 }
1883
1884 pub fn flood_fill_from_seeds(&self, ignore_colour: Colour, new_colour: Colour) -> Self {
1885 let mut grid = self.clone();
1886
1887 let coloured: Vec<(usize, usize)> = grid.cells.items()
1888 .filter(|(_, cell)| cell.colour == ignore_colour)
1889 .map(|(i, _)| i)
1890 .collect();
1891
1892 coloured.iter()
1893 .for_each(|(r, c)| grid.flood_fill_mut(*r, *c, ignore_colour, new_colour));
1894
1895 grid
1896 }
1897
1898 pub fn subgrid(&self, tlr: usize, sr: usize, tlc: usize, sc: usize) -> Self {
1899 if sr == 0 || sc == 0 {
1900 return Grid::trivial();
1901 }
1902
1903 let mut m = Matrix::new(sr, sc, Cell::new(0, 0, 0));
1904
1905 for r in 0 .. sr {
1906 for c in 0 .. sc {
1907 m[(r,c)].row = self.cells[(r + tlr,c + tlc)].row;
1908 m[(r,c)].col = self.cells[(r + tlr,c + tlc)].col;
1909 m[(r,c)].colour = self.cells[(r + tlr,c + tlc)].colour;
1910 }
1911 }
1912
1913 Self::new_from_matrix(&m)
1914 }
1915
1916 pub fn cell_colours(&self) -> Vec<Colour> {
1917 self.cell_colour_cnt_map().keys().map(|c| *c).collect()
1918 }
1919
1920 pub fn cell_colour_cnt_map(&self) -> BTreeMap<Colour, usize> {
1921 let mut h: BTreeMap<Colour, usize> = BTreeMap::new();
1922
1923 for c in self.cells.values() {
1924 if c.colour != Black {
1925 *h.entry(c.colour).or_insert(0) += 1;
1926 }
1927 }
1928
1929 h
1930 }
1931
1932 pub fn cell_colour_posn_map(&self) -> BTreeMap<Colour, Vec<(usize, usize)>> {
1933 let mut h: BTreeMap<Colour, Vec<(usize, usize)>> = BTreeMap::new();
1934
1935 for c in self.cells.values() {
1936 if c.colour != Black {
1937 h.entry(c.colour).or_default().push((c.row, c.col));
1938 }
1939 }
1940
1941 h
1942 }
1943
1944 pub fn majority_colour(&self) -> Colour {
1945 let cccm = self.cell_colour_cnt_map();
1946
1947 let mx = cccm.iter().map(|(c,n)| (n,c)).max();
1948
1949 if let Some(mx) = mx {
1950 *mx.1
1951 } else {
1952 NoColour
1953 }
1954 }
1955
1956 pub fn minority_colour(&self) -> Colour {
1957 let cccm = self.cell_colour_cnt_map();
1958
1959 let mn = cccm.iter().map(|(c,n)| (n,c)).min();
1960
1961 if let Some(mn) = mn {
1962 *mn.1
1963 } else {
1964 NoColour
1965 }
1966 }
1967
1968 pub fn get_diff_colour(&self, other: &Self) -> Colour {
1969 let mut in_colour = Black;
1970
1971 if let Some(diff) = self.diff(other) {
1972 let colour = diff.cell_colour_cnt_map_diff();
1973
1974 if colour.len() != 1 {
1975 return in_colour;
1976 }
1977
1978 if let Some((colour, _)) = colour.first_key_value() {
1979 in_colour = colour.to_base()
1980 }
1981 }
1982
1983 in_colour
1984 }
1985
1986 pub fn cell_colour_cnt_map_diff(&self) -> BTreeMap<Colour, usize> {
1987 let mut h: BTreeMap<Colour, usize> = BTreeMap::new();
1988
1989 for c in self.cells.values() {
1990 if c.colour >= DiffBlack && c.colour <= DiffBrown {
1991 *h.entry(c.colour).or_insert(0) += 1;
1992 }
1993 }
1994
1995 h
1996 }
1997
1998 pub fn even_rows(&self) -> bool {
1999 self.cells.rows % 2 == 0
2000 }
2001
2002 pub fn even_columns(&self) -> bool {
2003 self.cells.columns % 2 == 0
2004 }
2005
2006 pub fn border_top(&self) -> bool {
2007 self.cells.items()
2008 .filter(|((r, _), cell)| *r == 0 && cell.colour != Black)
2009 .count() == self.cells.columns - 1
2010 }
2011
2012 pub fn border_bottom(&self) -> bool {
2013 self.cells.items()
2014 .filter(|((r, _), cell)| *r == self.cells.columns - 1 && cell.colour != Black)
2015 .count() == self.cells.columns - 1
2016 }
2017
2018 pub fn border_left(&self) -> bool {
2019 self.cells.items()
2020 .filter(|((_, c), cell)| *c == 0 && cell.colour != Black)
2021 .count() == self.cells.rows - 1
2022 }
2023
2024 pub fn border_right(&self) -> bool {
2025 self.cells.items()
2026 .filter(|((_, c), cell)| *c == self.cells.rows - 1 && cell.colour != Black)
2027 .count() == self.cells.rows - 1
2028 }
2029
2030 pub fn has_border(&self) -> bool {
2031 self.border_top() && self.border_bottom() && self.border_left() && self.border_right()
2032 }
2033
2034 pub fn mirrored_rows(&self) -> Self {
2035 let mut m = self.cells.flipped_ud();
2036
2037 for (r, c) in self.cells.keys() {
2038 m[(r, c)].row = r;
2039 m[(r, c)].col = c;
2040 }
2041
2042 Self::new_from_matrix(&m)
2043 }
2044
2045 pub fn mirrored_cols(&self) -> Self {
2046 let mut m = self.cells.flipped_lr();
2047
2048 for (x, y) in self.cells.keys() {
2049 m[(x, y)].row = x;
2050 m[(x, y)].col = y;
2051 }
2052
2053 Self::new_from_matrix(&m)
2054 }
2055
2056 fn compare_colour(this: &Matrix<Cell>, other: &Matrix<Cell>) -> bool {
2057 if this.columns == 1 || this.rows == 1 || this.columns != other.columns || this.rows != other.rows {
2058 return false;
2059 }
2060
2061 for x in 0 .. this.rows {
2062 for y in 0 .. this.columns {
2063 if this[(x, y)].colour != other[(x, y)].colour {
2064 return false
2065 }
2066 }
2067 }
2068
2069 true
2070 }
2071
2072 pub fn populate_skew_edge_lr(&self, shape: &Shape, colour: Colour) -> Shape {
2073 let rs = self.row_skew();
2074 let mut new_shape = shape.clone();
2075
2076 for r in 0 .. rs as usize {
2077 for c in 0 .. self.cells.columns {
2078 if self.cells[(r,c)].colour == colour {
2079 if shape.cells.rows >= r + 1 {
2080 new_shape.cells[(r - shape.orow,c - shape.ocol)].colour = self.cells[(shape.cells.rows - r - 1,c)].colour;
2081 } else {
2082 new_shape.cells[(r - shape.orow,c - shape.ocol)].colour = self.cells[(r,c)].colour;
2083 }
2084 } else if self.cells[(c,r)].colour == colour {
2085 if shape.cells.columns >= c + 1 {
2086 new_shape.cells[(c - shape.orow,r - shape.ocol)].colour = self.cells[(r,shape.cells.columns - c - 1)].colour;
2087 } else {
2088 new_shape.cells[(c - shape.orow,r - shape.ocol)].colour = self.cells[(r,c)].colour;
2089 }
2090 }
2091 }
2092 }
2093
2094 new_shape
2095 }
2096
2097 pub fn populate_skew_edge_tb(&self, shape: &Shape, colour: Colour) -> Shape {
2098 let grid = self.rotated_270(1);
2099 let mut shape = shape.rot_rect_270();
2100
2101 let tr = shape.orow;
2102
2103 shape.orow = shape.ocol;
2104 shape.ocol = tr;
2105
2106 let shape = grid.populate_skew_edge_lr(&shape, colour);
2107
2108 let mut shape = shape.rot_rect_90();
2109
2110 let tr = shape.orow;
2111
2112 shape.orow = shape.ocol;
2113 shape.ocol = tr;
2114
2115 shape
2116 }
2117
2118 pub fn is_mirror_rows(&self) -> bool {
2119 if self.cells.len() <= 4 {
2120 return false
2121 }
2122 let copy = self.cells.flipped_ud();
2123
2124 Self::compare_colour(&self.cells, ©)
2125 }
2126
2127 pub fn is_mirror_cols(&self) -> bool {
2128 if self.cells.len() <= 4 {
2129 return false
2130 }
2131 let copy = self.cells.flipped_lr();
2132
2133 Self::compare_colour(&self.cells, ©)
2134 }
2135
2136 pub fn is_symmetric(&self) -> bool {
2137 self.is_mirror_rows() && self.is_mirror_cols()
2138 }
2139
2140 pub fn is_mirror_offset_rows(&self, skew: i32) -> bool {
2141 let copy = if skew < 0 {
2142 self.cells.slice(0 .. (self.cells.rows as i32 + skew) as usize, 0 .. self.cells.columns)
2143 } else {
2144 self.cells.slice((skew as usize) .. self.cells.rows, 0 .. self.cells.columns)
2145 };
2146
2147 if copy.is_err() { return false; };
2148
2149 let this = copy.unwrap();
2150 let flipped_copy = this.flipped_ud();
2151
2152 Self::compare_colour(&this, &flipped_copy)
2153 }
2154
2155 pub fn is_mirror_offset_cols(&self, skew: i32) -> bool {
2156 let copy = if skew < 0 {
2157 self.cells.slice(0 .. self.cells.rows, 0 .. (self.cells.columns - skew.unsigned_abs() as usize))
2158 } else {
2159 self.cells.slice(0 .. self.cells.rows, (skew as usize) .. self.cells.columns)
2160 };
2161
2162 if copy.is_err() { return false; };
2163
2164 let this = copy.unwrap();
2165 let flipped_copy = this.flipped_lr();
2166
2167 Self::compare_colour(&this, &flipped_copy)
2168 }
2169
2170 pub fn is_panelled_rows(&self) -> bool {
2171 let len: usize = self.cells.rows;
2172 let half: usize = len / 2;
2173
2174 if len < 4 || half == 0 { return false }
2175
2176 let offset: usize = if len % 2 == 0 { 0 } else { 1 };
2177
2178 for c in 0 .. self.cells.columns {
2179 for r in 0 .. half {
2180 if self.cells[(r, c)].colour != self.cells[(half + offset + r, c)].colour {
2181 return false;
2182 }
2183 }
2184 }
2185
2186 true
2187 }
2188
2189 pub fn is_panelled_cols(&self) -> bool {
2190 let len: usize = self.cells.columns;
2191 let half: usize = len / 2;
2192
2193 if len < 4 || half == 0 { return false }
2194
2195 let offset: usize = if len % 2 == 0 { 0 } else { 1 };
2196
2197 for r in 0 .. self.cells.rows {
2198 for c in 0 .. half {
2199 if self.cells[(r, c)].colour != self.cells[(r, half + offset + c)].colour {
2200 return false;
2201 }
2202 }
2203 }
2204
2205 true
2206 }
2207
2208 pub fn transpose(&mut self) {
2209 if self.cells.rows != self.cells.columns {
2210 return;
2211 }
2212
2213 self.cells.transpose();
2214 }
2215
2216 pub fn transposed(&self) -> Self {
2217 if self.cells.rows != self.cells.columns {
2218 return self.clone();
2219 }
2220
2221 let mut m: Matrix<Cell> = self.cells.clone();
2222
2223 m.transpose();
2224
2225 for (r, c) in self.cells.keys() {
2226 m[(r, c)].row = r;
2227 m[(r, c)].col = c;
2228 }
2229
2230 Self::new_from_matrix(&m)
2231 }
2232
2233 pub fn inv_transposed(&self) -> Self {
2234 Self::new_from_matrix(&self.cells.rotated_cw(2).transposed())
2235 }
2236
2237 pub fn rotated_90(&self, times: usize) -> Self {
2270 if self.cells.rows != self.cells.columns || times == 0 {
2271 return self.clone();
2272 }
2273
2274 let mut m: Matrix<Cell> = self.cells.clone();
2275
2276 m.rotate_cw(times);
2277
2278 for (r, c) in self.cells.keys() {
2279 m[(r, c)].row = r;
2280 m[(r, c)].col = c;
2281 }
2282
2283 Self::new_from_matrix(&m)
2284 }
2285
2286 pub fn rotated_270(&self, times: usize) -> Self {
2287 if self.cells.rows != self.cells.columns {
2288 return self.clone();
2289 }
2290
2291 let mut m: Matrix<Cell> = self.cells.clone();
2292
2293 m.rotate_ccw(times);
2294
2295 for (r, c) in self.cells.keys() {
2296 m[(r, c)].row = r;
2297 m[(r, c)].col = c;
2298 }
2299
2300 Self::new_from_matrix(&m)
2301 }
2302
2303 pub fn rotate_90(&self, times: usize) -> Self {
2304 if times == 1 {
2305 self.rot_rect_90()
2306 } else if times == 2 {
2307 self.rot_rect_90().rot_rect_90()
2308 } else if times == 3 {
2309 self.rot_rect_90().rot_rect_90().rot_rect_90()
2310 } else {
2311 self.clone()
2312 }
2313 }
2314
2315 pub fn rot_00(&self) -> Self { self.clone()
2317 }
2318
2319 pub fn rot_90(&self) -> Self {
2320 self.rotated_90(1)
2321 }
2322
2323 pub fn rot_180(&self) -> Self {
2324 self.rotated_90(2)
2325 }
2326
2327 pub fn rot_270(&self) -> Self {
2328 self.rotated_270(1)
2329 }
2330
2331 pub fn rot_rect_90(&self) -> Self {
2332 if self.cells.rows == self.cells.columns {
2333 self.rotated_90(1)
2334 } else {
2335 let mut rot = Self::new(self.cells.columns, self.cells.rows, Black);
2336 let n = self.cells.rows;
2337
2338 for ((r, c), cell) in self.cells.items() {
2339 rot.cells[(c, n - r - 1)].colour = cell.colour;
2342 }
2343
2344 rot
2345 }
2346 }
2347
2348 pub fn rot_rect_180(&self) -> Self {
2349 if self.cells.rows == self.cells.columns {
2350 self.rotated_90(2)
2351 } else {
2352 self.rot_rect_90().rot_rect_90()
2353 }
2354 }
2355
2356 pub fn rot_rect_270(&self) -> Self {
2357 if self.cells.rows == self.cells.columns {
2358 self.rotated_270(1)
2359 } else {
2360 self.rot_rect_90().rot_rect_90().rot_rect_90()
2361 }
2362 }
2363
2364 pub fn colours(&self) -> BTreeMap<Colour, usize> {
2365 let mut h: BTreeMap<Colour, usize> = BTreeMap::new();
2366
2367 for cell in self.cells.values() {
2368 if cell.colour != Black {
2369 *h.entry(cell.colour).or_insert(0) += 1;
2370 }
2371 }
2372
2373 h
2374 }
2375
2376 pub fn min_colour(&self) -> Colour {
2377 let h = self.colours();
2378
2379 match h.iter().min_by(|col, c| col.1.cmp(c.1)) {
2380 None => NoColour,
2381 Some((colour,_)) => *colour
2382 }
2383 }
2384
2385 pub fn max_colour(&self) -> Colour {
2386 let h = self.colours();
2387
2388 match h.iter().max_by(|col, c| col.1.cmp(c.1)) {
2389 None => NoColour,
2390 Some((colour,_)) => *colour
2391 }
2392 }
2393
2394 pub fn no_colours(&self) -> usize {
2395 self.colours().len()
2396 }
2397
2398 pub fn single_colour(&self) -> Colour {
2399 let h = self.colours();
2400
2401 if h.is_empty() {
2402 NoColour
2403 } else if h.len() == 1 {
2404 *h.keys().max().unwrap()
2406 } else {
2407 Mixed
2408 }
2409 }
2410
2411 fn draw_row(&mut self, from_c: usize, to_c: usize, x: usize, colour: Colour) -> usize {
2412 for c in from_c .. to_c {
2413 self.cells[(x, c)].colour = colour;
2414 }
2415
2416 if to_c > 0 { to_c - 1 } else { 0 }
2417 }
2418
2419 fn draw_col(&mut self, from_r: usize, to_r: usize, y: usize, colour: Colour) -> usize {
2420 for r in from_r .. to_r {
2421 self.cells[(r, y)].colour = colour;
2422 }
2423
2424 if to_r > 0 { to_r - 1 } else { 0 }
2425 }
2426
2427 pub fn do_circle(&self, colour: Colour, spiral: bool) -> Self {
2428 let inc = if spiral { 2 } else { 0 };
2429 let mut copy = self.clone();
2430 let mut cinc = 0;
2431 let mut sr = 0;
2432 let mut sc = 1;
2433 let mut rows = self.cells.rows;
2434 let mut cols = self.cells.columns;
2435
2436 let mut cc = copy.draw_row(sr, cols, 0, colour);
2438 let mut cr = copy.draw_col(sc, rows, cc, colour);
2439 cc = copy.draw_row(sr, cols - 1, cr, colour);
2440 if spiral { sc += 1};
2441 copy.draw_col(sc, rows - 1, 0, colour);
2442
2443 if spiral {
2444 while sr + 1 < cc {
2445 sr += 1;
2446 sc += 1;
2447 rows -= inc;
2448 cols -= inc;
2449 cinc += inc;
2450
2451 cc = copy.draw_row(sr, cols, cinc, colour);
2452 cr = copy.draw_col(sc, rows, cc, colour);
2453 sr += 1;
2454 cc = copy.draw_row(sr, cols - 1, cr, colour);
2455 sc += 1;
2456 copy.draw_col(sc, rows - 1, cinc, colour);
2457 }
2458 }
2459
2460 Self::new_from_matrix(©.cells)
2461 }
2462
2463 pub fn circle(&self, colour: Colour) -> Self {
2464 self.do_circle(colour, false)
2465 }
2466
2467 pub fn spiral(&self, colour: Colour) -> Self {
2468 self.do_circle(colour, true)
2469 }
2470
2471 pub fn show_matrix(m: &Matrix<Cell>, diff: bool, io: bool) {
2472 let mut px = 0;
2473 for ((r, c), cell) in m.items() {
2474 if r != px {
2475 println!();
2476 px = r;
2477 } else if c != 0 {
2478 print!(" ");
2479 }
2480
2481 let colour = cell.colour.to_usize();
2482
2483 if colour == 100 {
2484 print!("{}", if !diff && io { "##" } else { "#" });
2485 } else if colour == 101 {
2486 print!("{}", if !diff && io { "**" } else { "*" });
2487 } else if diff && !io {
2488 if colour >= 10 { print!("#", ) } else { print!("{colour}") };
2489 } else if !diff && io {
2490 print!("{colour:0>2}");
2491 } else if !diff && !io {
2492 if colour >= 20 { print!("#") } else { print!("{}", colour % 10) };
2493 } else {
2494 print!("{}", colour % 10);
2495 }
2496 }
2497 }
2498
2499 fn show_any(&self, diff: bool, io: bool) {
2500 println!("--------Grid--------");
2501 Self::show_matrix(&self.cells, diff, io);
2502 println!();
2503 }
2504
2505 pub fn show_summary(&self) {
2506 println!("0/0: {}/{} {:?}", self.cells.rows, self.cells.columns, self.colour);
2507 }
2508
2509 pub fn show(&self) {
2510 self.show_any(true, false);
2511 }
2512
2513 pub fn show_full(&self) {
2514 self.show_any(false, true);
2515 }
2516
2517 pub fn show_out(&self) {
2518 self.show_any(false, false);
2519 }
2520
2521 pub fn show_io(&self) {
2522 self.show_any(true, true);
2523 }
2524
2525 pub fn has_bg_grid(&self) -> Colour {
2526 self.has_bg_grid_impl(true, true)
2527 }
2528
2529 pub fn has_bg_grid_coloured(&self) -> Colour {
2530 self.has_bg_grid_impl(false, true)
2531 }
2532
2533 pub fn has_bg_grid_not_sq(&self) -> Colour {
2534 self.has_bg_grid_impl(true, false)
2535 }
2536
2537 pub fn has_bg_grid_coloured_not_sq(&self) -> Colour {
2538 self.has_bg_grid_impl(false, false)
2539 }
2540
2541 fn has_bg_grid_impl(&self, can_be_black: bool, square: bool) -> Colour {
2542 let mut colour = NoColour;
2543
2544if self.cells.len() <= 9 || (square && self.cells.rows != self.cells.columns) {
2546 return colour;
2547 }
2548
2549 let mut nox = false; 'outerr:
2552 for x in 0 .. self.cells.rows {
2553 if can_be_black || self.cells[(x, 0)].colour != Black {
2554 colour = self.cells[(x, 0)].colour;
2555 } else {
2556 continue;
2557 }
2558
2559 if colour == self.cells[(x, 0)].colour {
2560 for c in 0 .. self.cells.columns {
2561 if colour != self.cells[(x, c)].colour {
2562 continue 'outerr;
2563 }
2564 nox = true;
2565 }
2566 break; }
2568 }
2569
2570 'outerc:
2571 for y in 0 .. self.cells.columns {
2572 if nox {
2573 if can_be_black || self.cells[(0, y)].colour != Black {
2574 colour = self.cells[(0, y)].colour;
2575 } else {
2576 continue;
2577 }
2578 }
2579 if colour == self.cells[(0, y)].colour {
2580 for r in 0 .. self.cells.rows {
2581 if colour != self.cells[(r, y)].colour {
2582 continue 'outerc;
2583 }
2584 }
2585
2586 if !can_be_black && colour == Black {
2587 break;
2588 }
2589
2590 return colour; }
2592 }
2593
2594 NoColour
2595 }
2596
2597 pub fn ray(&self, _direction: (i8, i8)) -> Shape {
2599 Shape::new_empty()
2600 }
2601
2602 pub fn r#move(&self, _direction: (i8, i8)) -> Shape {
2604 Shape::new_empty()
2605 }
2606
2607 pub fn template_shapes(&self, template: &Self) -> Shapes {
2608 let mut shapes = Shapes::new_sized(self.height(), self.width());
2609
2610 if self.height() % template.height() != 0 || self.width() % template.width() != 0 {
2611 return shapes;
2612 }
2613
2614 let rr = self.height() / template.height();
2615 let cr = self.width() / template.width();
2616
2617 for (tr, r) in (0 .. self.height()).step_by(rr).enumerate() {
2618 for (tc, c) in (0 .. self.width()).step_by(cr).enumerate() {
2619 if template.cells[(tr,tc)].colour != Black {
2620 let sg = self.subgrid(r, rr, c, cr);
2621
2622 shapes.shapes.push(sg.as_shape());
2623 }
2624 }
2625 }
2626
2627 shapes
2628 }
2629
2630 pub fn fill_template(&self, filler: &Shape) -> Self {
2631 let mut shapes = Shapes::new_sized(self.height() * filler.height(), self.width() * filler.width());
2632
2633 let rr = filler.height();
2634 let cr = filler.width();
2635
2636 for r in 0 .. self.height() {
2637 for c in 0 .. self.width() {
2638 if self.cells[(r,c)].colour != Black {
2639 let s = filler.to_position(r * rr, c * cr);
2640
2641 shapes.shapes.push(s);
2642 }
2643 }
2644 }
2645
2646 shapes.to_grid()
2647 }
2648
2649 pub fn scale_up(&self, factor: usize) -> Self {
2650 let mut cells = Matrix::new(self.cells.rows * factor, self.cells.columns * factor, Cell::new(0, 0, 0));
2651
2652 for r in 0 .. cells.rows {
2653 for c in 0 .. cells.columns {
2654 let rf = r / factor;
2655 let cf = c / factor;
2656
2657 cells[(r, c)].row = r;
2658 cells[(r, c)].col = c;
2659 cells[(r, c)].colour = self.cells[(rf, cf)].colour;
2660 }
2661 }
2662
2663 Self::new_from_matrix(&cells)
2664 }
2665
2666 pub fn scale_down(&self, factor: usize) -> Self {
2667 let mut cells = Matrix::new(self.cells.rows / factor, self.cells.columns / factor, Cell::new(0, 0, 0));
2668
2669 for r in 0 .. cells.rows {
2670 for c in 0 .. cells.columns {
2671 let rf = r * factor;
2672 let cf = c * factor;
2673
2674 cells[(r, c)].row = r;
2675 cells[(r, c)].col = c;
2676 cells[(r, c)].colour = self.cells[(rf, cf)].colour;
2677 }
2678 }
2679
2680 Self::new_from_matrix(&cells)
2681 }
2682
2683 pub fn resize(&self, factor: usize) -> Self {
2684 let mut cells = Matrix::new(self.cells.rows * factor, self.cells.columns * factor, Cell::new(0, 0, 0));
2685
2686 for ((r, c), cell) in self.cells.items() {
2687 let rf = r + factor;
2688 let cf = c + factor;
2689
2690 cells[(rf, cf)].row = r;
2691 cells[(rf, cf)].col = c;
2692 cells[(rf, cf)].colour = cell.colour;
2693 }
2694
2695 Self::new_from_matrix(&cells)
2696 }
2697
2698 pub fn resize_inc(&self, factor: usize) -> Self {
2699 let mut cells = Matrix::new(self.cells.rows + factor * 2, self.cells.columns + factor * 2, Cell::new(0, 0, 0));
2700
2701 for ((r, c), cell) in self.cells.items() {
2702 let rf = r + factor;
2703 let cf = c + factor;
2704
2705 cells[(rf, cf)].row = r;
2706 cells[(rf, cf)].col = c;
2707 cells[(rf, cf)].colour = cell.colour;
2708 }
2709
2710 Self::new_from_matrix(&cells)
2711 }
2712
2713 pub fn find_patch(&self, patch: &Shape) -> (usize, usize) {
2714 if patch.size() < 4 {
2715 return (0, 0);
2716 }
2717 let colour00 = patch.cells[(0,0)].colour;
2718 let colour01 = patch.cells[(0,1)].colour;
2719 let colour10 = patch.cells[(1,0)].colour;
2720 let colour11 = patch.cells[(1,1)].colour;
2721
2722 for ((rw, cl), cell) in self.cells.items() {
2723 if rw > patch.cells.rows || cl > patch.cells.columns {
2724 if cell.colour == colour00 && rw + patch.cells.rows < self.cells.rows && cl + patch.cells.columns < self.cells.columns && self.cells[(rw+1,cl)].colour == colour10 && self.cells[(rw,cl+1)].colour == colour01 && self.cells[(rw+1,cl+1)].colour == colour11 {
2726 let s = self.subgrid(rw, patch.cells.rows, cl, patch.cells.columns);
2727
2728 if s.equals(&patch.to_grid()) == Same {
2729 return (rw, cl);
2730 }
2731 }
2732 }
2733 }
2734
2735 (0, 0)
2736 }
2737
2738 pub fn find_axis_colour(&self, shape: &Shape) -> Colour {
2739 self.find_axis_colour_bg(shape, Black)
2740 }
2741
2742 pub fn find_axis_colour_bg(&self, shape: &Shape, bg: Colour) -> Colour {
2743 if self.cells.rows <= shape.cells.rows || self.cells.columns <= shape.cells.columns || shape.ocol >= self.cells.columns || shape.orow >= self.cells.rows || shape.orow >= self.cells.rows || shape.ocol >= self.cells.columns {
2744 return NoColour;
2745 }
2746
2747 for r in 0 .. shape.cells.rows {
2748 for c in shape.ocol .. shape.ocol + shape.cells.columns {
2749 if self.cells[(r,c)].colour != bg {
2750 return self.cells[(r,c)].colour;
2751 }
2752 }
2753 }
2754 for c in 0 .. shape.cells.columns {
2755 for r in shape.orow .. shape.orow + shape.cells.rows {
2756 if self.cells[(r,c)].colour != bg {
2757 return self.cells[(r,c)].colour;
2758 }
2759 }
2760 }
2761
2762 NoColour
2763 }
2764
2765 pub fn colour_squares(&mut self, colour: Colour) {
2767 let grid = self.clone();
2768
2769 for (r, c) in grid.cells.keys() {
2770 if surround_cnt(&grid.cells, r, c, Black) == (8, false) {
2771 self.cells[(r-1,c-1)].colour = colour;
2772 self.cells[(r-1,c)].colour = colour;
2773 self.cells[(r-1,c+1)].colour = colour;
2774 self.cells[(r,c-1)].colour = colour;
2775 self.cells[(r,c)].colour = colour;
2776 self.cells[(r,c+1)].colour = colour;
2777 self.cells[(r+1,c-1)].colour = colour;
2778 self.cells[(r+1,c)].colour = colour;
2779 self.cells[(r+1,c+1)].colour = colour;
2780 }
2781 }
2782
2783 let grid = self.clone();
2784
2785 for ((r, c), cell) in grid.cells.items() {
2786 let col = cell.colour;
2787
2788 if col == Black && r < grid.cells.rows - 1 && c < grid.cells.columns - 1 && grid.cells[(r+1,c)].colour == Black && grid.cells[(r,c+1)].colour == Black && grid.cells[(r+1,c+1)].colour == Black {
2789 self.cells[(r,c)].colour = colour;
2790 self.cells[(r,c+1)].colour = colour;
2791 self.cells[(r+1,c)].colour = colour;
2792 self.cells[(r+1,c+1)].colour = colour;
2793 }
2794 }
2795 }
2796
2797 fn find_colour_patches_core(&self, colour: Colour) -> Shapes {
2798 fn mshape(cells: &mut Matrix<Cell>, colour: Colour) -> Option<(usize, usize, Matrix<Cell>)> {
2799 let rc = cells.items().filter(|(_, cell)| cell.colour == colour).map(|(pos, _)| pos).min();
2801 if let Some((r, c)) = rc {
2806 let reachable = cells.bfs_reachable((r, c), false, |i| cells[i].colour == colour);
2807
2808 let tlr = *reachable.iter().map(|(r, _)| r).min().unwrap();
2809 let tlc = *reachable.iter().map(|(_, c)| c).min().unwrap();
2810 let brr = *reachable.iter().map(|(r, _)| r).max().unwrap();
2811 let brc = *reachable.iter().map(|(_, c)| c).max().unwrap();
2812
2813 let mut m = Matrix::new(brr - tlr + 1, brc - tlc + 1, Cell::new(0, 0, 0));
2814
2815 for r in tlr ..= brr {
2817 for c in tlc ..= brc {
2818 let cell = &mut m[(r - tlr, c - tlc)];
2819
2820 cell.row = r;
2821 cell.col = c;
2822 cell.colour = colour;
2823 }
2824 }
2825
2826 reachable.iter().for_each(|(r, c)| {
2828 cells[(*r, *c)].colour = NoColour;
2829 });
2830
2831 Some((tlr, tlc, m))
2832 } else {
2833 None
2834 }
2835 }
2836
2837 let mut shapes = Shapes::new_sized(self.cells.rows, self.cells.columns);
2838 let mut cells = self.cells.clone();
2839
2840 while let Some((or, oc, m)) = mshape(&mut cells, colour) {
2841 let s = Shape::new(or, oc, &m);
2842
2843 shapes.add(&s);
2844 }
2866
2867 shapes
2868 }
2869
2870 pub fn find_black_patches(&self) -> Shapes {
2897 self.find_black_patches_limit(12)
2898 }
2899
2900 pub fn find_black_patches_limit(&self, limit: usize) -> Shapes {
2901 if self.cells.rows < limit && self.cells.columns < limit {
2902 return Shapes::new_sized(0, 0);
2903 }
2904 self.find_colour_patches_core(Black)
2905 }
2906
2907 pub fn find_colour_patches(&self, colour: Colour) -> Shapes {
2908 self.find_colour_patches_limit(colour, 2)
2910 }
2911
2912 pub fn find_colour_patches_limit(&self, colour: Colour, limit: usize) -> Shapes {
2913 if self.cells.rows < limit && self.cells.columns < limit {
2914 return Shapes::new_sized(0, 0);
2915 }
2916 self.find_colour_patches_core(colour)
2917 }
2918
2919 fn find_gaps(&self, bg: Colour) -> (Vec<usize>, Vec<usize>) {
2920 let mut rs: Vec<usize> = Vec::new();
2921 let mut cs: Vec<usize> = Vec::new();
2922
2923 rs.push(0);
2924 cs.push(0);
2925
2926 let mut lastr: isize = -1;
2927 let mut lastc: isize = -1;
2928
2929 for ((r, c), cell) in self.cells.items() {
2930 if cell.colour == bg {
2931 if c == 0 {
2932 if (lastr + 1) as usize != r {
2933 rs.push(r);
2934 }
2935 lastr = r as isize;
2936 }
2937 if r == 0 {
2938 if (lastc + 1) as usize != c {
2939 cs.push(c);
2940 }
2941 lastc = c as isize;
2942 }
2943 }
2944 }
2945
2946 (rs, cs)
2947 }
2948
2949 pub fn toddle_colour(&self, bg: Colour, fg: Colour) -> Self {
2950 let s = self.recolour(bg, ToBlack + bg).recolour(fg, bg);
2951
2952 s.recolour(ToBlack + bg, fg)
2953 }
2954
2955 pub fn to_shapes_base_bg(&self, bg: Colour) -> Shapes {
2956 let mut shapes: Vec<Shape> = Vec::new();
2957 let (mut rs, mut cs) = self.find_gaps(bg);
2958
2959 if rs.len() >= 2 && rs[0] == rs[1] || cs.len() > 4 && cs[0] == cs[1] {
2960 return Shapes::new(); }
2962
2963 if self.cells[(self.cells.rows - 1, 0)].colour != bg {
2964 rs.push(self.cells.rows);
2965 }
2966 if self.cells[(0, self.cells.columns - 1)].colour != bg {
2967 cs.push(self.cells.columns);
2968 }
2969
2970 for i in 0 .. rs.len() - 1 {
2971 let mut sr = rs[i];
2972 if i > 0 {
2973 sr += 1;
2974 for x in sr .. rs[i + 1] {
2976 if self.cells[(x, 0)].colour != bg {
2977 break;
2978 }
2979 }
2980 }
2981
2982 for j in 0 .. cs.len() - 1 {
2983 let mut sc = cs[j];
2984 if j > 0 {
2985 sc += 1;
2986 for y in sc .. cs[j + 1] {
2988 if self.cells[(0, y)].colour != bg {
2989 break;
2990 }
2991 }
2992 }
2993 let xsize = rs[i + 1] - sr;
2995 let ysize = cs[j + 1] - sc;
2996 let mut m = Matrix::from_fn(xsize, ysize, |(_, _)| Cell::new_empty());
2997
2998 for r in sr .. rs[i + 1] {
2999 for c in sc .. cs[j + 1] {
3000 m[(r - sr, c - sc)].row = r;
3001 m[(r - sr, c - sc)].col = c;
3002 m[(r - sr, c - sc)].colour = self.cells[(r, c)].colour;
3003 }
3004 }
3005
3006 shapes.push(Shape::new_cells(&m));
3007 }
3008 }
3009
3010 Shapes::new_shapes(&shapes)
3011 }
3012
3013 pub fn mid_div_colour(&self) -> Colour {
3014 let mut colour = NoColour;
3015
3016 if self.cells.rows % 2 == 1 {
3017 colour = self.cells[(self.cells.rows / 2,0)].colour;
3018
3019 for c in 1 .. self.cells.columns {
3020 if self.cells[(self.cells.rows / 2,c)].colour != colour {
3021 return NoColour;
3022 }
3023 }
3024 } else if self.cells.columns % 2 == 1 {
3025 colour = self.cells[(0,self.cells.columns / 2)].colour;
3026
3027 for r in 1 .. self.cells.rows {
3028 if self.cells[(r,self.cells.columns / 2)].colour != colour {
3029 return NoColour;
3030 }
3031 }
3032 }
3033
3034 colour
3035 }
3036
3037 pub fn has_shapes_base_bg(&self) -> bool {
3038 match self.has_bg_grid() {
3039 NoColour => false,
3040 colour => {
3041 let shapes = self.to_shapes_base_bg(colour);
3042shapes.len() >= 4
3045 }
3046 }
3047 }
3048
3049 pub fn copy_part_matrix(rs: usize, cs: usize, rows: usize, cols: usize, cells: &Matrix<Cell>) -> Matrix<Cell> {
3050 let mut m = Matrix::new(rows, cols, Cell::new(0, 0, 0));
3051
3052 for r in 0 .. rows {
3053 for c in 0 .. cols {
3054 m[(r, c)].row = cells[(rs + r, cs + c)].row;
3055 m[(r, c)].col = cells[(rs + r, cs + c)].col;
3056 m[(r, c)].colour = cells[(rs + r, cs + c)].colour;
3057 }
3058 }
3059
3060 m
3061 }
3062
3063 fn de_diag(or: usize, oc: usize, s: &Shape, shapes: &mut Shapes) {
3065 if s.cells.rows >= 4 && s.cells.rows % 2 == 0 && s.cells.rows == s.cells.columns {
3066 let hrow = s.cells.rows / 2;
3067 let hcol = s.cells.columns / 2;
3068
3069 if s.cells[(hrow - 1, hcol - 1)].colour == Black && s.cells[(hrow, hcol)].colour == Black && s.cells[(hrow - 1, hcol)].colour != Black && s.cells[(hrow, hcol - 1)].colour != Black {
3070 let m = Self::copy_part_matrix(hrow, 0, hrow, hcol, &s.cells);
3071 shapes.add(&Shape::new(or + hrow, oc, &m));
3072 let m = Self::copy_part_matrix(0, hcol, hrow, hcol, &s.cells);
3073 shapes.add(&Shape::new(or, oc + hcol, &m));
3074 } else if s.cells[(hrow - 1, hcol - 1)].colour != Black && s.cells[(hrow, hcol)].colour != Black && s.cells[(hrow - 1, hcol)].colour == Black && s.cells[(hrow, hcol - 1)].colour == Black {
3075 let m = Self::copy_part_matrix(0, 0, hrow, hcol, &s.cells);
3076 shapes.add(&Shape::new(or, oc, &m));
3077 let m = Self::copy_part_matrix(hrow, hcol, hrow, hcol, &s.cells);
3078 shapes.add(&Shape::new(or + hrow, oc + hcol, &m));
3079 } else { shapes.add(s);
3081 }
3082 } else {
3083 shapes.add(s);
3084 }
3085 }
3086
3087 fn to_shapes_base(&self, same_colour: bool, diag: bool, cons: bool, bg: Colour) -> Shapes {
3089 fn mshape(same_colour: bool, bgc: Colour, bg: Colour, cells: &mut Matrix<Cell>, diag: bool) -> Option<(usize, usize, Matrix<Cell>)> {
3091 let rc = cells.items().filter(|(_, c)| c.colour != bgc && c.colour != bg).map(|(xy, _)| xy).min();
3093
3094 if let Some((r, c)) = rc {
3095 let start_colour = cells[(r, c)].colour;
3096 let reachable = cells.bfs_reachable((r, c), diag, |i| cells[i].colour != bgc && cells[i].colour != bg && (!same_colour || cells[i].colour == start_colour));
3097 let tlr = *reachable.iter().map(|(r, _)| r).min().unwrap();
3100 let tlc = *reachable.iter().map(|(_, c)| c).min().unwrap();
3101 let brr = *reachable.iter().map(|(r, _)| r).max().unwrap();
3102 let brc = *reachable.iter().map(|(_, c)| c).max().unwrap();
3103
3104 let mut m = Matrix::new(brr - tlr + 1, brc - tlc + 1, Cell::new(0, 0, 0));
3105
3106 for r in tlr ..= brr {
3108 for c in tlc ..= brc {
3109 let cell = &mut m[(r - tlr, c - tlc)];
3110
3111 cell.row = r;
3112 cell.col = c;
3113
3114 }
3122 }
3123 reachable.iter().for_each(|(r, c)| {
3125 m[(r - tlr, c - tlc)].colour = cells[(*r, *c)].colour;
3126 cells[(*r, *c)].colour = bgc;
3127 });
3128
3129 Some((tlr, tlc, m))
3130 } else {
3131 None
3132 }
3133 }
3134
3135 let mut shapes = Shapes::new_sized(self.cells.rows, self.cells.columns);
3136 let mut cells = self.cells.clone();
3137 let bg = if bg == NoColour {
3138 match self.has_bg_grid_not_sq() {
3139 NoColour => bg,
3140 colour => colour
3141 }
3142 } else {
3143 bg
3144 };
3145
3146 if bg == NoColour || bg == Black {
3147 let bgc = Black;
3148
3149 while let Some((or, oc, m)) = mshape(same_colour, bgc, bg, &mut cells, diag) {
3150 let s = Shape::new(or, oc, &m);
3151
3152 Self::de_diag(or, oc, &s, &mut shapes);
3177 }
3178 } else {
3179 shapes = self.to_shapes_base_bg(bg);
3180
3181 if shapes.is_empty() {
3183 while let Some((or, oc, m)) = mshape(same_colour, Black, bg, &mut cells, diag) {
3186 let s = Shape::new(or, oc, &m);
3187
3188 Self::de_diag(or, oc, &s, &mut shapes);
3189 }
3190 }
3191 }
3192 if cons {
3199 shapes = shapes.consolidate_shapes();
3200 }
3201
3202 shapes.shapes.sort();
3203
3204 shapes
3205 }
3206
3207 pub fn to_shapes_coloured(&self) -> Shapes {
3208 self.to_shapes_base(false, true, false, Black)
3209 }
3210
3211 pub fn to_shapes(&self) -> Shapes {
3212 self.to_shapes_base(true, true, false, Black)
3213 }
3214
3215 pub fn to_shapes_cons(&self) -> Shapes {
3216 self.to_shapes_base(true, true, true, Black)
3217 }
3218
3219 pub fn to_shapes_coloured_bg(&self, bg: Colour) -> Shapes {
3220 self.to_shapes_base(false, true, false, bg)
3221 }
3222
3223 pub fn to_shapes_bg(&self, bg: Colour) -> Shapes {
3224 self.to_shapes_base(true, true, false, bg)
3225 }
3226
3227 pub fn to_shapes_bg_cons(&self, bg: Colour) -> Shapes {
3228 self.to_shapes_base(true, true, true, bg)
3229 }
3230
3231 pub fn to_shapes_coloured_cbg(&self) -> Shapes {
3232 self.to_shapes_base(false, true, false, NoColour)
3233 }
3234
3235 pub fn to_shapes_cbg(&self) -> Shapes {
3236 self.to_shapes_base(true, true, false, NoColour)
3237 }
3238
3239 pub fn to_shapes_coloured_sq(&self) -> Shapes {
3240 self.to_shapes_base(false, false, false, Black)
3241 }
3242
3243 pub fn to_shapes_sq(&self) -> Shapes {
3244 self.to_shapes_base(true, false, false, Black)
3245 }
3246
3247 pub fn to_shapes_coloured_bg_sq(&self, bg: Colour) -> Shapes {
3248 self.to_shapes_base(false, false, false, bg)
3249 }
3250
3251 pub fn to_shapes_bg_sq(&self, bg: Colour) -> Shapes {
3252 self.to_shapes_base(true, false, false, bg)
3253 }
3254
3255 pub fn to_shapes_coloured_cbg_sq(&self) -> Shapes {
3256 self.to_shapes_base(false, false, false, NoColour)
3257 }
3258
3259 pub fn to_shapes_cbg_sq(&self) -> Shapes {
3260 self.to_shapes_base(true, false, false, NoColour)
3261 }
3262
3263 pub fn to_shapes_from_grid_gap(&self, gap: usize) -> Shapes {
3264 self.to_shapes_from_grid_gap_border(gap, 0)
3265 }
3266
3267 pub fn to_shapes_from_grid_border(&self, border: usize) -> Shapes {
3268 self.to_shapes_from_grid_gap_border(1, border)
3269 }
3270
3271 pub fn to_shapes_from_grid(&self) -> Shapes {
3272 self.to_shapes_from_grid_gap_border(1, 0)
3273 }
3274
3275 pub fn to_shapes_from_grid_gap_border(&self, gap: usize, border: usize) -> Shapes {
3276 let rs = self.height() - border * 2;
3277 let cs = self.width() - border * 2;
3278 let r = (rs as f32).sqrt().abs() as usize;
3279 let c = (cs as f32).sqrt().abs() as usize;
3280
3281 let mut shapes = Shapes::new_sized(self.height(), self.width());
3282
3283 for ri in (border .. rs).step_by(r + gap) {
3284 for ci in (border .. cs).step_by(c + gap) {
3285 if ri + r > rs || ci + c > cs {
3286 return Shapes::trivial();
3287 }
3288 let sg = self.subgrid(ri, r, ci, c);
3289
3290 shapes.shapes.push(sg.as_shape_position(ri, ci));
3291 }
3292 }
3293
3294 shapes
3295 }
3296
3297 pub fn as_shape(&self) -> Shape {
3298 if self.size() == 0 {
3299 return Shape::trivial();
3300 }
3301
3302 Shape::new_cells(&self.cells)
3303 }
3304
3305 pub fn as_shape_position(&self, r: usize, c: usize) -> Shape {
3306 if self.size() == 0 {
3307 return Shape::trivial();
3308 }
3309
3310 Shape::new(r, c, &self.cells)
3311 }
3312
3313 pub fn as_shapes(&self) -> Shapes {
3314 if self.size() == 0 {
3315 return Shapes::new();
3316 }
3317
3318 Shapes::new_from_shape(&Shape::new_cells(&self.cells))
3319 }
3320
3321 pub fn as_shapes_position(&self, r: usize, c: usize) -> Shapes {
3322 if self.size() == 0 {
3323 return Shapes::new();
3324 }
3325
3326 Shapes::new_from_shape(&Shape::new(r, c, &self.cells))
3327 }
3328
3329 pub fn as_pixel_shapes(&self) -> Shapes {
3330 if self.size() == 0 {
3331 return Shapes::new();
3332 }
3333
3334 let mut shapes = Shapes::new_sized(self.cells.rows, self.cells.columns);
3335
3336 for ((r, c), cell) in self.cells.items() {
3337 if cell.colour != Black {
3338 let s = Shape::new_sized_coloured_position(r, c, 1, 1, cell.colour);
3339
3340 shapes.shapes.push(s);
3341 }
3342 }
3343
3344 shapes
3345 }
3346
3347 pub fn repeat_rows(&self, start: usize, colour: Colour) -> Vec<usize> {
3348 let mut res: Vec<usize> = vec![start];
3349 let row: Vec<Colour> = (0 .. self.cells.rows)
3350 .map(|r| self.cells[(r,start)].colour)
3351 .collect();
3352
3353 for c in start + 1 .. self.cells.columns {
3354 for r in 0 .. self.cells.rows {
3355 let lcol = self.cells[(r,c)].colour;
3356
3357 if row[r] != lcol && lcol != colour {
3358 break;
3359 }
3360 if r == self.cells.rows - 1 {
3361 res.push(c);
3362 }
3363 }
3364 }
3365
3366 res
3367 }
3368
3369 pub fn cover_rows(&self, start: usize, colour: Colour) -> Self {
3371 let reps = self.repeat_rows(start, colour);
3372 let mut grid = self.clone();
3373
3374 for rc in 1 .. reps.len() - 1 {
3375 for c in 0 .. self.cells.columns {
3376 let r = reps[rc];
3377let r1 = reps[rc + 1];
3379 let curr = &mut grid.cells[(r,c)];
3380 let curr1 = &self.cells[(r1,c)];
3381
3382 if curr.colour == colour && curr1.colour != colour {
3383 curr.colour = curr1.colour;
3384 }
3385 }
3386 }
3387
3388 grid
3389 }
3390
3391 pub fn repeat_cols(&self, start: usize, colour: Colour) -> Vec<usize> {
3392 let mut res: Vec<usize> = vec![start];
3393 let col: Vec<Colour> = (0 .. self.cells.columns)
3394 .map(|c| self.cells[(start,c)].colour)
3395 .collect();
3396
3397 for r in start + 1 .. self.cells.rows {
3398 for c in 0 .. self.cells.columns {
3399 let lcol = self.cells[(r,c)].colour;
3400
3401 if col[c] != lcol && lcol != colour {
3402 break;
3403 }
3404 if c == self.cells.columns - 1 {
3405 res.push(r);
3406 }
3407 }
3408 }
3409
3410 res
3411 }
3412
3413 pub fn is_square(&self) -> bool {
3414 self.cells.rows > 1 && self.cells.rows == self.cells.columns
3415 }
3416
3417 pub fn square(&self) -> usize {
3418 if self.is_square() {
3419 self.cells.rows * self.cells.columns
3420 } else {
3421 0
3422 }
3423 }
3424
3425 pub fn height(&self) -> usize {
3426 self.cells.rows
3427 }
3428
3429 pub fn width(&self) -> usize {
3430 self.cells.columns
3431 }
3432
3433 pub fn row_colour(&self, r: usize) -> Colour {
3434 let colour = self.cells[(r,0)].colour;
3435
3436 Self::row_colour_matrix(&self.cells, r, colour)
3437 }
3438
3439 pub fn row_colour_matrix(m: &Matrix<Cell>, r: usize, colour: Colour) -> Colour {
3440 for y in 1 .. m.columns {
3441 if m[(r,y)].colour != colour {
3442 return Mixed;
3443 }
3444 }
3445
3446 colour
3447 }
3448
3449 pub fn find_pixel(&self, colour: Colour) -> (usize, usize) {
3450 for ((r, c), cell) in self.cells.items() {
3451 if cell.colour == colour {
3452 return (r, c);
3453 }
3454 }
3455
3456 (0, 0)
3457 }
3458
3459 pub fn invert_colour(&self) -> Self {
3460 self.invert_colour_new(self.colour)
3461 }
3462
3463 pub fn invert_colour_new(&self, colour: Colour) -> Self {
3464 if self.colour == Mixed {
3465 return Self::trivial();
3466 }
3467
3468 let mut grid = self.clone();
3469
3470 for cell in grid.cells.values_mut() {
3471 cell.colour = if cell.colour == Black {
3472 colour
3473 } else {
3474 Black
3475 };
3476 }
3477
3478 grid
3479 }
3480
3481 pub fn blank(&self) -> Self {
3482 let mut shape = self.clone();
3483
3484 for cell in shape.cells.values_mut() {
3485 cell.colour = Black;
3486 }
3487
3488 shape
3489 }
3490
3491 pub fn col_colour(&self, c: usize) -> Colour {
3492 let colour = self.cells[(0,c)].colour;
3493
3494 Self::col_colour_matrix(&self.cells, c, colour)
3495 }
3496
3497 pub fn col_colour_matrix(m: &Matrix<Cell>, c: usize, colour: Colour) -> Colour {
3498 for x in 1 .. m.rows {
3499 if m[(x,c)].colour != colour {
3500 return Mixed;
3501 }
3502 }
3503
3504 colour
3505 }
3506
3507 pub fn div9(&self) -> bool {
3508 self.cells.rows == 3 && self.cells.columns == 3
3509 }
3510
3511 pub fn is_3x3(&self) -> bool {
3512 self.cells.rows % 3 == 0 && self.cells.columns % 3 == 0
3513 }
3514
3515 pub fn is_full(&self) -> bool {
3516 for (r, c) in self.cells.keys() {
3517 if self.cells[(r, c)].colour == Black {
3518 return false;
3519 }
3520 }
3521
3522 true
3523 }
3524
3525 pub fn has_marker(&self, shape: &Shape) -> bool {
3526 self.has_marker_colour(shape, Black)
3527 }
3528
3529 pub fn has_marker_colour(&self, s: &Shape, colour: Colour) -> bool {
3530 for (r, c) in s.cells.keys() {
3531 if r == 0 && s.orow >= 3 &&
3532 self.cells[(s.orow - 1, s.ocol + c)].colour != colour &&
3533 self.cells[(s.orow - 2, s.ocol + c)].colour != colour &&
3534 self.cells[(s.orow - 3, s.ocol + c)].colour != colour ||
3535 c == 0 && s.ocol >= 3 &&
3536 self.cells[(s.orow + r, s.ocol - 1)].colour != colour &&
3537 self.cells[(s.orow + r, s.ocol - 2)].colour != colour &&
3538 self.cells[(s.orow + r, s.ocol - 3)].colour != colour ||
3539 r == s.cells.rows - 1 &&
3540 s.orow + s.cells.rows < self.cells.rows - 3 &&
3541 self.cells[(s.orow + 1, s.ocol + c)].colour != colour &&
3542 self.cells[(s.orow + 2, s.ocol + c)].colour != colour &&
3543 self.cells[(s.orow + 3, s.ocol + c)].colour != colour ||
3544 c == s.cells.columns - 1 &&
3545 s.ocol + s.cells.columns < self.cells.columns - 3 &&
3546 self.cells[(s.orow + r, s.ocol + c + 1)].colour != colour &&
3547 self.cells[(s.orow + r, s.ocol + c + 2)].colour != colour &&
3548 self.cells[(s.orow + r, s.ocol + c + 3)].colour != colour {
3549 return true;
3550 }
3551 }
3552
3553 false
3554 }
3555
3556 pub fn find_rectangles(&self) -> Shapes {
3557 let grid = self.recolour(Black, NoColour);
3558
3559 let shapes = grid.to_shapes();
3560 let mut new_shapes = shapes.clone_base();
3561
3562 for s in shapes.shapes.iter() {
3563 if s.is_full() && grid.has_marker_colour(s, NoColour) {
3564 let s = s.recolour(NoColour, Black);
3565 new_shapes.shapes.push(s.clone());
3566 }
3567 }
3568
3569 new_shapes
3570 }
3571
3572 pub fn has_gravity(&self, orientation: usize) -> bool {
3573 self.has_gravity_colour(orientation, Black)
3574 }
3575
3576 pub fn has_gravity_colour(&self, orientation: usize, colour: Colour) -> bool {
3577 if self.cells.rows != self.cells.columns {
3579 return false;
3580 }
3581
3582 let mut grid = self.clone();
3583 let mut has_colour = false;
3584
3585 grid = grid.rotate_90(orientation);
3586
3587 for r in 0 .. grid.cells.rows {
3588 let mut prev = grid.cells[(r, 0)].colour;
3589
3590 if !has_colour {
3591 has_colour = prev == colour;
3592 }
3593
3594 for c in 1 .. grid.cells.columns {
3595 let next = grid.cells[(r, c)].colour;
3596
3597 if prev != next && next == colour {
3598 return false;
3599 }
3600
3601 prev = next;
3602 }
3603 }
3604
3605 has_colour
3606 }
3607
3608 pub fn has_gravity_down(&self) -> bool {
3609 self.has_gravity(3)
3610 }
3611
3612 pub fn has_gravity_up(&self) -> bool {
3613 self.has_gravity(1)
3614 }
3615
3616 pub fn has_gravity_left(&self) -> bool {
3617 self.has_gravity(0)
3618 }
3619
3620 pub fn has_gravity_right(&self) -> bool {
3621 self.has_gravity(0)
3622 }
3623
3624 pub fn equals(&self, other: &Self) -> Colour {
3625 if self.size() == 0 || other.size() == 0 || self.cells.columns != other.cells.columns || self.cells.rows != other.cells.rows {
3626 return DiffShape;
3627 }
3628
3629 for (c1, c2) in self.cells.values().zip(other.cells.values()) {
3630 if c1.colour.to_base() != c2.colour.to_base() {
3631 return DiffBlack + c2.colour;
3632 }
3633 }
3634
3635 Same
3636 }
3637
3638 pub fn bleach(&self) -> Self {
3639 let mut shape = self.clone();
3640
3641 if self.size() == 0 {
3642 return shape;
3643 }
3644
3645 shape.colour = NoColour;
3646
3647 for cell in shape.cells.values_mut() {
3648 if cell.colour != Black {
3649 cell.colour = NoColour;
3650 }
3651 }
3652
3653 shape
3654 }
3655
3656 pub fn equal_footprint(&self, other: &Self) -> bool {
3658 self.cells.columns == other.cells.columns && self.cells.rows == other.cells.rows
3659 }
3660
3661 pub fn equal_shape(&self, other: &Self) -> bool {
3663 if !self.equal_footprint(other) {
3664 return false;
3665 }
3666
3667 for ((sr, sc), (or, oc)) in self.cells.keys().zip(other.cells.keys()) {
3668 if sr != or || sc != oc {
3669 return false;
3670 }
3671 }
3672
3673 true
3674 }
3675
3676 pub fn diff_only_diff(&self) -> Self {
3693 let mut g = self.clone();
3694
3695 for c in g.cells.values_mut() {
3696 if Colour::to_usize(c.colour) / 40 < 10 {
3697 c.colour = Colour::from_usize(Colour::to_usize(c.colour) / 40);
3698 } else {
3699 c.colour = Black;
3700 }
3701 }
3702
3703 g
3704 }
3705
3706 pub fn diff_only_and(&self, colour: Colour) -> Self {
3719 let mut g = self.clone();
3720
3721 for c in g.cells.values_mut() {
3722 if c.colour.is_same() {
3723 c.colour = colour;
3724 } else {
3725 c.colour = Black;
3726 }
3727 }
3728
3729 g
3730 }
3731
3732 pub fn diff_only_or(&self, colour: Colour) -> Self {
3733 let mut g = self.clone();
3734
3735 for c in g.cells.values_mut() {
3736 if Colour::to_usize(c.colour) > 0 {
3737 c.colour = colour;
3738 } else {
3739 c.colour = Black;
3740 }
3741 }
3742
3743 g
3744 }
3745
3746 pub fn diff_only_xor(&self, colour: Colour) -> Self {
3747 let mut g = self.clone();
3748
3749 for c in g.cells.values_mut() {
3750 if c.colour == Black || Colour::to_usize(c.colour) > 30 {
3751 c.colour = Black;
3752 } else {
3753 c.colour = colour;
3754 }
3755 }
3756
3757 g
3758 }
3759
3760 pub fn diff_only_not(&self, colour: Colour) -> Self {
3761 let mut g = self.clone();
3762
3763 for c in g.cells.values_mut() {
3764 if c.colour == Black {
3765 c.colour = colour;
3766 } else {
3767 c.colour = Black;
3768 }
3769 }
3770
3771 g
3772 }
3773
3774 pub fn diff_only_same(&self) -> Self {
3775 let mut g = self.clone();
3776
3777 for c in g.cells.values_mut() {
3778 if c.colour.is_same() {
3779 c.colour = c.colour.to_base();
3780 } else {
3781 c.colour = Black;
3782 }
3783 }
3784
3785 g
3786 }
3787
3788 pub fn diff_black_same(&self, colour: Colour) -> Self {
3789 let mut g = self.clone();
3790
3791 for c in g.cells.values_mut() {
3792 if Colour::to_usize(c.colour) == 30 {
3793 c.colour = colour;
3794 } else {
3795 c.colour = Black;
3796 }
3797 }
3798
3799 g
3800 }
3801
3802 pub fn diff_other_same(&self, colour: Colour) -> Self {
3803 let mut g = self.clone();
3804
3805 for c in g.cells.values_mut() {
3806 if Colour::to_usize(c.colour) > 30 && Colour::to_usize(c.colour) < 40 {
3807 c.colour = colour;
3808 } else {
3809 c.colour = Black;
3810 }
3811 }
3812
3813 g
3814 }
3815
3816 pub fn find_unique_colours(&self) -> Vec<Colour> {
3818 let mut unique_colours = Vec::new();
3819 for row in 0..self.cells.rows {
3820 for col in 0..self.cells.columns {
3821 let colour = self.cells[(row, col)].colour;
3822 if !unique_colours.contains(&colour) {
3823 unique_colours.push(colour);
3824 }
3825 }
3826 }
3827 unique_colours
3828 }
3829
3830 pub fn find_colour_row_order(&self) -> BTreeMap<usize, Colour> {
3831 let mut colours: BTreeMap<usize, Colour> = BTreeMap::new();
3832 let mut col_set: Vec<Colour> = Vec::new();
3833
3834 for row in 0 .. self.cells.rows {
3835 let colour = self.cells[(row, 0)].colour;
3836
3837 if colour != Black && !col_set.contains(&colour){
3838 colours.insert(row, colour);
3839 col_set.push(colour);
3840 }
3841
3842 let colour = self.cells[(row, self.cells.columns - 1)].colour;
3843
3844 if colour != Black && !col_set.contains(&colour){
3845 colours.insert(row, colour);
3846 col_set.push(colour);
3847 }
3848 }
3849
3850 colours
3851 }
3852
3853 pub fn diff_only_transparent(&self) -> Self {
3854 let mut g = self.clone();
3855
3856 for c in g.cells.values_mut() {
3857 if c.colour != Black {
3858 c.colour = Colour::to_base(c.colour);
3859 }
3860 }
3861
3862 g
3863 }
3864
3865 pub fn diff(&self, other: &Self) -> Option<Self> {
3866 self.diff_impl(other, true)
3867 }
3868
3869 pub fn diff_orig(&self, other: &Self) -> Option<Self> {
3870 self.diff_impl(other, false)
3871 }
3872
3873 pub fn diff_impl(&self, other: &Self, diff: bool) -> Option<Self> {
3874 if self.cells.columns != other.cells.columns || self.cells.rows != other.cells.rows {
3876 return None;
3877 }
3878
3879 let mut newg = other.clone();
3880
3881 for (((r, c), c1), ((_, _), c2)) in self.cells.items().zip(other.cells.items()) {
3882 if c1.colour != c2.colour {
3883 newg.cells[(r, c)].colour = if c1.colour == Black {
3884 c2.colour + ToBlack
3885 } else if c2.colour == Black {
3886 c1.colour + FromBlack
3887 } else if diff {
3888 c2.colour + DiffBlack
3889 } else {
3890 c1.colour + OrigBlack
3891 };
3892 } else if c1.colour != Black && c1.colour == c2.colour {
3893 newg.cells[(r, c)].colour = c1.colour + SameBlack;
3894 }
3895 }
3896
3897 Some(newg)
3898 }
3899
3900 pub fn distance(&self, other: &Self) -> f64 {
3901 let diff = self.diff_impl(other, true);
3902
3903 if diff.is_none() {
3905 return -1.0;
3906 }
3907
3908 let diff = diff.unwrap();
3909 let mut cnt = 0;
3910
3911 for cell in diff.cells.values() {
3912 if cell.colour == Black || cell.colour.is_same() {
3913 cnt += 1;
3914 }
3915 }
3916
3917 cnt as f64 / diff.size() as f64
3918 }
3919
3920pub fn centre_of(&self) -> (usize, usize) {
3998 (self.cells.rows / 2, self.cells.columns / 2)
3999 }
4000
4001 pub fn centre_of_symmetry(&self) -> (usize, usize) {
4002 let (min_r, min_c, max_r, max_c) = self.corners();
4003
4004 (min_r + (max_r - min_r) / 2, min_c + (max_c - min_c) / 2)
4005 }
4006
4007 pub fn corners(&self) -> (usize, usize, usize, usize) {
4008 let mut min_r = usize::MAX;
4009 let mut min_c = usize::MAX;
4010 let mut max_r = 0;
4011 let mut max_c = 0;
4012
4013 for cell in self.cells.values() {
4014 if cell.colour != Black {
4015 min_r = min_r.min(cell.row);
4016 min_c = min_c.min(cell.col);
4017 max_r = max_r.max(cell.row);
4018 max_c = max_c.max(cell.col);
4019 }
4020 }
4021
4022 if min_r == usize::MAX || min_c == usize::MAX {
4023 return (0, 0, 0, 0);
4024 }
4025
4026 (min_r, min_c, max_r, max_c)
4027 }
4028
4029 pub fn row_skew(&self) -> isize {
4030 fn same(cells1: &Matrix<Cell>, cells2: &Matrix<Cell>, offset: usize) -> bool {
4031 for (c1, c2) in (offset .. cells1.rows).zip(0 .. cells2.rows) {
4032 if cells1[(c1,0)].colour != cells2[(cells2.rows - 1 - c2,0)].colour {
4033 return false;
4034 }
4035 }
4036
4037 true
4038 }
4039
4040 if self.cells.rows != self.cells.columns || self.cells.rows < 12 {
4041 return 0;
4042 }
4043 let rows = self.cells.rows;
4044 let dim = 6;
4045
4046 let top = self.subgrid(0, dim, 0, 1);
4047 let bot = self.subgrid(rows - dim, dim, 0, 1);
4048
4049 for i in 0 .. 3 {
4050 if same(&top.cells, &bot.cells, i) {
4051 return i as isize;
4052 }
4053 }
4054
4055 for i in 0 .. 3 {
4056 if same(&bot.cells, &top.cells, i) {
4057 return -(i as isize);
4058 }
4059 }
4060
4061 0
4062 }
4063
4064 pub fn col_skew(&self) -> isize {
4065 fn same(cells1: &Matrix<Cell>, cells2: &Matrix<Cell>, offset: usize) -> bool {
4066 for (c1, c2) in (offset .. cells1.columns).zip(0 .. cells2.columns) {
4067 if cells1[(0,c1)].colour != cells2[(0,cells2.columns - 1 - c2)].colour {
4068 return false;
4069 }
4070 }
4071
4072 true
4073 }
4074
4075 if self.cells.rows != self.cells.columns || self.cells.rows < 12 {
4076 return 0;
4077 }
4078 let rows = self.cells.rows;
4079 let dim = 6;
4080
4081 let left = self.subgrid(0, 1, 0, dim);
4082 let right = self.subgrid(0, 1, rows - dim, dim);
4083
4084 for i in 0 .. 3 {
4085 if same(&left.cells, &right.cells, i) {
4086 return i as isize;
4087 }
4088 }
4089
4090 for i in 0 .. 3 {
4091 if same(&right.cells, &left.cells, i) {
4092 return -(i as isize);
4093 }
4094 }
4095
4096 0
4097 }
4098
4099 pub fn count_diff(&self) -> (usize, usize) {
4100 let mut total = 0;
4101 let mut count = 0;
4102
4103 for c in self.cells.values() {
4104 if c.colour == NoColour {
4105 count += 1;
4106 }
4107
4108 total += 1;
4109 }
4110
4111 (count, total)
4112 }
4113
4114 pub fn tile_mut(&mut self, tile: &Self) {
4115 for r in (0 .. self.height()).step_by(tile.height()) {
4116 for c in (0 .. self.width()).step_by(tile.width()) {
4117 for ((tr, tc), cell) in tile.cells.items() {
4118 if r + tr < self.height() && c + tc < self.width() {
4119 self.cells[(r + tr, c + tc)].colour = cell.colour;
4120 }
4121 }
4122 }
4123 }
4124 }
4125
4126 pub fn roll_right(&self) -> Self {
4127 let mut grid = self.clone();
4128 let rows = self.cells.rows;
4129 let cols = self.cells.columns;
4130 let first = self.cells.slice(0 .. rows, 0 .. 1);
4131
4132 if let Ok(first) = first {
4133 for r in 0 .. rows {
4134 for c in 1 .. cols {
4135 grid.cells[(r,c-1)].colour = self.cells[(r,c)].colour;
4136 }
4137 }
4138 for r in 0 .. rows {
4139 grid.cells[(r,cols-1)].colour = first[(r,0)].colour;
4140 }
4141 }
4142
4143 grid
4144 }
4145
4146 pub fn roll_left(&self) -> Self {
4147 self.rotate_90(2).roll_right().rotate_90(2)
4148 }
4149
4150 pub fn roll_up(&self) -> Self {
4151 self.rotate_90(3).roll_right().rotate_90(1)
4152 }
4153
4154 pub fn roll_down(&self) -> Self {
4155 self.rotate_90(3).roll_right().rotate_90(3)
4156 }
4157
4158 pub fn to_json(&self) -> String {
4159 let mut grid: Vec<Vec<usize>> = vec![vec![0; self.cells.columns]; self.cells.rows];
4160
4161 for r in 0 .. self.cells.rows {
4162 for c in 0 .. self.cells.columns {
4163 let colour: usize = self.cells[(r, c)].colour.to_usize();
4164
4165 grid[r][c] = colour;
4166 }
4167 }
4168
4169 serde_json::to_string(&grid).unwrap()
4170 }
4171
4172 pub fn to_vec(&self) -> Vec<Vec<usize>> {
4173 let mut grid: Vec<Vec<usize>> = vec![vec![0; self.cells.columns]; self.cells.rows];
4174
4175 for r in 0 .. self.cells.rows {
4176 for c in 0 .. self.cells.columns {
4177 let colour: usize = self.cells[(r, c)].colour.to_usize();
4178
4179 grid[r][c] = colour;
4180 }
4181 }
4182
4183 grid
4184 }
4185
4186 pub fn corner_colours(&self) -> (Colour, Colour, Colour, Colour) {
4187 (self.cells[(0,0)].colour, self.cells[(self.cells.rows - 1, 0)].colour, self.cells[(0, self.cells.columns - 1)].colour, self.cells[(self.cells.rows - 1, self.cells.columns - 1)].colour)
4188 }
4189
4190 pub fn corner_idx(&self) -> (Self, Direction) {
4191 let g = self.subgrid(0, 2, 0, 2);
4192 if g.no_colours() == 4 {
4193 return (g, FromUpLeft);
4194 }
4195 let g = self.subgrid(self.cells.rows - 2, 2, self.cells.columns - 2, 2);
4196 if g.no_colours() == 4 {
4197 return (g, FromDownRight);
4198 }
4199 let g = self.subgrid(self.cells.rows - 2, 2, 0, 2);
4200 if g.no_colours() == 4 {
4201 return (g, FromDownLeft);
4202 }
4203 let g = self.subgrid(0, 2, self.cells.columns - 2, 2);
4204 if g.no_colours() == 4 {
4205 return (g, FromUpRight);
4206 }
4207
4208 (self.clone(), Other)
4209 }
4210
4211 pub fn corner_body(&self, dir: Direction) -> Self {
4212 let hr = self.cells.rows - 2;
4213 let hc = self.cells.columns - 2;
4214
4215 match dir {
4216 FromUpLeft => self.subgrid(0, hr, 0, hc),
4217 FromDownRight => self.subgrid(self.cells.rows - hr, hr, self.cells.columns - hc, hc),
4218 FromDownLeft => self.subgrid(self.cells.rows - hr, hr, 0, hc),
4219 FromUpRight => self.subgrid(0, hr, self.cells.columns - hc, hc),
4220 _ => self.clone(),
4221 }
4222 }
4223
4224 pub fn split_n_horizontal(&self, n: usize) -> Vec<Self> {
4225 if n == 0 {
4226 return Vec::new();
4227 }
4228 let hr = self.cells.rows;
4229 let hc = self.cells.columns / n;
4230 let mut gs: Vec<Grid> = Vec::new();
4231
4232 if hr == 0 || hc == 0 {
4233 return Vec::new();
4234 }
4235
4236 for c in 0 .. n {
4237 let s = self.subgrid(0, hr, c * hc, hc);
4238
4239 gs.push(s);
4240 }
4241gs
4244 }
4245
4246 pub fn split_n_vertical(&self, n: usize) -> Vec<Self> {
4247 if n == 0 {
4248 return Vec::new();
4249 }
4250 let hr = self.cells.rows / n;
4251 let hc = self.cells.columns;
4252 let mut gs: Vec<Grid> = Vec::new();
4253
4254 if hr == 0 || hc == 0 {
4255 return Vec::new();
4256 }
4257
4258 for r in 0 .. n {
4259 let s = self.subgrid(r * hr, hr, 0, hc);
4260
4261 gs.push(s);
4262 }
4263
4264 gs
4265 }
4266
4267 pub fn split_4(&self) -> Vec<Self> {
4268 let hr = self.cells.rows / 2;
4269 let hc = self.cells.columns / 2;
4270
4271 if hr == 0 || hc == 0 || self.cells.rows % 2 != 0 || self.cells.columns % 2 != 0 {
4272 return Vec::new();
4273 }
4274
4275 let s1 = self.subgrid(0, hr, 0, hc);
4276 let s2 = self.subgrid(0, hr, self.cells.columns - hc, hc);
4277 let s3 = self.subgrid(self.cells.rows - hr, hr, 0, hc);
4278 let s4 = self.subgrid(self.cells.rows - hr, hr, self.cells.columns - hc, hc);
4279
4280 vec![s1, s2, s3, s4]
4281 }
4282
4283 pub fn split_4_inline(&self, delimiter: bool) -> Shapes {
4284 let rows = self.cells.rows;
4285 let cols = self.cells.columns;
4286 let mut dr = if delimiter { 1 } else { 0 };
4287 let mut dc = if delimiter { 1 } else { 0 };
4288 let mut shapes = Shapes::new_sized(rows, cols);
4289
4290 if rows % 4 != 0 && cols % 4 != 0 || rows < dr * 3 || cols < dc * 3 {
4291 return shapes;
4292 }
4293if ((rows - dr * 3) % 4 != 0 || cols % 4 != 0) &&
4296 (rows % 4 != 0 || (cols - dc * 3) % 4 != 0) {
4297 dr = 0;
4299 dc = 0;
4300 }
4301let (s1, s2, s3, s4) = if rows > cols {
4306 let qr = rows / 4;
4307 if qr * 4 >= rows {
4308 dr = 0;
4309 }
4310
4311 (self.subgrid(0, qr, 0, cols),
4312 self.subgrid(qr + dr, qr, 0, cols),
4313 self.subgrid((qr + dr) * 2, qr, 0, cols),
4314 self.subgrid((qr + dr) * 3, qr, 0, cols))
4315 } else {
4316 let qc = cols / 4;
4317 if qc * 4 >= cols {
4318 dc = 0;
4319 }
4320
4321 (self.subgrid(0, rows, 0, qc),
4322 self.subgrid(0, rows, qc + dc, qc),
4323 self.subgrid(0, rows, (qc + dc) * 2, qc),
4324 self.subgrid(0, rows, (qc + dc) * 3, qc))
4325 };
4326
4327 shapes.shapes = vec![s1.as_shape(), s2.as_shape(), s3.as_shape(), s4.as_shape()];
4328
4329 shapes
4330 }
4331
4332 pub fn full_row(&self, shape: &Shape) -> bool {
4333 shape.orow == 0 && shape.cells.rows == self.cells.rows
4334 }
4335
4336 pub fn full_col(&self, shape: &Shape) -> bool {
4337 shape.ocol == 0 && shape.cells.columns == self.cells.columns
4338 }
4339
4340 pub fn full_dim_split(&self, shapes: &Shapes) -> (Colour, Shapes) {
4341 let mut div_colour = NoColour;
4342 let mut horizontal = false;
4343 let mut shapes = shapes.clone();
4344
4345 for s in shapes.shapes.iter_mut() {
4346 if self.full_row(s) {
4347 horizontal = true;
4348 div_colour = s.colour;
4350 } else if self.full_col(s) {
4351 horizontal = false;
4352 div_colour = s.colour;
4354 }
4355 }
4356
4357 if horizontal {
4358 shapes.shapes.sort_by(|a,b| (a.ocol,a.orow).cmp(&(b.ocol,b.orow)));
4359 } else {
4360 shapes.shapes.sort_by(|a,b| (a.orow,a.ocol).cmp(&(b.orow,b.ocol)));
4361 }
4362
4363 (div_colour, shapes)
4364 }
4365
4366 pub fn split_2(&self) -> Shapes {
4367 if self.cells.rows % 2 != 0 && self.cells.columns % 2 != 0 {
4368 return Shapes::new();
4369 }
4370
4371 let mut shapes = Shapes::new_sized(self.cells.rows, self.cells.columns);
4372 let hr = self.cells.rows / 2;
4373 let hc = self.cells.columns / 2;
4374
4375 let s1 = if self.cells.rows > self.cells.columns {
4377 self.subgrid(0, hr, 0, self.cells.columns)
4378 } else {
4379 self.subgrid(0, self.cells.rows, 0, hc)
4380 };
4381 let s2 = if self.cells.rows > self.cells.columns {
4382 self.subgrid(hr, self.cells.rows - hr, 0, self.cells.columns)
4383 } else {
4384 self.subgrid(0, self.cells.rows, hc, self.cells.columns - hc)
4385 };
4386
4387 shapes.shapes = vec![s1.as_shape(), s2.as_shape()];
4388
4389 shapes
4390 }
4391
4392 pub fn full(&self) -> bool {
4393 if self.cells.rows == 0 {
4394 return false;
4395 }
4396 for cell in self.cells.values() {
4397 if cell.colour == Black {
4398 return false;
4399 }
4400 }
4401
4402 true
4403 }
4404
4405 pub fn get_patch(&self, r: usize, c: usize, rows: usize, cols: usize) -> Shape {
4406 match self.cells.slice(r .. r + rows, c .. c + cols) {
4407 Ok(m) => Shape::new(r, c, &m),
4408 Err(_e) => {
4409 Shape::trivial()
4412 }
4413 }
4414
4415 }
4416
4417 pub fn fill_patch_mut(&mut self, other: &Shape, or: usize, oc: usize) {
4418 if self.size() <= other.size() {
4419 return;
4420 }
4421
4422 for (r, c) in other.cells.keys() {
4423 if self.cells[(or + r, oc + c)].colour == Black {
4424 self.cells[(or + r, oc + c)].colour = other.cells[(r, c)].colour;
4425 }
4426 }
4427 }
4428
4429
4430 pub fn fill_patch_coord_mut(&mut self, or: usize, oc: usize, rs: usize, cs: usize, colour: Colour) {
4431 for r in or .. or + rs {
4432 for c in oc .. oc + cs {
4433 self.cells[(r, c)].colour = colour;
4434 }
4435 }
4436 }
4437
4438 pub fn used_in_row(&self, r: usize, colour: Colour) -> bool {
4453 for c in 0 .. self.cells.columns {
4454 if self.cells[(r,c)].colour == colour {
4455 return true;
4456 }
4457 }
4458
4459 false
4460 }
4461
4462 pub fn used_in_col(&self, c: usize, colour: Colour) -> bool {
4463 for r in 0 .. self.cells.rows {
4464 if self.cells[(r,c)].colour == colour {
4465 return true;
4466 }
4467 }
4468
4469 false
4470 }
4471
4472 pub fn solve(&mut self, pred: &dyn Fn(&Self, usize, usize, Colour) -> bool) -> bool {
4499 self.solve_depth(pred, 6)
4500 }
4501
4502 pub fn solve_depth(&mut self, pred: &dyn Fn(&Self, usize, usize, Colour) -> bool, depth: usize) -> bool {
4503 fn find_empty_cell(grid: &Grid) -> Option<(usize, usize)> {
4504 for ((r, c), cell) in grid.cells.items() {
4505 if cell.colour == Black {
4506 return Some((r, c));
4507 }
4508 }
4509
4510 None
4511 }
4512
4513 if self.cells.rows != self.cells.columns || self.cells.rows > 9 || depth == 0 {
4515 return false;
4516 }
4517
4518 if let Some((r, c)) = find_empty_cell(self) {
4519 for n in 1 ..= self.cells.rows {
4520 let colour = Colour::from_usize(n);
4521
4522 if pred(self, r, c, colour) {
4523 self.cells[(r,c)].colour = colour;
4524
4525 if self.solve_depth(pred, depth - 1) {
4526 return true;
4527 }
4528
4529 self.cells[(r,c)].colour = Black;
4530 }
4531 }
4532 return false;
4533 }
4534 true
4535 }
4536}
4537
4538#[derive(Debug, Clone, PartialEq)]
4539pub struct QualifiedGrid {
4540 pub grid: Grid,
4541 pub bg: Colour,
4542 pub shapes: Shapes,
4543 pub coloured_shapes: Shapes,
4544 pub black: Shapes,
4545}
4546
4547impl QualifiedGrid {
4548 pub fn new(data: &[Vec<usize>]) -> Self {
4549 let grid = Grid::duplicate(data);
4550 let bg = grid.has_bg_grid();
4551 let shapes = if bg == NoColour {
4552 grid.to_shapes()
4553 } else {
4554 grid.to_shapes_bg(bg)
4555 };
4556 let coloured_shapes = if bg == NoColour {
4557 grid.to_shapes_coloured()
4558 } else {
4559 grid.to_shapes_coloured_bg(bg)
4560 };
4561 let black = grid.find_black_patches();
4562
4563 Self { grid: grid.clone(), bg, shapes, coloured_shapes, black }
4564 }
4565
4566 pub fn new_cons(data: &[Vec<usize>]) -> Self {
4567 let grid = Grid::duplicate(data);
4568 let bg = grid.has_bg_grid();
4569 let shapes = if bg == NoColour {
4570 grid.to_shapes_cons()
4571 } else {
4572 grid.to_shapes_bg_cons(bg)
4573 };
4574 let coloured_shapes = if bg == NoColour {
4575 grid.to_shapes_coloured()
4576 } else {
4577 grid.to_shapes_coloured_bg(bg)
4578 };
4579 let black = grid.find_black_patches();
4580
4581 Self { grid: grid.clone(), bg, shapes, coloured_shapes, black }
4582 }
4583
4584 pub fn trivial() -> Self {
4585 Self { grid: Grid::trivial(), bg: NoColour, shapes: Shapes::trivial(), coloured_shapes: Shapes::trivial(), black: Shapes::trivial() }
4586 }
4587
4588 pub fn single_shape_count(&self) -> usize {
4589 self.shapes.len()
4590 }
4591
4592 pub fn colour_shape_count(&self) -> usize {
4593 self.coloured_shapes.len()
4594 }
4595
4596 pub fn has_bg_shape(&self) -> bool {
4597 for s in self.shapes.shapes.iter() {
4598 if s.orow == 0 && s.ocol == 0 && s.cells.rows == self.grid.cells.rows && s.cells.columns == self.grid.cells.columns {
4599 return true;
4600 }
4601 }
4602
4603 false
4604 }
4605
4606 pub fn has_bg_coloured_shape(&self) -> bool {
4607 for s in self.coloured_shapes.shapes.iter() {
4608 if s.orow == 0 && s.ocol == 0 && s.cells.rows == self.grid.cells.rows && s.cells.columns == self.grid.cells.columns {
4609 return true;
4610 }
4611 }
4612
4613 false
4614 }
4615
4616 }