arc_agi/
grid.rs

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    //pub cats: BTreeSet<ShapeCategory>,
18}
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        //self.colour.cmp(&other.colour)
24    }
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    /*
80    pub fn new_from_sized_matrix(x: usize, y: usize, shape: Matrix<Cell>) -> Self {
81        let mut cells: Matrix<Cell> = Matrix::from_fn(x, y, |(_, _)| Cell::new_empty());
82
83        for ((x, y), c) in shape.items() {
84            cells[(x, y)].x = x;
85            cells[(x, y)].y = y;
86            cells[(x, y)].colour = c.colour;
87        }
88
89        Self { cells }
90    }
91    */
92
93    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    // TODO crap improve
302    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    /*
349    pub fn stretch_up(&self) -> Self {
350        self.mirrored_x().stretch_up().mirrored_x()
351    }
352    */
353
354    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    /*
413     * move_up
414     * stretch down
415     * stretch_up
416     */
417
418    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 {
589            //    c.colour = to;
590            //}
591            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            // Clip
640            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    // Not perfect: No start and only works for pixels not shapes
665    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 != colour {
805            //if term && (*cell_colour != bg || *cell_colour != colour) {
806            //if term && *cell_colour != bg {
807            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    // unfinished 0e671a1a
1062    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    /*
1261    fn extend_inc(&self, lr: bool, amount: usize) -> Self {
1262        let rows = self.cells.rows;
1263        let cols = self.cells.columns;
1264        let mut grid = if lr {
1265            Self::new(rows, cols + amount, Black)
1266        } else {
1267            Self::new(rows + amount, cols, Black)
1268        };
1269
1270        for ((r, c), cell) in self.cells.items() {
1271            grid.cells[(r,c)].row = r;
1272            grid.cells[(r,c)].col = c;
1273            grid.cells[(r,c)].colour = cell.colour;
1274        }
1275
1276        grid.colour = self.colour;
1277
1278        grid
1279    }
1280    */
1281
1282    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        // not efficient!
1319        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            // not happy with this
1589            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            // not happy with this
1597            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                // untidy but necessary
1610                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            }
1646//println!("Layers: {layer} {:?}", cc);
1647
1648            for 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    /*
1666    pub fn find_xy_seq(&self, xseq: &[Colour], yseq: &[Colour]) -> (bool, (usize, usize)) {
1667
1668        if xseq.is_empty() || Colour::single_colour_vec(&xseq) {
1669            (false, self.find_y_seq(0, 0, yseq, xseq.len()))
1670        } else if !yseq.is_empty() {
1671            (true, self.find_x_seq(0, 0, xseq, yseq.len()))
1672        } else {
1673            (false, (0, 0))
1674        }
1675/*
1676println!("1 #### {}/{} {}/{}", xsx, xsy, ysx, ysy);
1677
1678        while (xsx != ysx || xsy != ysy) && xsx != usize::MAX && ysx != usize::MAX {
1679            if xsx < ysx || xsy < ysy {
1680                (xsx, xsy) = self.find_x_seq(xsx, xsy + 1, xseq, yseq.len());
1681            } else {
1682                (ysx, ysy) = self.find_y_seq(ysx + 1, ysy, yseq, xseq.len());
1683            }
1684println!("2 #### {}/{} {}/{}", xsx, xsy, ysx, ysy);
1685        }
1686
1687        if xsx != usize::MAX {
1688           (xsx, xsy)
1689        } else {
1690           (ysx, ysy)
1691        }
1692*/
1693        //(xsx, xsy)
1694        //(ysx, ysy)
1695        //self.find_x_seq(xsx, xsy + 1, xseq, yseq.len())
1696        //self.find_y_seq(ysx + 1, ysy, yseq, xseq.len())
1697    }
1698    */
1699
1700    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                        }
1735//println!("{} {} == {} {xs}/{ys} {x} {y}", cnt, Colour::to_usize(seq[cnt]), Colour::to_usize(c.colour));
1736//println!("{sy} ==== {cnt} {:?}", c.colour);
1737                        if 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, &copy)
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, &copy)
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    /*
2238    pub fn rotate_90(&mut self, times: usize) {
2239        if self.cells.rows == self.cells.columns {
2240            return;
2241        }
2242
2243        self.cells.rotate_cw(times);
2244
2245        for r in 0 .. self.cells.rows {
2246            for c in 0 .. self.cells.columns {
2247                self.cells[(r, c)].row = r;
2248                self.cells[(r, c)].col = c;
2249            }
2250        }
2251    }
2252
2253    pub fn rotate_270(&mut self, times: usize) {
2254        if self.cells.rows != self.cells.columns {
2255            return;
2256        }
2257
2258        self.cells.rotate_ccw(times);
2259
2260        for r in 0 .. self.cells.rows {
2261            for c in 0 .. self.cells.columns {
2262                self.cells[(r, c)].row = r;
2263                self.cells[(r, c)].col = c;
2264            }
2265        }
2266    }
2267    */
2268
2269    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 {      // Identity rotation
2316        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)].row = r;
2340                //rot.cells[(c, n - r - 1)].col = c;
2341                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().clone()
2405            *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        // First round
2437        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(&copy.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
2544//println!("---- {colour:?} {square}");
2545        if self.cells.len() <= 9 || (square && self.cells.rows != self.cells.columns) {
2546            return colour;
2547        }
2548
2549        let mut nox = false;    // may be only a y axis
2550
2551        '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;  // we have found a candidate
2567            }
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;  // we have found one
2591            }
2592        }
2593
2594        NoColour
2595    }
2596
2597    // TODO
2598    pub fn ray(&self, _direction: (i8, i8)) -> Shape {
2599        Shape::new_empty()
2600    }
2601
2602    // TODO
2603    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                // find candidate
2725                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    // Size 4 and 9
2766    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            // Find starting position
2800            let rc = cells.items().filter(|(_, cell)| cell.colour == colour).map(|(pos, _)| pos).min();
2801            //if let Some((0, 0)) = xy {    // This is allowed???
2802            //    return None;
2803            //}
2804
2805            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                // Set all cells to correct position
2816                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                // Set cells to correct colour 
2827                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            /*  11e1fe23 trans ?
2845            if self.cells.rows == s.cells.rows && self.cells.columns == s.cells.columns {
2846                shapes.add(&s);
2847            } else {
2848                let sg = self.subgrid(s.orow, s.cells.rows, s.ocol, s.cells.columns);
2849//sg.show();
2850                let mut ss = sg.to_shapes_coloured();
2851                if ss.shapes.len() > 1 {
2852                    for s2 in ss.shapes.iter_mut() {
2853//println!("{or}/{oc}");
2854//s2.show_summary();
2855//s2.show();
2856                        s2.to_position_mut(or + s.orow, oc + s.ocol);
2857
2858                        shapes.add(&s2);
2859                    }
2860                } else {
2861                    shapes.add(&s);
2862                }
2863            }
2864            */
2865        }
2866
2867        shapes
2868    }
2869
2870    /*
2871    // Assumes two offset rectangles
2872    pub fn find_touching(&self, colour: Colour) -> (bool, usize, usize) {
2873        let is_colour = self.cells[(0,0)].colour == colour;
2874        let mut rr = 0;
2875        let mut cc = 0;
2876
2877        for r in 1 .. self.cells.rows {
2878            if !is_colour && self.cells[(r,0)].colour == colour ||
2879                is_colour && self.cells[(r,0)].colour != colour {
2880                rr = r - 1;
2881                break;
2882            }
2883        }
2884        for c in 1 .. self.cells.columns {
2885            if !is_colour && self.cells[(0,c)].colour == colour ||
2886                is_colour && self.cells[(0,c)].colour != colour {
2887                cc = c - 1;
2888                break;
2889            }
2890        }
2891
2892        (is_colour, rr, cc)
2893    }
2894    */
2895
2896    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        // patches tend to be smaller
2909        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();   // Trivial shapes
2961        }
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                // Find start of x range
2975                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                    // Find start of y range
2987                    for y in sc .. cs[j + 1] {
2988                        if self.cells[(0, y)].colour != bg {
2989                            break;
2990                        }
2991                    }
2992                }
2993                // Find shape
2994                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);
3042//println!("{shapes:?}"); 
3043
3044              shapes.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    // Split cell composed of 2 cells joined at a corner apart
3064    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 {    // Not diagonally opposed shapes
3080                shapes.add(s);
3081            }
3082        } else {
3083            shapes.add(s);
3084        }
3085    }
3086
3087    // Find shapes in a grid
3088    fn to_shapes_base(&self, same_colour: bool, diag: bool, cons: bool, bg: Colour) -> Shapes {
3089        // TODO Fix training 2204b7a8 - left border
3090        fn mshape(same_colour: bool, bgc: Colour, bg: Colour, cells: &mut Matrix<Cell>, diag: bool) -> Option<(usize, usize, Matrix<Cell>)> {
3091            // Find starting position
3092            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 mut other: Vec<(usize, usize)> = Vec::new();
3098
3099                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                // S cells to correct position
3107                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                        // Find other same colour objects in bounding box
3115                        // and add to reachable???
3116                        /*
3117                        if !reachable.contains(&(x, y)) && (!same_colour || start_colour == cells[(x, y)].colour) {
3118                            reachable.insert((x, y));
3119                        }
3120                        */
3121                    }
3122                }
3123                // Set cells to correct colour 
3124                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                /*
3153                // Quit if Background not Black
3154                let mut bg = bg;
3155                let mut bgc = bgc;
3156                if self.size() == s.size() {
3157println!("BG not Black {:?}", s.colour);
3158                    return shapes;
3159                }
3160                if self.size() == s.size() && s.colour != Mixed {
3161//println!("{} == {} {:?} {:?}", self.size(), s.size(), self.colour, s.colour);
3162                    bgc = s.colour;
3163                    bg = NoColour;
3164//println!("--- {:?}", self.cells);
3165                    cells = self.cells.clone();
3166
3167                    if let Some((ox, oy, m)) = mshape(same_colour, bgc, bg, &mut cells, diag) {
3168                        let s = Shape::new(ox, oy, &m);
3169
3170                        Self::de_diag(ox, oy, &s, &mut shapes);
3171                    }
3172                    continue;
3173                }
3174                */
3175
3176                Self::de_diag(or, oc, &s, &mut shapes);
3177            }
3178        } else {
3179            shapes = self.to_shapes_base_bg(bg);
3180
3181            // Hum, not grid, try ordinary shape conversion
3182            if shapes.is_empty() {
3183                // Not Right???
3184                //while let Some((ox, oy, m)) = mshape(same_colour, Black, Black, &mut cells, diag) {
3185                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            //// unfinished 0e671a1a
3193//shapes.show();
3194
3195        //shapes.categorise_shapes();
3196
3197        //shapes.patch_shapes()
3198        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    // ea959feb trans - does not work
3370    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];
3377//println!("{r}");
3378                let 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        // Must be same shape
3578        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    // Same footprint
3657    pub fn equal_footprint(&self, other: &Self) -> bool {
3658        self.cells.columns == other.cells.columns && self.cells.rows == other.cells.rows
3659    }
3660
3661    // Same shape
3662    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    /*
3677    pub fn diff_only_same(&self) -> Self {
3678        let mut g = self.clone();
3679
3680        for c in g.cells.values_mut() {
3681            if Colour::to_usize(c.colour) / 30 < 10 {
3682                c.colour = Colour::from_usize(Colour::to_usize(c.colour) / 30);
3683            } else {
3684                c.colour = Black;
3685            }
3686        }
3687
3688        g
3689    }
3690    */
3691
3692    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    // Experiiments on difference allowed
3707    /*
3708    pub fn diff_only(&self, colour: Colour, n: usize) -> Self {
3709        match n {
3710           0 => self.diff_only_and(colour),
3711           1 => self.diff_only_or(colour),
3712           2 => self.diff_only_xor(colour),
3713           _ => Self::trivial()
3714        }
3715    }
3716    */
3717
3718    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    // GEN
3817    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        // Must be same shape
3875        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        // different shapes
3904        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
3920/*
3921    pub fn diff_map(&self, to: &Self) -> HashMap<Colour, Colour> {
3922        let mut map: HashMap<Colour, Colour> = HashMap::new();
3923        if self.cells.rows != to.cells.rows || self.cells.columns != to.cells.columns {
3924            return map;
3925        }
3926        let inp = self.diff_orig(to);
3927        let inp = if let None = inp {
3928            return map;
3929        } else {
3930            inp.unwrap()
3931        };
3932        let out = self.diff(to);
3933        let out = if let None = out {
3934            return map;
3935        } else {
3936            out.unwrap()
3937        };
3938
3939
3940        //for (((x, y), ic), ((_, _), oc)) in inp.cells.items().zip(out.cells.items()) {
3941        for ((x, y), c) in inp.cells.items() {
3942            match Colour::to_usize(c.colour) {
3943                units @ 0 ..= 9 => {
3944                    let units = Colour::from_usize(units);
3945                    map.insert(units, units)
3946                },
3947                tens @ 10 ..= 19 => {
3948                    //let from = Colour::from_usize(tens);
3949                    let from = self.cells[(x,y)].colour;
3950                    let to = Colour::from_usize(tens % 10);
3951                    map.insert(from, to)
3952                },
3953                twenties @ 20 ..= 29 => {
3954                    let from = self.cells[(x,y)].colour;
3955                    map.insert(from, Black)
3956                },
3957                thirties @ 30 ..= 39 => {
3958                    let from = self.cells[(x,y)].colour;
3959                    let to = Colour::from_usize(thirties % 10);
3960                    map.insert(from, to)
3961                },
3962                forties @ 40 ..= 49 => {    // Should not happen
3963                    let from = self.cells[(x,y)].colour;
3964                    let to = Colour::from_usize(forties % 10);
3965                    map.insert(from, to)
3966                },
3967                fifties @ 50 ..= 59 => {
3968                    let from = self.cells[(x,y)].colour;
3969                    let to = Colour::to_usize(out.cells[(x,y)].colour);
3970                    let to = Colour::from_usize(to % 10);
3971                    map.insert(from, to)
3972                },
3973                other => {
3974                    let other = Colour::from_usize(other);
3975                    map.insert(other, other)
3976                },
3977            };
3978        }
3979
3980        map
3981    }
3982
3983    pub fn diff_update(&self, map: HashMap<Colour, Colour>) -> Self {
3984        let mut ans = self.clone();
3985
3986        for ((x, y), c) in self.cells.items() {
3987            if let Some(colour) = map.get(&c.colour) {
3988                ans.cells[(x,y)].colour = *colour;
3989            } else {
3990            }
3991        }
3992
3993        ans
3994    }
3995*/
3996
3997    pub 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        }
4241//gs.iter().for_each(|g| g.show());
4242
4243        gs
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        }
4293//println!("1 {rows} {cols}");
4294        // too strict?
4295        if ((rows - dr * 3) % 4 != 0 || cols % 4 != 0) &&
4296            (rows % 4 != 0 || (cols - dc * 3) % 4 != 0) {
4297            //return shapes;
4298            dr = 0;
4299            dc = 0;
4300        }
4301//println!("2 {rows} {cols}");
4302        /*
4303        */
4304
4305        let (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                //s.to_position_mut(s.orow, s.ocol * 2 + 1);
4349                div_colour = s.colour;
4350            } else if self.full_col(s) {
4351                horizontal = false;
4352                //s.to_position_mut(s.orow * 2 + 1, s.ocol);
4353                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 % 2 == 0 {
4376        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                //eprintln!("{e}");
4410
4411                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    // TODO
4439    /*
4440    fn compress_1d(&self) -> Self {
4441        self.clone()
4442    }
4443
4444    fn compress_2d(&self) -> Self {
4445        self.clone()
4446    }
4447    */
4448
4449    /**
4450     * Code constraint solver predicates
4451     */
4452    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    // Only needed for Suduko type problems
4473    /*
4474    pub fn used_in_subgrid(&self, sr: usize, sc: usize, colour: Colour) -> bool {
4475        let rl = self.cells.rows;
4476        let cl = self.cells.columns;
4477        let rs = (rl as f32).sqrt().abs() as usize;
4478        let cs = (cl as f32).sqrt().abs() as usize;
4479
4480        for r in 0 .. rs {
4481            for c in 0 .. cs {
4482                if self.cells[(r + sr,c + sc)].colour == colour {
4483                    return true;
4484                }
4485            }
4486        }
4487
4488        false
4489    }
4490
4491    fn is_valid_move(&self, r: usize, c: usize, colour: Colour) -> bool {
4492        //!self.used_in_row(r, colour) && !self.used_in_col(c, colour) && !self.used_in_subgrid(r - r % 3, c - c % 3, colour)
4493        !self.used_in_row(r, colour) && !self.used_in_col(c, colour)
4494    }
4495    */
4496
4497    // Expensive so only call when sure
4498    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        // Might be a bit too conmservative on recursive depth!
4514        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    /*
4617    // TODO: improve!
4618    pub fn grid_likelyhood(&self) -> f32 {
4619        let shapes_any = self.to_shapes_cbg();
4620        if shapes_any.len() == 1 { return 1.0; }
4621        let shapes = self.to_shapes_single_colour_cbg();
4622        let count = shapes.shapes.len();
4623        if shapes_any.shapes.len() as f32 / count as f32 > 10.0 { return 1.0; }
4624        let singles = shapes.shapes.iter().filter(|s| s.size() == 1).count();
4625
4626        if count == 0 {
4627            1.0
4628        } else {
4629            singles as f32 / count as f32
4630        }
4631    }
4632    */
4633}