arc_agi/
shape.rs

1use std::cmp::Ordering;
2use std::collections::{BTreeMap, BTreeSet, HashMap};
3use array_tool::vec::Uniq;
4use pathfinding::prelude::Matrix;
5use crate::cats::Colour::*;
6use crate::cats::Direction::*;
7use crate::utils::*;
8//use crate::cats::CellCategory::*;
9use crate::cats::*;
10use crate::cell::*;
11use crate::grid::*;
12use crc::Crc;
13
14#[derive(Debug, Clone, Eq)]
15pub struct Shape {
16    pub orow: usize,
17    pub ocol: usize,
18    pub colour: Colour,
19//    pub sid: u32,
20    pub cells: Matrix<Cell>,
21    //pub cats: BTreeSet<ShapeCategory>,
22    //pub io_edges: BTreeSet<ShapeEdgeCategory>,
23}
24
25/*
26use std::hash::Hash;
27use std::hash::Hasher;
28use std::hash::DefaultHasher;
29impl Hash for Shape {
30    fn hash<H>(&self, state: &mut H)
31    where
32        H: Hasher,
33    {
34        /*
35        fn calculate_hash(t: &str) -> u64 {
36            let mut s = DefaultHasher::new();
37
38            s.write(t.as_bytes());
39            s.finish()
40        }
41        */
42
43        //state.write_usize(self.ox);
44        //state.write_usize(self.oy);
45        //state.write_u64(calculate_hash(&self.to_json()));
46        for c in self.cells.values() {
47            state.write_usize(c.colour.to_usize());
48        }
49        let _ = state.finish();
50    }
51}
52*/
53
54impl PartialEq for Shape {
55    fn eq(&self, other: &Shape) -> bool {
56        self.orow == other.orow && self.ocol == other.ocol && self.cells.rows == other.cells.rows && self.cells.columns == other.cells.columns
57    }
58}
59 
60        //let sdist = ((self.ox * self.ox + self.oy * self.oy) as f64).sqrt();
61 
62impl Ord for Shape {
63    fn cmp(&self, other: &Self) -> Ordering {
64        (self.orow, self.ocol, &self.to_json(), &self.colour).cmp(&(other.orow, other.ocol, &other.to_json(), &other.colour))
65        //(&self.to_json(), self.ox, &self.oy).cmp(&(&other.to_json(), other.ox, &other.oy))
66    }
67}
68
69impl PartialOrd for Shape {
70    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
71        Some(self.cmp(other))
72    }
73}
74
75impl Default for Shapes {
76    fn default() -> Self {
77        Self::new()
78    }
79}
80
81impl Shape {
82    pub fn new(orow: usize, ocol: usize, cells: &Matrix<Cell>) -> Self {
83        let (colour, _) = Self::cell_colour_cnt_mixed(cells, true, true);
84        let mut new_cells = cells.clone();
85
86        for (r, c) in cells.keys() {
87            new_cells[(r, c)].row = r + orow;
88            new_cells[(r, c)].col = c + ocol;
89        }
90
91        //let cats: BTreeSet<ShapeCategory> = BTreeSet::new();
92        //let io_edges: BTreeSet<ShapeEdgeCategory> = BTreeSet::new();
93        let new_cells = Self::cell_category(&new_cells);
94
95        let res = Self { orow, ocol, colour, cells: new_cells };
96
97        //res.categorise_shape();
98
99        res
100    }
101
102    pub fn new_cells(cells: &Matrix<Cell>) -> Self {
103        let (colour, _) = Self::cell_colour_cnt_mixed(cells, true, true);
104        //let io_edges: BTreeSet<ShapeEdgeCategory> = BTreeSet::new();
105        //let cats: BTreeSet<ShapeCategory> = BTreeSet::new();
106        let cells = Self::cell_category(cells);
107
108        if cells.rows == 0 || cells.columns == 0 {
109            return Shape::trivial();
110        }
111
112        let orow = cells[(0,0)].row;
113        let ocol = cells[(0,0)].col;
114        let res = Self { orow, ocol, colour, cells };
115
116        //res.categorise_shape();
117
118        res
119    }
120
121    pub fn new_sized_coloured(rows: usize, cols: usize, colour: Colour) -> Self {
122        let cells: Matrix<Cell> = Matrix::from_fn(rows, cols, |(rows, cols)| Cell::new_colour(rows, cols, colour));
123        //let io_edges: BTreeSet<ShapeEdgeCategory> = BTreeSet::new();
124        //let cats: BTreeSet<ShapeCategory> = BTreeSet::new();
125
126        Self { orow: 0, ocol: 0, colour, cells }
127    }
128
129    pub fn new_sized_coloured_position(orow: usize, ocol: usize, row: usize, col: usize, colour: Colour) -> Self {
130        let cells: Matrix<Cell> = Matrix::from_fn(row, col, |(r, c)| Cell::new_colour(r + orow, c + ocol, colour));
131
132        //let io_edges: BTreeSet<ShapeEdgeCategory> = BTreeSet::new();
133        //let cats: BTreeSet<ShapeCategory> = BTreeSet::new();
134
135        Self { orow, ocol, colour, cells }
136    }
137
138    pub fn new_empty() -> Self {
139        let cells = Matrix::new(0, 0, Cell::new_empty());
140        //let io_edges: BTreeSet<ShapeEdgeCategory> = BTreeSet::new();
141        //let cats: BTreeSet<ShapeCategory> = BTreeSet::new();
142
143        Self { orow: 0, ocol: 0, colour: NoColour, cells }
144    }
145
146    pub fn trivial() -> Self {
147        Self::new_empty()
148    }
149
150    pub fn new9(&self, corners: bool, colour: Colour) -> Self {
151        let mut s = if self.orow == 0 && self.ocol == 0 {
152            let mut s = Self::new_sized_coloured(2, 2, Transparent);
153            s.cells[(0,0)].colour = self.colour;
154
155            if corners {
156                s.cells[(1,1)].colour = colour;
157            } else {
158                s.cells[(0,1)].colour = colour;
159                s.cells[(1,0)].colour = colour;
160            }
161
162            s
163        } else if self.orow > 0 && self.ocol == 0 {
164            let mut s = Self::new_sized_coloured(3, 2, Transparent);
165
166            s.cells[(1,0)].colour = self.colour;
167
168            if corners {
169                s.cells[(0,1)].colour = colour;
170                s.cells[(2,1)].colour = colour;
171            } else {
172                s.cells[(2,0)].colour = colour;
173                s.cells[(1,1)].colour = colour;
174            }
175
176            s
177        } else if self.orow == 0 && self.ocol > 0 {
178            let mut s = Self::new_sized_coloured(2, 3, Transparent);
179
180            s.cells[(0,1)].colour = self.colour;
181
182            if corners {
183                s.cells[(1,0)].colour = colour;
184                s.cells[(1,2)].colour = colour;
185            } else {
186                s.cells[(0,2)].colour = colour;
187                s.cells[(1,1)].colour = colour;
188            }
189
190            s
191        } else {
192            let mut s = Self::new_sized_coloured(3, 3, Transparent);
193
194            s.cells[(1,1)].colour = self.colour;
195
196            if corners {
197                s.cells[(0,0)].colour = colour;
198                s.cells[(0,2)].colour = colour;
199                s.cells[(2,0)].colour = colour;
200                s.cells[(2,2)].colour = colour;
201            } else {
202                s.cells[(0,1)].colour = colour;
203                s.cells[(1,0)].colour = colour;
204                s.cells[(2,1)].colour = colour;
205                s.cells[(1,2)].colour = colour;
206            }
207
208            s
209        };
210
211        s.orow = if self.orow > 0 { self.orow - 1 } else { self.orow };
212        s.ocol = if self.ocol > 0 { self.ocol - 1 } else { self.ocol };
213
214        s.colour = Mixed;
215
216        for r in 0 .. s.cells.rows {
217            for c in 0 .. s.cells.columns {
218                s.cells[(r,c)].row = s.orow + r;
219                s.cells[(r,c)].col = s.ocol + c;
220            }
221        }
222
223        s
224    }
225
226    /*
227    pub fn shape_from_reachable(&self, reachable: BTreeSet<(usize, usize)>) -> Self {
228        reachable.iter().for_each(|&i| self.cells[i].colour = new_colour)
229    }
230    */
231
232    pub fn is_full(&self) -> bool {
233        for c in self.cells.values() {
234            if c.colour == Black {
235                return false;
236            }
237        }
238
239        true
240    }
241
242    pub fn corners(&self) -> (usize, usize, usize, usize) {
243        (self.orow, self.ocol, self.orow + self.cells.rows - 1, self.ocol + self.cells.columns - 1)
244    }
245
246    pub fn same_patch(&self, other: &Self) -> bool {
247//self.show();
248        if self.size() != other.size() || self.cells.rows != other.cells.rows {
249            return false;
250        }
251
252        for (rc, c) in self.cells.items() {
253//println!("{:?} {:?}", c.colour, other.cells[rc].colour);
254            if c.colour != Black && c.colour != other.cells[rc].colour {
255                return false;
256            }
257        }
258//println!("----------------");
259
260        true
261    }
262
263    pub fn fill(&self, other: &Self) -> Self {
264        if self.size() != other.size() || !self.is_square() {
265            return self.clone();
266        }
267
268        let mut shape = self.clone();
269
270        for rc in self.cells.keys() {
271            if self.cells[rc].colour == Black {
272                shape.cells[rc].colour = other.cells[rc].colour;
273            }
274        }
275        
276        shape
277    }
278
279    pub fn make_symmetric(&self) -> Self {
280        let shape = self.clone();
281        let shape = shape.fill(&shape.rotated_90());
282        let shape = shape.fill(&shape.rotated_180());
283
284        shape.fill(&shape.rotated_270())
285    }
286
287    pub fn col_symmetric_mut(&self, shapes: &mut Shapes) {
288        let cols = self.cells.columns;
289        let even = cols %2 == 0;
290        let half = cols / 2;
291        let len = half + (if even { 0 } else { 1 });
292//println!("{cols} {even} {half} {len}");
293let this = self.clone();
294let mut shapes2 = shapes.clone_base();
295let mut cnt1 = 0;
296let mut cnt2 = 0;
297
298        let s1 = self.subshape(0, self.cells.rows, 0, len);
299        let s2 = self.subshape(0, self.cells.rows, half, len).mirrored_c();
300
301        if let Some(mut diff) = s1.diff(&s2) {
302            for cell in diff.cells.values_mut() {
303                cell.colour = if cell.colour.is_same() {
304                    cell.colour.to_base()
305                } else {
306cnt1 += 1;
307                    Black
308                };
309            }
310
311            shapes.shapes.push(diff.to_position(self.orow, self.ocol));
312            shapes.shapes.push(diff.mirrored_c().to_position(self.orow, self.ocol + half));
313//shapes.to_grid().show();
314        }
315
316        let s1 = this.subshape(0, self.cells.rows, 1, len);
317        //let s2 = this.subshape(0, self.cells.rows, half, len).mirrored_c();
318
319        if let Some(mut diff) = s1.diff(&s2) {
320            for cell in diff.cells.values_mut() {
321                cell.colour = if cell.colour.is_same() {
322                    cell.colour.to_base()
323                } else {
324cnt2 += 1;
325                    Black
326                };
327            }
328
329            shapes2.shapes.push(diff.to_position(self.orow, self.ocol + 1));
330            shapes2.shapes.push(diff.mirrored_c().to_position(self.orow, self.ocol + half));
331//shapes2.to_grid().show();
332//println!("### {cnt1} {cnt2}");
333        }
334
335        if cnt2 <= cnt1 {
336            shapes.shapes.pop();
337            shapes.shapes.pop();
338
339            for s in shapes2.shapes.iter() {
340                shapes.shapes.push(s.clone());
341            }
342        }
343    }
344
345    // must be odd size
346    pub fn new_square(r: usize, c: usize, size: usize, colour: Colour) -> Self {
347        let mut square = Self::new_sized_coloured(size, size, Black);
348
349        square.colour = colour;
350
351        for (r, c) in square.cells.keys() {
352            if r == 0 || c == 0 || r == square.cells.rows - 1 || c == square.cells.columns - 1 {
353                square.cells[(r, c)].colour = colour;
354            }
355        }
356
357        square.translate_absolute(r, c)
358    }
359
360    pub fn is_trivial(&self) -> bool {
361        self.cells.rows == 0 && self.cells.columns == 0 && self.colour == Black
362    }
363
364    pub fn remove(&mut self, c: &Cell) {
365        let mut c = c.clone();
366
367        c.colour = Black;
368
369        self.cells[(c.row, c.col)] = c.clone();
370    }
371
372    pub fn to_shapes(&self) -> Shapes {
373        self.to_shapes_base(false)
374    }
375
376    pub fn to_shapes_coloured(&self) -> Shapes {
377        self.to_shapes_base(true)
378    }
379
380    pub fn to_shapes_base(&self, coloured: bool) -> Shapes {
381        let mut inner_shapes = if coloured {
382            self.to_grid().to_shapes_coloured_cbg()
383        } else {
384            self.to_grid().to_shapes()
385        };
386
387        for s in inner_shapes.shapes.iter_mut() {
388            s.orow += self.orow;
389            s.ocol += self.ocol;
390
391            for r in 0 .. s.cells.rows {
392                for c in 0 .. s.cells.columns {
393                    s.cells[(r,c)].row += self.orow;
394                    s.cells[(r,c)].col += self.ocol;
395                }
396            }
397        }
398
399        inner_shapes
400    }
401
402    pub fn pixels_in_shape(&self) -> usize {
403        let bg = self.majority_colour();
404
405        let pixels: usize = self.cells.values()
406            .filter(|c| c.colour != bg)
407            .count();
408            
409        pixels
410    }
411
412    pub fn shrink_any(&self, coloured: bool) -> Self {
413        let mut s = if coloured {
414            self.to_grid().to_shapes_coloured().shapes[0].clone()
415        } else {
416            self.to_grid().to_shapes().shapes[0].clone()
417        };
418
419        s.orow = self.orow;
420        s.ocol = self.ocol;
421
422        for r in 0 .. s.cells.rows {
423            for c in 0 .. s.cells.columns {
424                s.cells[(r,c)].row = s.orow + r;
425                s.cells[(r,c)].col = s.ocol + c;
426            }
427        }
428
429        s
430    }
431
432    pub fn remove_border(&self) -> Self {
433        let m = self.cells.slice(1 .. self.cells.rows - 2, 1 .. self.cells.columns - 2);
434
435        if let Ok(m) = m {
436            Self::new_cells(&m)
437        } else {
438            Self::trivial()
439        }
440    }
441
442    pub fn remove_ragged_left(&self) -> Self {
443        for r in 1 .. self.cells.rows - 1 {
444            if self.cells[(r,0)].colour == Black {
445                if let Ok(cells) = self.cells.slice(0 .. self.cells.rows, 1 .. self.cells.columns) {
446                    return Shape::new_cells(&cells);
447                } else {
448                    break;
449                }
450            }
451        }
452
453        self.clone()
454    }
455
456    pub fn remove_ragged_right(&self) -> Self {
457        for r in 1 .. self.cells.rows - 1 {
458            if self.cells[(r,self.cells.columns-1)].colour == Black {
459                if let Ok(cells) = self.cells.slice(0 .. self.cells.rows, 0 .. self.cells.columns-1) {
460                    return Shape::new_cells(&cells);
461                } else {
462                    break;
463                }
464            }
465        }
466
467        self.clone()
468    }
469
470    pub fn remove_ragged_top(&self) -> Self {
471        for c in 1 .. self.cells.columns - 1 {
472            if self.cells[(0,c)].colour == Black {
473                if let Ok(cells) = self.cells.slice(1 .. self.cells.rows, 0 .. self.cells.columns) {
474                    return Shape::new_cells(&cells);
475                } else {
476                    break;
477                }
478            }
479        }
480
481        self.clone()
482    }
483
484    pub fn remove_ragged_bottom(&self) -> Self {
485        for c in 1 .. self.cells.columns - 1 {
486            if self.cells[(self.cells.rows-1,c)].colour == Black {
487                if let Ok(cells) = self.cells.slice(0 .. self.cells.rows-1, 0 .. self.cells.columns) {
488                    return Shape::new_cells(&cells);
489                } else {
490                    break;
491                }
492            }
493        }
494
495        self.clone()
496    }
497
498    pub fn has_ragged_left(&self) -> bool {
499        for r in 1 .. self.cells.rows - 1 {
500            if self.cells[(r,0)].colour == Black {
501                return true;
502            }
503        }
504
505        false
506    }
507
508    pub fn has_ragged_right(&self) -> bool {
509        for r in 1 .. self.cells.rows - 1 {
510            if self.cells[(r,self.cells.columns-1)].colour == Black {
511                return true;
512            }
513        }
514
515        false
516    }
517
518    pub fn has_ragged_top(&self) -> bool {
519        for c in 1 .. self.cells.columns - 1 {
520            if self.cells[(0,c)].colour == Black {
521                return true;
522            }
523        }
524
525        false
526    }
527
528    pub fn has_ragged_bottom(&self) -> bool {
529        for c in 1 .. self.cells.columns - 1 {
530            if self.cells[(self.cells.rows-1,c)].colour == Black {
531                return true;
532            }
533        }
534
535        false
536    }
537
538    // TODO: Fix 25094a63
539    pub fn remove_ragged_border(&self) -> Self {
540        let mut shape = self.clone();
541        let mut done = true;
542
543        loop {
544            if shape.has_ragged_top() {
545                shape = shape.remove_ragged_top();
546                done = false;
547            }
548            if shape.has_ragged_bottom() {
549                shape = shape.remove_ragged_bottom();
550                done = false;
551            }
552            if shape.has_ragged_left() {
553                shape = shape.remove_ragged_left();
554                done = false;
555            }
556            if shape.has_ragged_right() {
557                shape = shape.remove_ragged_right();
558                done = false;
559            }
560            if done {
561                break;
562            } else {
563                done = true;
564            }
565        }
566
567        shape
568    }
569
570    /*
571    pub fn shrink_ragged(&self) -> (usize, usize) {
572        let mut rs = 0;
573        let mut cs = 0;
574        let mut re = self.cells.rows;
575        let mut ce = self.cells.columns;
576
577        for r in 0 .. self.cells.rows {
578            for c in 0 .. self.cells.columns {
579                if self.cells[(r,c)].colour != Black {
580                    if r == 0 || c == 0 || self.cells[(r,c)].colour == Black 
581            }
582        }
583    }
584    */
585
586    pub fn find_colour_pixel_coords(&self, colour: Colour) -> (usize, usize) {
587        for ((r, c), cell) in self.cells.items() {
588            if cell.colour == colour {
589                return (r, c);
590            }
591        }
592
593        (0, 0)
594    }
595
596    pub fn find_different_pixel_coords(&self) -> (usize, usize) {
597        let colour = self.minority_colour();
598
599        self.find_colour_pixel_coords(colour)
600    }
601
602    pub fn find_distinct_colours(&self, bg: Colour) -> Vec<Cell> {
603        self.cells.values().filter(|c| c.colour != bg).cloned().collect()
604    }
605
606    pub fn shrink_border(&self) -> Self {
607        self.shrink_border_colour_n(Black, 1)
608    }
609
610    pub fn shrink_border_n(&self, n: usize) -> Self {
611        self.shrink_border_colour_n(Black, n)
612    }
613
614    pub fn shrink_border_colour(&self, bg: Colour) -> Self {
615        self.shrink_border_colour_n(bg, 1)
616    }
617
618    pub fn shrink_border_colour_n(&self, bg: Colour, n: usize) -> Self {
619        if self.cells.rows < n * 2 || self.cells.columns < n * 2 {
620            return Self::trivial();
621        }
622
623        let mut tlr = 0;
624        let mut tlc = 0;
625        let mut brr = 0;
626        let mut brc = 0;
627
628        for ((r, c), cell) in self.cells.items() {
629            if cell.colour == bg {
630                if r == 0 {
631                    tlr += 1;
632                }
633                if c == 0 {
634                    tlc += 1;
635                }
636                if r == self.cells.rows - 1 {
637                    brr += 1;
638                }
639                if c == self.cells.columns - 1 {
640                    brc += 1;
641                }
642            }
643        }
644
645        let (tlr, tlc) = if tlr > tlc {
646            (if tlr > 1 { 1 } else { 0 }, 0)
647        } else {
648            (0, if tlc > 1 { 1 } else { 0 })
649        };
650        let (brr, brc) = if brr > brc {
651            (if brr > 1 { self.cells.rows - 2 } else { self.cells.rows - 1 }, self.cells.columns - 1)
652        } else {
653            (self.cells.rows - 1, if brc > 1 { self.cells.columns - 2 } else { self.cells.columns - 1 })
654        };
655
656        let mut this = self.subshape_trim(tlr, brr + 1 - tlr, tlc, brc + 1 - tlc);
657
658        if n > 1 {
659            this = this.shrink_border_colour_n(bg, n - 1);
660        }
661
662        this
663    }
664
665    // TODO: complete for 3f23242b
666    pub fn shrink_left(&self, n: usize) -> Self {
667        let mut shape = Shape::new_sized_coloured_position(0, self.ocol, self.cells.rows - n, self.cells.columns, self.colour);
668
669        for r in n .. self.cells.rows {
670            for c in 0 .. self.cells.columns {
671                shape.cells[(r - n,c)].row = self.orow - n;
672                shape.cells[(r - n,c)].col = self.ocol;
673                shape.cells[(r - n,c)].colour = self.cells[(r,c)].colour;
674            }
675        }
676//self.show_summary();
677//shape.show_summary();
678
679        shape
680    }
681
682    pub fn on_edge(&self, grid: &Grid) -> bool {
683        let r = self.orow;
684        let c = self.ocol;
685        let rs = self.cells.rows - 1;
686        let cs = self.cells.columns - 1;
687        let rl = grid.cells.rows - 1;
688        let cl = grid.cells.columns - 1;
689
690        r == 0 || c == 0 || r + rs == rl || c + cs == cl
691    }
692
693    // extra check for border required
694    pub fn find_same_row(&self, others: &[Self]) -> Self {
695        for s in others.iter() {
696            if self.orow == s.orow && self.ocol < s.ocol {
697                return s.clone();
698            }
699        }
700
701        Self::trivial()
702    }
703
704    // extra check for border required
705    pub fn find_same_col(&self, others: &[Self]) -> Self {
706        for s in others.iter() {
707            if self.orow < s.orow && self.ocol == s.ocol {
708                return s.clone();
709            }
710        }
711
712        Self::trivial()
713    }
714
715    pub fn shrink(&self) -> Self {
716        self.shrink_any(false)
717    }
718
719    pub fn shrink_coloured(&self) -> Self {
720        self.shrink_any(true)
721    }
722
723    pub fn euclidian(&self, other: &Self) -> f64 {
724        let dr = (self.orow as isize - other.orow as isize).abs();
725        let dc = (self.ocol as isize - other.ocol as isize).abs();
726
727        ((dr * dr + dc * dc) as f64).sqrt()
728    }
729
730    pub fn manhattan(&self, other: &Self) -> usize {
731        let dr = (self.orow as isize - other.orow as isize).abs();
732        let dc = (self.ocol as isize - other.ocol as isize).abs();
733
734        (dr + dc) as usize
735    }
736
737    pub fn is_diagonal(&self, other: &Self) -> bool {
738        let dr = (self.orow as isize - other.orow as isize).abs();
739        let dc = (self.ocol as isize - other.ocol as isize).abs();
740
741        dr == dc
742    }
743
744    pub fn which_direction(&self, other: &Self) -> Direction {
745        let dr = (self.orow as isize - other.orow as isize).abs();
746        let dc = (self.ocol as isize - other.ocol as isize).abs();
747
748        if dr == 0 && dc > 0 {
749            return if self.orow < other.orow { Up } else { Down };
750        } else if dr > 0 && dc == 0 {
751            return if self.ocol < other.ocol { Left } else { Right };
752        } else if dr == dc {
753            return if self.orow < other.orow && self.ocol < other.ocol {
754                DownRight
755            } else if self.orow < other.orow && self.ocol > other.ocol {
756                DownLeft
757            } else if self.orow > other.orow && self.ocol < other.ocol {
758                UpRight
759            } else {
760                UpLeft
761            };
762        }
763
764        Other
765    }
766
767    /*
768    // Must have at least one other!
769    pub fn nearest(&self, other: &Shapes) -> Self {
770        let dself = self.euclidian();
771        let mut min: f64 = f64::MAX;
772        let mut pos: &Self = &other.shapes[0];
773
774        for s in &other.shapes {
775            //if self.orow > s.orow + 1 && self.ocol > s.ocol + 1 {
776                let dist = dself - s.euclidian();
777println!("{:?}", dist.abs());
778
779                if dist.abs() < min {
780                    min = dist;
781                    pos = s;
782                }
783            //}
784        }
785
786        pos.clone()
787    }
788
789    pub fn touching(&self, other: &Shape) -> bool {
790        let l_tlx = self.ox;
791        let l_lty = self.oy;
792        let l_brx = self.ox + self.cells.rows;
793        let l_bry = self.oy + self.cells.columns;
794        let r_tlx = other.ox;
795        let r_lty = other.oy;
796        let r_brx = other.ox + other.cells.rows;
797        let r_bry = other.oy + other.cells.columns;
798        // TODO complete
799
800        false
801    }
802    */
803
804    /* TODO
805    pub fn add_outer_layer(&self, colour: Colour, thickness: usize) -> Self {
806        //let mut m: Matrix<Cell> = self.cells.clone();
807        //Self::new(self.ox, self.oy, &m)
808
809        self.clone()
810    }
811
812    pub fn add_inner_layer(&self, colour: Colour, thickness: usize) -> Self {
813        self.clone()
814    }
815    */
816
817    pub fn is_pixel(&self) -> bool {
818        self.cells.rows == 1 && self.cells.columns == 1
819    }
820
821    pub fn fill_boundary_colour(&self) -> Self {
822        self.fill_boundary_colour_bg(Black)
823    }
824
825    pub fn fill_boundary_colour_bg(&self, bg: Colour) -> Self {
826        if self.colour == Mixed {
827            return self.clone();
828        }
829
830        let mut shape = self.clone();
831
832        for ((r, c), cell) in self.cells.items() {
833            if cell.colour == bg && (r == 0 || c == 0 || r == self.cells.rows - 1 || c == self.cells.columns - 1) {
834                shape.flood_fill_mut(r, c, NoColour, self.colour);
835            }
836        }
837
838        shape
839    }
840
841    /*
842    pub fn fill_boundary_colour_bg(&self, bg: Colour) -> Self {
843        if self.colour == Mixed {
844            return self.clone();
845        }
846
847        let m = Self::fill_boundary_colour_cells(&self.cells, bg);
848
849        Shape::new_cells(&m)
850    }
851
852    fn fill_boundary_colour_cells(cells: &Matrix<Cell>, bg: Colour) -> Matrix<Cell>{
853        let mut m = cells.clone();
854
855        for ((r, c), cell) in m.clone().items() {
856            if cell.colour == bg && (r == 0 || c == 0 || r == m.rows - 1 || c == m.columns - 1) {
857                let reachable = m.bfs_reachable((r, c), false, |i| m[i].colour == bg);
858
859                reachable.iter().for_each(|&i| m[i].colour = NoColour);
860            }
861        }
862
863        m
864    }
865    */
866
867    pub fn flood_fill_border_mut(&mut self, ignore_colour: Colour, new_colour: Colour) {
868        let rows = self.cells.rows;
869        let cols = self.cells.columns;
870
871        for r in 0 .. rows {
872            for c in 0 .. cols {
873                if (r == 0 || c == 0 || r == rows - 1 || c == cols - 1) && self.cells[(r, c)].colour == Black {
874                    self.flood_fill_mut(r, c, ignore_colour, new_colour);
875                }
876            }
877        }
878
879        let (colour, _) = Self::cell_colour_cnt_mixed(&self.cells, true, true);
880
881        self.colour = colour;
882    }
883
884    pub fn flood_fill(&self, r: usize, c: usize, ignore_colour: Colour, new_colour: Colour) -> Self {
885        let mut shape = self.clone();
886
887        shape.flood_fill_mut(r, c, ignore_colour, new_colour);
888
889        let (colour, _) = Self::cell_colour_cnt_mixed(&shape.cells, true, true);
890
891        shape.colour = colour;
892
893        shape
894    }
895
896    pub fn flood_fill_mut(&mut self, r: usize, c: usize, ignore_colour: Colour, new_colour: Colour) {
897        let reachable = self.cells.bfs_reachable((r, c), false, |i| self.cells[i].colour == Black || self.cells[i].colour == ignore_colour);
898
899        reachable.iter().for_each(|&i| self.cells[i].colour = new_colour);
900    }
901
902    pub fn sid(m: &Matrix<Cell>, coloured: bool) -> u32 {
903        let crc = Crc::<u32>::new(&crc::CRC_32_ISCSI);
904        let mut digest = crc.digest();
905
906        for ((r, c), cell) in m.items() {
907            let colour = if cell.colour == Black {
908                Black
909            } else if coloured {
910                cell.colour
911            } else {
912                Mixed 
913            };
914
915            digest.update(&r.to_ne_bytes());
916            digest.update(&c.to_ne_bytes());
917            digest.update(&Colour::to_usize(colour).to_ne_bytes());
918        }
919
920        digest.finalize()
921    }
922
923    pub fn contains_colour(&self, colour: Colour) -> bool {
924        if self.colour == colour {
925            return true;
926        }
927
928        for cell in self.cells.values() {
929            if cell.colour == colour {
930                return true;
931            }
932        }
933
934        false
935    }
936
937    pub fn has_bg_grid(&self) -> Colour {
938        self.to_grid().has_bg_grid()
939    }
940
941    pub fn has_bg_grid_coloured(&self) -> Colour {
942        self.to_grid().has_bg_grid()
943    }
944
945    pub fn has_bg_grid_not_sq(&self) -> Colour {
946        self.to_grid().has_bg_grid_not_sq()
947    }
948
949    pub fn has_bg_grid_coloured_not_sq(&self) -> Colour {
950        self.to_grid().has_bg_grid_not_sq()
951    }
952
953    pub fn gravity_down(&self) -> Self {
954        self.gravity_down_colour(Black)
955    }
956
957    pub fn gravity_down_colour(&self, colour: Colour) -> Self {
958        let mut values: Vec<Colour> = vec![colour; self.cells.columns];
959        let mut counts: Vec<usize> = vec![0; self.cells.columns];
960
961        for ((r, c), cell) in self.cells.items() {
962            if self.cells[(r,c)].colour != colour {
963                if values[c] == colour {
964                    values[c] = cell.colour;
965                }
966
967                counts[c] += 1;
968            }
969        }
970
971        let mut m = self.cells.clone();
972
973        for (r, c) in self.cells.keys() {
974            m[(r,c)].row = r + self.orow;
975            m[(r,c)].col = c + self.ocol;
976
977            if self.cells[(r,c)].colour == colour {
978               m[(r,c)].colour = values[c];
979            }
980            if self.cells.rows - r > counts[c] {
981               m[(r,c)].colour = colour;
982            }
983        }
984
985        Self::new_cells(&m)
986    }
987
988    pub fn gravity_up(&self) -> Self {
989        self.gravity_up_colour(Black)
990    }
991
992    pub fn gravity_up_colour(&self, colour: Colour) -> Self {
993        self.mirrored_r().gravity_down_colour(colour).mirrored_r()
994    }
995
996    pub fn gravity_right(&self) -> Self {
997        self.gravity_right_colour(Black)
998    }
999
1000    pub fn gravity_right_colour(&self, colour: Colour) -> Self {
1001        self.rot_rect_90().gravity_down_colour(colour).rot_rect_270()
1002    }
1003
1004    pub fn gravity_left(&self) -> Self {
1005        self.gravity_left_colour(Black)
1006    }
1007
1008    pub fn gravity_left_colour(&self, colour: Colour) -> Self {
1009        self.rot_rect_270().gravity_down_colour(colour).rot_rect_90()
1010    }
1011
1012    // Same footprint + colours
1013    pub fn equals(&self, other: &Self) -> Colour {
1014        if !self.equal_footprint(other) {
1015            return DiffShape;
1016        }
1017
1018        for (c1, c2) in self.cells.values().zip(other.cells.values()) {
1019            if c1.colour != c2.colour {
1020                return DiffBlack + c2.colour;
1021            }
1022        }
1023
1024        Same
1025    }
1026
1027    pub fn find_equals(&self, shapes: &Shapes) -> Shape {
1028        for s in shapes.shapes.iter() {
1029            if s.equals(self) == Same {
1030                return s.clone();
1031            }
1032        }
1033
1034        Shape::trivial()
1035    }
1036
1037    // Same position
1038    pub fn equal_position(&self, other: &Self) -> bool {
1039        self.orow == other.orow && self.ocol == other.ocol
1040    }
1041
1042    pub fn find_equal_position(&self, shapes: &Shapes) -> Shape {
1043        for s in shapes.shapes.iter() {
1044            if s.equal_position(self) {
1045                return s.clone();
1046            }
1047        }
1048
1049        Shape::trivial()
1050    }
1051
1052    // Same footprint
1053    pub fn equal_footprint(&self, other: &Self) -> bool {
1054        self.cells.columns == other.cells.columns && self.cells.rows == other.cells.rows
1055    }
1056
1057    pub fn find_equal_footprint(&self, shapes: &Shapes) -> Shape {
1058        for s in shapes.shapes.iter() {
1059            if s.equal_footprint(self) {
1060                return s.clone();
1061            }
1062        }
1063
1064        Shape::trivial()
1065    }
1066
1067    // Same shape
1068    pub fn equal_shape(&self, other: &Self) -> bool {
1069        if !self.equal_footprint(other) {
1070            return false;
1071        }
1072
1073        for (((sr, sc), c1), ((or, oc), c2)) in self.cells.items().zip(other.cells.items()) {
1074            if sr != or || sc != oc || (c1.colour == Black && c2.colour != Black) || (c1.colour != Black && c2.colour == Black) {
1075                return false;
1076            }
1077        }
1078
1079        true
1080    }
1081
1082    pub fn find_equal_shape(&self, shapes: &Shapes) -> Shape {
1083        for s in shapes.shapes.iter() {
1084            if s.equal_shape(self) {
1085                return s.clone();
1086            }
1087        }
1088
1089        Shape::trivial()
1090    }
1091
1092    pub fn show_summary(&self) {
1093        println!("{}/{}: {}/{} {:?}", self.orow, self.ocol, self.cells.rows, self.cells.columns, self.colour);
1094    }
1095
1096    fn show_any(&self, diff: bool, io: bool) {
1097        println!("--------Shape-------");
1098        Grid::show_matrix(&self.cells, diff, io);
1099        println!();
1100    }
1101
1102    pub fn show(&self) {
1103        self.show_any(true, false);
1104    }
1105
1106    pub fn show_full(&self) {
1107        self.show_any(false, true);
1108    }
1109
1110    pub fn show_out(&self) {
1111        self.show_any(false, false);
1112    }
1113
1114    pub fn show_io(&self) {
1115        self.show_any(true, true);
1116    }
1117
1118    pub fn is_empty(&self) -> bool {
1119        for c in self.cells.values() {
1120            if c.colour != Black {
1121                return false
1122            }
1123        }
1124
1125        true
1126    }
1127
1128    pub fn subshape_remain(&self, tlr: usize, sr: usize, tlc: usize, sc: usize) -> Self {
1129        let mut s = self.subshape(tlr, sr, tlc, sc);
1130
1131        s.orow = self.orow + tlr;
1132        s.ocol = self.ocol + tlc;
1133
1134        for r in 0 .. s.cells.rows {
1135            for c in 0 .. s.cells.columns {
1136                s.cells[(r,c)].row = s.orow + r;
1137                s.cells[(r,c)].col = s.ocol + c;
1138            }
1139        }
1140
1141        s
1142    }
1143
1144    pub fn subshape(&self, tlr: usize, sr: usize, tlc: usize, sc: usize) -> Self {
1145        if sr == 0 || sc == 0 {
1146            return Self::trivial();
1147        }
1148
1149        let mut m = Matrix::new(sr, sc, Cell::new(0, 0, 0));
1150
1151        for r in 0 ..  sr {
1152            for c in 0 .. sc {
1153                m[(r,c)].row = self.cells[(r + tlr,c + tlc)].row;
1154                m[(r,c)].col = self.cells[(r + tlr,c + tlc)].col;
1155                m[(r,c)].colour = self.cells[(r + tlr,c + tlc)].colour;
1156            }
1157        }
1158
1159        Self::new_cells(&m)
1160    }
1161
1162    pub fn subshape_trim(&self, tlr: usize, sr: usize, tlc: usize, sc: usize) -> Self {
1163        let sr = if tlr + sr > self.cells.rows {
1164            self.cells.rows - tlr
1165        } else {
1166            sr
1167        };
1168        let sc = if tlc + sc > self.cells.columns {
1169            self.cells.columns - tlc
1170        } else {
1171            sc
1172        };
1173
1174        self.to_grid().subgrid(tlr, sr, tlc, sc).as_shape()
1175    }
1176
1177    pub fn id(&self) -> String {
1178        format!("{}/{}", self.orow, self.ocol)
1179    }
1180
1181    pub fn above(&self, other: &Self) -> bool {
1182        let (sr, _) = self.centre_of_exact();
1183        let (or, _) = other.centre_of_exact();
1184        
1185        sr > or
1186    }
1187
1188    pub fn below(&self, other: &Self) -> bool {
1189        let (sr, _) = self.centre_of_exact();
1190        let (or, _) = other.centre_of_exact();
1191        
1192        sr < or
1193    }
1194
1195    pub fn right(&self, other: &Self) -> bool {
1196        let (_, sc) = self.centre_of_exact();
1197        let (_, oc) = other.centre_of_exact();
1198        
1199        sc < oc
1200    }
1201
1202    pub fn left(&self, other: &Self) -> bool {
1203        let (_, sc) = self.centre_of_exact();
1204        let (_, oc) = other.centre_of_exact();
1205        
1206        sc > oc
1207    }
1208
1209    pub fn diag(&self, other: &Self) -> bool {
1210        let (sr, sc) = self.centre_of();
1211        let (or, oc) = other.centre_of();
1212        
1213        let dr = if sr > or { sr - or } else { or - sr };
1214        let dc = if sc > oc { sc - oc } else { oc - sc };
1215
1216        dr == dc
1217    }
1218
1219    pub fn orientation_horizontal(&self) -> Option<bool> {
1220        let width = self.width();
1221        let height = self.height();
1222
1223        if width == 1 && height > 1 {
1224            Some(true)
1225        } else if width > 1 && height == 1 {
1226            Some(false)
1227        } else {
1228            None
1229        }
1230    }
1231
1232    pub fn size(&self) -> usize {
1233        self.cells.columns * self.cells.rows
1234    }
1235
1236    pub fn width(&self) -> usize {
1237        self.cells.columns
1238    }
1239
1240    pub fn height(&self) -> usize {
1241        self.cells.rows
1242    }
1243
1244    pub fn origin(&self) -> (usize, usize) {
1245        (self.orow, self.ocol)
1246    }
1247
1248    pub fn pixels(&self) -> usize {
1249        self.cells.values()
1250            .filter(|c| c.colour != Black)
1251            .count()
1252    }
1253
1254    pub fn same_size(&self, other: &Self) -> bool {
1255        self.size() == other.size()
1256    }
1257
1258    pub fn same_shape(&self, other: &Self) -> bool {
1259        self.cells.columns == other.cells.columns && self.cells.rows == other.cells.rows
1260    }
1261
1262    pub fn same_pixel_positions(&self, other: &Self, same_colour: bool) -> bool {
1263        if !self.same_shape(other) {
1264            return false;
1265        }
1266
1267        for (c1, c2) in self.cells.values().zip(other.cells.values()) {
1268            if c1.colour == Black && c2.colour != Black || c1.colour != Black && c2.colour == Black || (same_colour && c1.colour != c2.colour) {
1269                return false;
1270            }
1271        }
1272
1273        true
1274    }
1275
1276    pub fn dimensions(&self) -> (usize, usize) {
1277        (self.cells.rows, self.cells.columns)
1278    }
1279
1280    pub fn density(&self) -> f32 {
1281        self.size() as f32 / self.cells.len() as f32
1282    }
1283
1284    pub fn distinct_colour_cnt(&self) -> usize {
1285        let mut s: BTreeSet<Colour> = BTreeSet::new();
1286
1287        for c in self.cells.values() {
1288            if c.colour != Black {
1289                s.insert(c.colour);
1290            }
1291        }
1292
1293        s.len()
1294    }
1295
1296    pub fn find_layers(&self) -> (usize, Colour, Vec<Direction>) {
1297        let rows = self.cells.rows;
1298        let cols = self.cells.columns;
1299        let mut depth = 0;
1300        let mut colour = NoColour;
1301        let mut dirs: Vec<Direction> = Vec::new();
1302
1303        for ((r, c), cell) in self.cells.items() {
1304            if cell.colour != Black {
1305                if colour == NoColour {
1306                    colour = cell.colour;
1307                } else if colour != NoColour && cell.colour != colour {
1308                    break;
1309                }
1310            }
1311
1312            let mut ldepth = 0;
1313
1314            if r == 0 && c == cols / 2 {
1315                for rr in 0 .. rows {
1316                    if self.cells[(rr,c)].colour == colour {
1317                        ldepth += 1;
1318                        if !dirs.contains(&Up) { dirs.push(Up); }
1319                    } else {
1320                        break;
1321                    }
1322                }
1323            } else if r == rows - 1 && c == cols / 2 {
1324                for rr in (0 .. rows).rev() {
1325                    if self.cells[(rr,c)].colour == colour {
1326                        ldepth += 1;
1327                        if !dirs.contains(&Down) { dirs.push(Down); }
1328                    } else {
1329                        break;
1330                    }
1331                }
1332            } else if c == 0 && r == rows / 2 {
1333                for cc in 0 .. cols {
1334                    if self.cells[(r,cc)].colour == colour {
1335                        ldepth += 1;
1336                        if !dirs.contains(&Left) { dirs.push(Left); }
1337                    } else {
1338                        break;
1339                    }
1340                }
1341            } else if c == cols - 1 && r == rows / 2 {
1342                for cc in (0 .. cols).rev() {
1343                    if self.cells[(r,cc)].colour == colour {
1344                        ldepth += 1;
1345                        if !dirs.contains(&Right) { dirs.push(Right); }
1346                    } else {
1347                        break;
1348                    }
1349                }
1350            }
1351
1352            if ldepth > 0 {
1353                if depth == 0 && ldepth > 0 {
1354                    depth = ldepth;
1355                } else if ldepth != depth {
1356                    depth = 0;
1357                    dirs = Vec::new();
1358                    break;
1359                }
1360            }
1361        }
1362
1363        (depth, colour, dirs)
1364    }
1365
1366    // see 40f6cd08.todo
1367    pub fn paint_layers_mut(&mut self, indent: usize, depth: usize, colour: Colour, dirs: Vec<Direction>) {
1368        let rows = self.cells.rows;
1369        let cols = self.cells.columns;
1370        //let bg = self.colour;
1371        let bg = Black;
1372
1373        for dir in dirs.iter() {
1374            match dir {
1375                Up => {
1376                    for r in indent .. indent + depth {
1377                        for c in indent .. cols {
1378                            if self.cells[(r, c)].colour == bg {
1379                                self.cells[(r, c)].colour = colour;
1380                            } else {
1381                                break;
1382                            }
1383                        }
1384                    }
1385                },
1386                Down => {
1387                    for r in rows - indent - depth .. rows - indent {
1388                        for c in indent .. cols {
1389                            if self.cells[(r, c)].colour == bg {
1390                                self.cells[(r, c)].colour = colour;
1391                            } else {
1392                                break;
1393                            }
1394                        }
1395                    }
1396                },
1397                Left => {
1398                    for r in indent .. rows  {
1399                        for c in indent .. indent + depth {
1400                            if self.cells[(r, c)].colour == bg {
1401                                self.cells[(r, c)].colour = colour;
1402                            } else {
1403                                break;
1404                            }
1405                        }
1406                    }
1407                },
1408                Right => {
1409println!("--- {} {}", indent, depth);
1410                    for r in indent .. rows {
1411                        //for c in 0 .. cols - indent {
1412                        for c in cols - indent - depth .. cols - indent {
1413                        //for c in indent + depth .. cols {
1414                        //for c in (0 .. cols  - indent - depth).rev() {
1415                        //for c in (indent + depth .. cols).rev() {
1416                        //for c in 0 .. cols - indent - depth {
1417                            if self.cells[(r, c)].colour == bg {
1418                                self.cells[(r, c)].colour = colour;
1419                            } else {
1420                                break;
1421                            }
1422                        }
1423                    }
1424                },
1425                _ => todo!()
1426            }
1427        }
1428//self.show();
1429    }
1430
1431    pub fn cell_colours(&self) -> Vec<Colour>  {
1432        self.cell_colour_cnt_map().keys().map(|c| *c).collect()
1433    }
1434
1435    pub fn cell_colour_cnt_map(&self) -> BTreeMap<Colour, usize>  {
1436        let mut h: BTreeMap<Colour, usize> = BTreeMap::new();
1437
1438        for c in self.cells.values() {
1439            if c.colour != Black {
1440                *h.entry(c.colour).or_insert(0) += 1;
1441            }
1442        }
1443
1444        h
1445    }
1446
1447    pub fn cell_colour_cnt(cells: &Matrix<Cell>, max: bool) -> (Colour, usize) {
1448        Self::cell_colour_cnt_mixed(cells, max, false)
1449    }
1450
1451    pub fn cell_colour_cnt_mixed(cells: &Matrix<Cell>, max: bool, mixed: bool) -> (Colour, usize) {
1452        let mut h: HashMap<usize, usize> = HashMap::new();
1453
1454        for c in cells.values() {
1455            if c.colour != Black {
1456                *h.entry(Colour::to_usize(c.colour)).or_insert(0) += 1;
1457            }
1458        }
1459
1460        if mixed && h.len() > 1 {
1461            return (Mixed, 0);
1462        }
1463
1464        let mm = if max {
1465            h.iter().max_by(|col, c| col.1.cmp(c.1))
1466        } else {
1467            h.iter().min_by(|col, c| col.1.cmp(c.1))
1468        };
1469        let pair: Option<(Colour, usize)> = mm
1470            .map(|(col, cnt)| (Colour::from_usize(*col), *cnt));
1471
1472        match pair {
1473            None => (Black, 0),
1474            Some((colour, cnt)) => (colour, cnt)
1475        }
1476    }
1477
1478    pub fn colour_cnt(&self, max: bool) -> (Colour, usize) {
1479        Self::cell_colour_cnt(&self.cells, max)
1480    }
1481
1482    pub fn majority_colour(&self) -> Colour {
1483        let cc = self.colour_cnt(true);
1484
1485        cc.0
1486    }
1487
1488    pub fn minority_colour(&self) -> Colour {
1489        let cc = self.colour_cnt(false);
1490
1491        cc.0
1492    }
1493    
1494    pub fn colour_position(&self, colour: Colour) -> Vec<(usize, usize)> {
1495        let mut ans: Vec<(usize, usize)> = Vec::new();
1496
1497        for ((r, c), cell) in self.cells.items() {
1498            if cell.colour == colour {
1499                ans.push((r, c));
1500            }
1501        }
1502
1503        ans
1504    }
1505
1506    /*
1507    pub fn make_square(&self) -> Self {
1508        // Figure must also be a square
1509        let brr_tlr = brr - tlr;
1510        let brc_tlc = brc - tlc;
1511        let mut tb = true;  // top/bottom equal extent?
1512        if brr_tlr > brc_tlc {
1513            let tl = tlr.min(tlc);
1514
1515            if tl == tlr {
1516                tlc = tl;
1517            } else {
1518                tlr = tl;
1519            }
1520        } else if brr_tlr < brc_tlc {
1521            let br = brr.max(tlc);
1522
1523            if br == brr {
1524                brc = br;
1525            } else {
1526                brr = br;
1527            }
1528        }
1529    }
1530    */
1531
1532    pub fn origin_centre(&self) -> (usize, usize, usize, usize) { 
1533        let (tlr, tlc, _, _) = self.corners();
1534        let side = self.cells.rows.max(self.cells.columns);
1535
1536        (tlr.min(tlc), tlr.min(tlc), side, if side % 2 == 1 { 1 } else { 4 })
1537    }
1538
1539    pub fn is_larger(&self, other: &Self) -> bool {
1540        self.size() >= other.size()
1541    }
1542
1543    pub fn is_smaller(&self, other: &Self) -> bool {
1544        self.size() <= other.size()
1545    }
1546
1547    pub fn larger(&self, other: &Self) -> Self {
1548        if self.size() >= other.size() {
1549            self.clone()
1550        } else {
1551            other.clone()
1552        }
1553    }
1554
1555    pub fn smaller(&self, other: &Self) -> Self {
1556        if self.size() <= other.size() {
1557            self.clone()
1558        } else {
1559            other.clone()
1560        }
1561    }
1562
1563    pub fn to_square(&self) -> Self {
1564        let (or, oc, side, _) = self.origin_centre();
1565        let shape = Self::new_sized_coloured_position(or, oc, side, side, Black);
1566
1567        Shapes::new_shapes(&[shape, self.clone()]).to_shape()
1568    }
1569
1570    pub fn to_square_grid(&self) -> Grid {
1571        let (or, oc, side, _) = self.origin_centre();
1572        let shape = Self::new_sized_coloured_position(or, oc, side, side, Black);
1573
1574        Shapes::new_shapes(&[shape, self.clone()]).to_grid()
1575    }
1576
1577    /* not necessary
1578    // must be square and assme 3 out of four shapes + centre already
1579    pub fn symmetric_slice(&self) -> (Self, Self) {
1580        let mut shape = self.clone();
1581        let mut centre = self.clone();
1582        let mut arm = self.clone();
1583
1584        let (mut tlr, mut tlc, mut brr, mut brc) = shape.corners();
1585shape.show();
1586
1587        // Rotate to minimise origin
1588        for i in 1 .. 4 {
1589            let rs = shape.rot_90(i);
1590rs.show();
1591            let (a, b, c, d) = rs.corners();
1592
1593            if a < tlr || b < tlc || c < brr || d < brc {
1594                tlr = a;
1595                tlc = b;
1596                brr = c;
1597                brc = d;
1598
1599                shape = rs;
1600            }
1601        }
1602println!("-- {tlr}, {tlc}, {brr}, {brc}");
1603
1604        let (mut tlr, mut tlc, mut brr, mut brc) = shape.corners();
1605
1606println!(">> {tlr}, {tlc}, {brr}, {brc}");
1607        // Figure must also be a square
1608        let brr_tlr = brr - tlr;
1609        let brc_tlc = brc - tlc;
1610        let mut tb = true;  // top/bottom equal extent?
1611        if brr_tlr > brc_tlc {
1612            let tl = tlr.min(tlc);
1613
1614            if tl == tlr {
1615                tlc = tl;
1616            } else {
1617                tlr = tl;
1618            }
1619        } else if brr_tlr < brc_tlc {
1620            let br = brr.max(tlc);
1621
1622            if br == brr {
1623                brc = br;
1624            } else {
1625                brr = br;
1626            }
1627        }
1628
1629        // if square side is odd then centre is pixel else size 4
1630        let side = brr_tlr.max(brc_tlc) + 1;
1631
1632        if side % 2 == 1 {
1633            let r = side / 2;
1634            let c = side / 2;
1635
1636            centre = self.subshape(r - tlr, 1, c - tlc, 1);
1637        } else {
1638            let r = side / 2 - 1;
1639            let c = side / 2 - 1;
1640
1641            centre = self.subshape(r - tlr, 2, c - tlc, 2);
1642        }
1643println!("<< {tlr}, {tlc}, {brr}, {brc} : {side}");
1644
1645        (centre, arm)
1646    }
1647    */
1648
1649    /*
1650    pub fn distance_x(&self, other: &Self) -> f32 {
1651        let tl_dist = self.orow.max(other.orow) - other.orow.min(self.orow);
1652        let br_dist = self.cells.columns.max(other.cells.columns) - other.cells.columns.min(self.cells.columns);
1653
1654        ((tl_dist * tl_dist + br_dist * br_dist) as f32).sqrt() / 2.0
1655    }
1656
1657    pub fn distance_y(&self, other: &Self) -> f32 {
1658        let tl_dist = self.ocol.max(other.ocol) - other.ocol.min(self.ocol);
1659        let br_dist = self.cells.rows.max(other.cells.rows) - other.cells.rows.min(self.cells.rows);
1660
1661        ((tl_dist * tl_dist + br_dist * br_dist) as f32).sqrt() / 2.0
1662    }
1663    */
1664
1665    pub fn distance(&self, other: &Self) -> f32 {
1666        let (sr, sc) = self.centre_of_exact();
1667        let (or, oc) = other.centre_of_exact();
1668        let dor = sr - or;
1669        let doc = sc - oc;
1670
1671        (dor * dor + doc * doc).sqrt()
1672    }
1673
1674    pub fn distance_from(&self, row: usize, col: usize) -> f32 {
1675        let (sr, sc) = self.centre_of_exact();
1676        let dor = sr - row as f32;
1677        let doc = sc - col as f32;
1678
1679        (dor * dor + doc * doc).sqrt()
1680    }
1681
1682    fn is_mirrored(&self, other: &Self, lr: bool) -> bool {
1683        if self.width() != other.width() || self.height() != other.height() {
1684            return false;
1685        }
1686
1687        let mut flip: Matrix<Cell> = self.cells.clone();
1688
1689        if lr {
1690            flip.flip_lr();
1691        } else {
1692            flip.flip_ud();
1693        }
1694
1695        for (c1, c2) in flip.values().zip(other.cells.values()) {
1696            if c1.colour != c2.colour {
1697                return false;
1698            }
1699        }
1700
1701        true
1702    }
1703
1704    pub fn is_mirrored_r(&self, other: &Self) -> bool {
1705        self.is_mirrored(other, false)
1706    }
1707
1708    pub fn is_mirrored_c(&self, other: &Self) -> bool {
1709        self.is_mirrored(other, true)
1710    }
1711
1712    pub fn is_mirror_r(&self) -> bool {
1713        if self.cells.rows == 1 {
1714            return false;
1715        }
1716        let inc = if self.cells.rows % 2 == 0 { 0 } else { 1 };
1717        let s1 = self.subshape(0, self.cells.rows / 2, 0, self.cells.columns);
1718        let s2 = self.subshape(self.cells.rows / 2 + inc, self.cells.rows / 2, 0, self.cells.columns);
1719
1720        s1.is_mirrored_r(&s2)
1721    }
1722
1723    pub fn is_mirror_c(&self) -> bool {
1724        if self.cells.columns == 1 {
1725            return false;
1726        }
1727        let inc = if self.cells.columns % 2 == 0 { 0 } else { 1 };
1728        let s1 = self.subshape(0, self.cells.rows, 0, self.cells.columns / 2);
1729        let s2 = self.subshape(0, self.cells.rows, self.cells.columns / 2 + inc, self.cells.columns / 2);
1730
1731        s1.is_mirrored_c(&s2)
1732    }
1733
1734    fn mirrored(&self, lr: bool) -> Self {
1735        let mut m: Matrix<Cell> = self.cells.clone();
1736
1737        if lr {
1738            m.flip_lr();
1739        } else {
1740            m.flip_ud();
1741        }
1742
1743        for (r, c) in self.cells.keys() {
1744            m[(r, c)].row = r + self.orow;
1745            m[(r, c)].col = c + self.ocol;
1746        }
1747        
1748        Self::new(self.orow, self.ocol, &m)
1749    }
1750
1751    pub fn mirrored_r(&self) -> Self {
1752        self.mirrored(false)
1753    }
1754
1755    pub fn mirrored_c(&self) -> Self {
1756        self.mirrored(true)
1757    }
1758
1759    pub fn transposed(&self) -> Self {
1760        let mut m: Matrix<Cell> = self.cells.clone();
1761
1762        m.transpose();
1763
1764        for (r, c) in self.cells.keys() {
1765            m[(r, c)].row = r + self.orow;
1766            m[(r, c)].col = c + self.ocol;
1767        }
1768        
1769        Self::new(self.orow, self.ocol, &m)
1770    }
1771
1772    pub fn is_transposed(&self, other: &Self) -> bool {
1773        if self.width() != other.width() || self.height() != other.height() {
1774            return false;
1775        }
1776
1777        let mut flip: Matrix<Cell> = self.cells.clone();
1778
1779        flip.transpose();
1780
1781        for (c1, c2) in flip.values().zip(other.cells.values()) {
1782            if c1 != c2 {
1783                return false;
1784            }
1785        }
1786
1787        true
1788    }
1789
1790    fn rot_90(&self, n: usize) -> Self {
1791        if !self.is_square() {
1792            return self.clone();
1793        }
1794        let mut m = if n < 3 {
1795            self.cells.rotated_cw(n)
1796        } else {
1797            self.cells.rotated_ccw(1)
1798        };
1799
1800        for (r, c) in self.cells.keys() {
1801            m[(r, c)].row = r + self.orow;
1802            m[(r, c)].col = c + self.ocol;
1803        }
1804
1805        Self::new(self.orow, self.ocol, &m)
1806    }
1807
1808    pub fn rotated_90(&self) -> Self {
1809        self.rot_90(1)
1810    }
1811
1812    pub fn rotated_180(&self) -> Self {
1813        self.rot_90(2)
1814    }
1815
1816    pub fn rotated_270(&self) -> Self {
1817        self.rot_90(3)
1818    }
1819
1820    pub fn rot_rect_90(&self) -> Self {
1821        if self.cells.rows == self.cells.columns {
1822            self.rotated_90()
1823        } else {
1824            let mut rot = Self::new_sized_coloured_position(self.orow, self.ocol, self.cells.columns, self.cells.rows, self.colour);
1825            let n = self.cells.rows;
1826            
1827            for ((r, c), cell) in self.cells.items() {
1828                //rot.cells[(c, n - r - 1)].row = r;
1829                //rot.cells[(c, n - r - 1)].col = c;
1830                rot.cells[(c, n - r - 1)].colour = cell.colour;
1831            }
1832
1833            rot
1834        }
1835    }
1836
1837    pub fn rot_rect_180(&self) -> Self {
1838        if self.cells.rows == self.cells.columns {
1839            self.rotated_90().rotated_90()
1840        } else {
1841            self.rot_rect_90().rot_rect_90()
1842        }
1843    }
1844
1845    pub fn rot_rect_270(&self) -> Self {
1846        if self.cells.rows == self.cells.columns {
1847            self.rotated_270()
1848        } else {
1849            self.rot_rect_90().rot_rect_90().rot_rect_90()
1850        }
1851    }
1852
1853    pub fn extend_line(&self) -> Self {
1854        if self.height() > 1 && self.width() > 1 {
1855            return self.clone();
1856        }
1857
1858        if self.height() == 1 {
1859            self.extend_right(1)
1860        } else {
1861            self.extend_bottom(1)
1862        }
1863    }
1864
1865    pub fn is_rotated_90(&self, other: &Self) -> bool {
1866        let rot = self.cells.rotated_cw(1);
1867
1868        for (c1, c2) in rot.values().zip(other.cells.values()) {
1869            if c1 != c2 {
1870                return false;
1871            }
1872        }
1873
1874        true
1875    }
1876
1877    pub fn is_rotated_180(&self, other: &Self) -> bool {
1878        let rot = self.cells.rotated_cw(2);
1879
1880        for (c1, c2) in rot.values().zip(other.cells.values()) {
1881            if c1 != c2 {
1882                return false;
1883            }
1884        }
1885
1886        true
1887    }
1888
1889    pub fn is_rotated_270(&self, other: &Self) -> bool {
1890        let rot = self.cells.rotated_ccw(2);
1891
1892        for (c1, c2) in rot.values().zip(other.cells.values()) {
1893            if c1 != c2 {
1894                return false;
1895            }
1896        }
1897
1898        true
1899    }
1900
1901    pub fn rotate_90_pos(&self, times: usize, or: usize, oc: usize) -> Self {
1902        let mut shape = self.to_grid().rotate_90(times).as_shape();
1903
1904        shape.orow = or;
1905        shape.ocol = oc;
1906
1907        for (r, c) in shape.clone().cells.keys() {
1908            shape.cells[(r,c)].row = or + r;
1909            shape.cells[(r,c)].col = oc + c;
1910        }
1911
1912        shape
1913    }
1914
1915    /*
1916    pub fn transposed(&self) -> Self {
1917        Self::new_cells(&self.cells.transposed())
1918    }
1919    */
1920
1921    pub fn to_grid(&self) -> Grid {
1922        Grid::new_from_matrix(&self.cells)
1923    }
1924
1925    pub fn to_json(&self) -> String {
1926        let mut grid: Vec<Vec<usize>> = vec![vec![0; self.cells.columns]; self.cells.rows];
1927
1928        for r in 0 .. self.cells.rows {
1929            for c in 0 .. self.cells.columns {
1930                let colour: usize = self.cells[(r, c)].colour.to_usize();
1931
1932                grid[r][c] = colour;
1933            }
1934        }
1935
1936        serde_json::to_string(&grid).unwrap()
1937    }
1938
1939    pub fn cell_count(&self) -> usize {
1940        self.cell_count_colour(Black)
1941    }
1942
1943    pub fn cell_count_colour(&self, colour: Colour) -> usize {
1944        self.cells.values().filter(|c| c.colour != colour).count()
1945    }
1946
1947    pub fn corner_idx(&self) -> (Self, Direction) {
1948        let (grid, dir) = self.to_grid().corner_idx();
1949
1950        (grid.as_shape(), dir)
1951    }
1952
1953    pub fn corner_body(&self, dir: Direction) -> Self {
1954        self.to_grid().corner_body(dir).as_shape()
1955    }
1956
1957    pub fn split_4(&self) -> Vec<Self> {
1958        self.to_grid().split_4().iter().map(|s| s.as_shape()).collect()
1959    }
1960
1961    pub fn diff(&self, other: &Self) -> Option<Self> {
1962        self.diff_impl(other, true)
1963    }
1964
1965    pub fn diff_orig(&self, other: &Self) -> Option<Self> {
1966        self.diff_impl(other, false)
1967    }
1968
1969    pub fn diff_impl(&self, other: &Self, diff: bool) -> Option<Self> {
1970        let grid = self.to_grid().diff_impl(&other.to_grid(), diff);
1971
1972        grid.map(|diff| diff.as_shape())
1973    }
1974
1975    pub fn diff_only_transparent(&self) -> Self {
1976        let mut s = self.clone();
1977
1978        for c in s.cells.values_mut() {
1979            if c.colour != Black {
1980                c.colour = Colour::to_base(c.colour);
1981            }
1982        }
1983
1984        s
1985    }
1986
1987    pub fn recolour(&self, from: Colour, to: Colour) -> Self {
1988        let mut shape = self.clone();
1989
1990        for c in shape.cells.values_mut() {
1991            if c.colour == from || from == NoColour {
1992                c.colour = to;
1993            }
1994        }
1995
1996        let (colour, _) = Self::cell_colour_cnt_mixed(&shape.cells, true, true);
1997
1998        shape.colour = colour;
1999
2000        shape
2001    }
2002
2003    pub fn recolour_mut(&mut self, from: Colour, to: Colour) {
2004        self.colour = to;
2005
2006        for c in self.cells.values_mut() {
2007            if c.colour == from || from == NoColour {
2008                c.colour = to;
2009            }
2010        }
2011
2012        let (colour, _) = Self::cell_colour_cnt_mixed(&self.cells, true, true);
2013
2014        self.colour = colour;
2015    }
2016
2017    pub fn force_recolour(&self, to: Colour) -> Self {
2018        let mut shape = self.clone();
2019
2020        shape.colour = to;
2021
2022        for c in shape.cells.values_mut() {
2023            c.colour = to;
2024        }
2025
2026        shape
2027    }
2028
2029    pub fn force_recolour_mut(&mut self, to: Colour) {
2030        self.colour = to;
2031
2032        for c in self.cells.values_mut() {
2033            c.colour = to;
2034        }
2035    }
2036
2037    pub fn uncolour(&self) -> Self {
2038        let mut shape = self.clone();
2039
2040        for c in shape.cells.values_mut() {
2041            c.colour = c.colour.to_base();
2042        }
2043
2044        shape
2045    }
2046
2047    pub fn uncolour_mut(&mut self) {
2048        for c in self.cells.values_mut() {
2049            c.colour = c.colour.to_base();
2050        }
2051    }
2052
2053    pub fn is_line(&self) -> bool {
2054        self.cells.rows == 1 && self.cells.columns > 0 || self.cells.rows > 1 && self.cells.columns == 1 
2055    }
2056
2057    pub fn is_horizontal_line(&self) -> bool {
2058        self.cells.columns > 1 && self.cells.rows == 1 
2059    }
2060
2061    pub fn is_vertical_line(&self) -> bool {
2062       self.cells.rows > 1 && self.cells.columns == 1 
2063    }
2064
2065    pub fn is_square(&self) -> bool {
2066        self.cells.rows == self.cells.columns
2067    }
2068
2069    pub fn has_band(&self, rs: usize, cs: usize) -> (Direction, usize) {
2070        if self.colour == Mixed {
2071            return (Other, 0);
2072        }
2073        if self.cells.rows == 1 && self.cells.columns == cs {
2074            (Down, self.orow)
2075        } else if self.cells.rows == rs && self.cells.columns == 1 {
2076            (Right, self.ocol)
2077        } else {
2078            (Other, 0)
2079        }
2080    }
2081
2082    pub fn make_square(&self) -> Self {
2083        let sz = self.cells.rows.max(self.cells.columns);
2084        let mut cells = Matrix::new(sz, sz, Cell::new(0, 0, 0));
2085
2086        for (i, cell) in self.cells.items() {
2087            cells[i].colour = cell.colour;
2088        }
2089        for (r, c) in cells.keys() {
2090            cells[(r,c)].row = self.orow + r;
2091            cells[(r,c)].col = self.ocol + c;
2092        }
2093
2094        Self::new(self.orow, self.ocol, &cells)
2095    }
2096
2097    pub fn mut_recolour(&mut self, from: Colour, to: Colour) {
2098        self.colour = to;
2099
2100        for c in self.cells.values_mut() {
2101            if c.colour == from || from == NoColour {
2102                c.colour = to;
2103            }
2104        }
2105    }
2106
2107    pub fn mut_force_recolour(&mut self, to: Colour) {
2108        self.colour = to;
2109
2110        for c in self.cells.values_mut() {
2111            c.colour = to;
2112        }
2113    }
2114
2115    pub fn fill_missing(&self, to: Colour) -> Self {
2116        let mut shape = self.clone();
2117
2118        for (r, c) in self.cells.keys() {
2119            if self.cells[(r, c)].colour == Black {
2120                shape.cells[(r, c)].colour = to;
2121            }
2122        }
2123
2124        shape
2125    }
2126
2127    pub fn scale_up(&self, factor: usize) -> Self {
2128        let mut cells = Matrix::new(self.cells.rows * factor, self.cells.columns * factor, Cell::new(0, 0, 0));
2129
2130        for r in 0 .. cells.rows {
2131            for c in 0 .. cells.columns {
2132                let rf = r / factor;
2133                let cf = c / factor;
2134
2135                cells[(r, c)].row = r;
2136                cells[(r, c)].col = c;
2137                cells[(r, c)].colour = self.cells[(rf, cf)].colour;
2138            }
2139        }
2140
2141        Self::new(0, 0, &cells)
2142    }
2143
2144    pub fn scale_down(&self, factor: usize) -> Self {
2145        let mut cells = Matrix::new(self.cells.rows / factor, self.cells.columns / factor, Cell::new(0, 0, 0));
2146
2147        for r in 0 .. cells.rows {
2148            for c in 0 .. cells.columns {
2149                let rf = r * factor;
2150                let cf = c * factor;
2151
2152                cells[(r, c)].row = r;
2153                cells[(r, c)].col = c;
2154                cells[(r, c)].colour = self.cells[(rf, cf)].colour;
2155            }
2156        }
2157
2158        Self::new(0, 0, &cells)
2159    }
2160
2161    /*
2162    pub fn scale_up_divider(&self, factor: usize, border: bool, divider: Colour) -> Shape {
2163        let resize = divider != NoColour;
2164        let size = if resize { factor + 1 } else { factor };
2165        let div = if !resize { 0 } else { factor - 1 };
2166        let mut cells = Matrix::new(self.cells.rows * factor + div, self.cells.columns * factor + div, Cell::new(0, 0, 0));
2167
2168        let mut dx = 0;
2169        let mut dy = 0;
2170
2171        for y in 0 .. cells.columns {
2172            if resize {
2173                dy = y % size;
2174            }
2175
2176            for x in 0 .. cells.rows {
2177                if resize {
2178                    dx = x % size;
2179                }
2180
2181                if x != 0 && y != 0 && resize && (x % size == 0 || y % size == 0) {
2182                } else {
2183                    let xf = (x + dx) % factor;
2184                    let yf = (y + dy) % factor;
2185println!("{x}/{y} {}/{} {} {}/{}", xf, yf, factor, dx, dy);
2186
2187                    cells[(x + dx, y + dy)].x = x;
2188                    cells[(x + dx, y + dy)].y = y;
2189                    cells[(x + dx, y + dy)].colour = self.cells[(xf, yf)].colour;
2190                }
2191            }
2192        }
2193
2194        Shape::new(0, 0, &cells)
2195    }
2196
2197    pub fn scale_up_divider(&self, factor: usize, border: bool, divider: Colour) -> Shape {
2198        let bord = if border { 2 } else { 0 };
2199        let resize = divider != NoColour;
2200        let size = if resize { factor + 1 } else { factor };
2201        let div = if !resize { 0 } else { factor - 1 };
2202        let mut cells = Matrix::new(self.cells.rows * factor + div + bord, self.cells.columns * factor + div + bord, Cell::new(0, 0, 0));
2203
2204        for b in 0 .. factor {
2205            for x in 0 .. self.cells.rows {
2206                for y in 0 .. self.cells.columns {
2207//println!("{x}/{y} {}/{} {} {}/{}", xf, yf, factor, dx, dy);
2208
2209                    let nx = x + self.cells.rows * b;
2210                    let ny = y + self.cells.columns * b;
2211//println!("{}/{} {}/{}", nx, ny, xf, yf);
2212
2213                    cells[(nx, ny)].x = nx;
2214                    cells[(nx, ny)].y = ny;
2215                    cells[(nx, ny)].colour = self.cells[(nx % (b + 1), ny % (b + 1))].colour;
2216                }
2217            }
2218        }
2219
2220        Shape::new(0, 0, &cells)
2221    }
2222    */
2223
2224    pub fn has_border_hole(&self, hole: bool, fc: &dyn Fn(usize, usize, usize, usize) -> bool) -> bool {
2225        let (r, c) = self.dimensions();
2226        if r < 3 || c < 3 {
2227            return false;
2228        }
2229        for ((r, c), cell) in self.cells.items() {
2230            let pred = fc(r, c, self.cells.rows, self.cells.columns);
2231
2232            if cell.colour == Black && pred || hole && cell.colour != Black && !pred {
2233                return false;
2234            }
2235        }
2236
2237        true
2238    }
2239
2240    pub fn has_border(&self) -> bool {
2241        self.has_border_hole(false, &|r, c, rows, cols| r == 0 || c == 0 || r == rows - 1 || c == cols - 1)
2242    }
2243
2244    pub fn is_hollow(&self) -> bool {
2245        self.has_border_hole(true, &|r, c, rows, cols| r == 0 || c == 0 || r == rows - 1 || c == cols - 1)
2246    }
2247
2248    pub fn has_open_border_top(&self) -> bool {
2249        self.has_border_hole(true, &|r, c, rows, cols| c == 0 || r == rows - 1 || c == cols - 1)
2250    }
2251
2252    pub fn has_open_hole_top(&self) -> bool {
2253        if self.is_hollow() {
2254            return false;
2255        }
2256        self.has_border_hole(false, &|r, c, rows, cols| c == 0 || r == rows - 1 || c == cols - 1)
2257    }
2258
2259    pub fn has_open_border_bottom(&self) -> bool {
2260        self.has_border_hole(true, &|r, c, _rows, cols| r == 0 || c == 0 || c == cols - 1)
2261    }
2262
2263    pub fn has_open_hole_bottom(&self) -> bool {
2264        if self.is_hollow() {
2265            return false;
2266        }
2267        self.has_border_hole(false, &|r, c, _rows, cols| r == 0 || c == 0 || c == cols - 1)
2268    }
2269
2270    pub fn has_open_border_left(&self) -> bool {
2271        self.has_border_hole(true, &|r, c, rows, cols| r == 0 || r == rows - 1 || c == cols - 1)
2272    }
2273
2274    pub fn has_open_hole_left(&self) -> bool {
2275        if self.is_hollow() {
2276            return false;
2277        }
2278        self.has_border_hole(false, &|r, c, rows, cols| r == 0 || r == rows - 1 || c == cols - 1)
2279    }
2280
2281    pub fn has_open_border_right(&self) -> bool {
2282        self.has_border_hole(true, &|r, c, rows, _cols| r == 0 || c == 0 || r == rows - 1)
2283    }
2284
2285    pub fn has_open_hole_right(&self) -> bool {
2286        if self.is_hollow() {
2287            return false;
2288        }
2289        self.has_border_hole(false, &|r, c, rows, _cols| r == 0 || c == 0 || r == rows - 1)
2290    }
2291
2292    pub fn find_a_border_break(&self) -> (Direction, usize, usize) {
2293        for ((r, c) , cell) in self.cells.items() {
2294            if r == 0 && cell.colour == Black { 
2295                return (Up, cell.row, cell.col);
2296            } else if c == self.cells.columns - 1 && cell.colour == Black {
2297                return (Right, cell.row, cell.col);
2298            } else if r == self.cells.rows - 1 && cell.colour == Black { 
2299                return (Down, cell.row, cell.col);
2300            } else if c == 0 && cell.colour == Black {
2301                return (Left, cell.row, cell.col);
2302            }
2303        }
2304
2305        (Other, 0, 0)
2306    }
2307
2308    pub fn has_border_break(&self) -> (Direction, usize, usize) {
2309        for ((r, c), cell) in self.cells.items() {
2310            let grow = self.orow + r;
2311            let gcol = self.ocol + c;
2312
2313            if cell.colour == Black && r == 0 {
2314                return (Up, grow, gcol);
2315            }
2316            if cell.colour == Black && c == 0  {
2317                return (Left, grow, gcol);
2318            }
2319            if cell.colour == Black && r == self.cells.rows - 1 {
2320                return (Down, grow, gcol);
2321            }
2322            if cell.colour == Black && c == self.cells.columns - 1 {
2323                return (Right, grow, gcol);
2324            }
2325        }
2326
2327        (Other, 0, 0)
2328    }
2329
2330    // TODO - remove old other from Shapes?
2331    pub fn centre_in(&self, other: &Self) -> Self {
2332        let new_other = self.move_in(other);
2333        let mut shape = self.clone();
2334
2335        for ((r, c), cell) in new_other.cells.items() {
2336            shape.cells[(r, c)] = cell.clone();
2337        }
2338
2339        shape
2340    }
2341
2342    /*
2343    pub fn mv(&self, xx: isize, yy: isize) -> Self {
2344        let mut shape = self.clone();
2345
2346        shape.ox = (shape.ox as isize + xx) as usize;
2347        shape.oy = (shape.oy as isize + yy) as usize;
2348
2349        for (x, y) in self.cells.keys() {
2350            shape.cells[(x, y)].x = (x as isize + xx) as usize;
2351            shape.cells[(x, y)].y = (y as isize + yy) as usize;
2352        }
2353
2354        shape
2355    }
2356    */
2357
2358    // TODO - remove old other from Shapes?
2359    pub fn put_all_in(&mut self, other: &Self) {
2360        for ((r, c), cell) in other.cells.items() {
2361            self.cells[(r, c)] = cell.clone();
2362        }
2363    }
2364
2365    pub fn centre_of(&self) -> (usize, usize) {
2366        (self.orow + self.cells.rows / 2, self.ocol + self.cells.columns / 2)
2367    }
2368
2369    pub fn centre_of_exact(&self) -> (f32, f32) {
2370        (self.orow as f32 + self.cells.rows as f32  / 2.0, self.ocol as f32 + self.cells.columns as f32  / 2.0)
2371    }
2372
2373    pub fn nearest_point_idx(&self, points: &Vec<(usize, usize)>) -> usize {
2374        let np = self.nearest_point(points);
2375
2376        for (i, &rc) in points.iter().enumerate() {
2377            if np == rc {
2378                return i;
2379            }
2380        }
2381
2382        usize::MAX
2383    }
2384
2385    pub fn nearest_point(&self, points: &Vec<(usize, usize)>) -> (usize, usize) {
2386        let (cr, cc) = self.centre_of_exact();
2387        let mut dist = f32::MAX;
2388        let mut nr = 0.0;
2389        let mut nc = 0.0;
2390
2391        for (r, c) in points.iter() {
2392            let r2_dist = ((cr - *r as f32).powi(2) + (cc - *c as f32).powi(2)).sqrt();
2393
2394            if dist == f32::MAX {
2395                nr = *r as f32;
2396                nc = *c as f32;
2397                dist = r2_dist;
2398            } else if r2_dist < dist {
2399                nr = *r as f32;
2400                nc = *c as f32;
2401                dist = r2_dist;
2402            }
2403        }
2404
2405        (nr as usize, nc as usize)
2406    }
2407
2408    pub fn pixel_coords(&self, colour: Colour) -> Option<(usize, usize)> {
2409        for c in self.cells.values() {
2410            if c.colour == colour {
2411                return Some((c.row, c.col));
2412            }
2413        }
2414
2415        None
2416    }
2417
2418    pub fn move_in(&self, other: &Self) -> Self {
2419        let (r, c) = self.centre_of();
2420        let (or, oc) = other.centre_of();
2421        let dr = (r - or) as isize;
2422        let dc = (c - oc) as isize;
2423
2424        other.translate(dr, dc)
2425    }
2426
2427    pub fn container(&self, other: &Self) -> bool {
2428        self.orow <= other.orow && self.ocol <= other.ocol && self.cells.rows + self.orow >= other.cells.rows + other.orow && self.cells.columns + self.ocol >= other.cells.columns + other.ocol
2429    }
2430
2431    pub fn can_contain(&self, other: &Self) -> bool {
2432        let (s, o) = if self.size() > other.size() { (self, other) } else { (other, self) };
2433        if s.width() < 2 || s.height() < 2 || s.width() < o.width() + 1 || s.height() < o.height() + 1 { return false };
2434        for (r, c) in other.cells.keys() {
2435            if r != 0 && c != 0 && r <= s.cells.rows && r <= s.cells.columns && s.cells[(r, c)].colour != Black {
2436                return false;
2437            }
2438        }
2439
2440        s.container(other)
2441    }
2442
2443    pub fn contained_by(&self, other: &Self) -> bool {
2444        other.can_contain(self)
2445    }
2446
2447    pub fn is_contained(&self, other: &Self) -> bool {
2448        let (s, o) = if self.size() > other.size() { (self, other) } else { (other, self) };
2449        if s.width() < 3 || s.height() < 3 || s.width() < o.width() + 2 || s.height() < o.height() + 2 { return false };
2450        for (r, c) in o.cells.keys() {
2451            if r != 0 && c != 0 && r < s.cells.rows && r < s.cells.columns && s.cells[(r, c)].colour != o.cells[(r - 1, c - 1)].colour {
2452                return false;
2453            }
2454        }
2455
2456        s.container(other)
2457    }
2458
2459    pub fn contained_in(&self, other: &Self) -> bool {
2460        other.is_contained(self)
2461    }
2462
2463    pub fn nest_mut(&mut self, n: usize, colour: Colour) {
2464        if self.cells.rows <= n || self.cells.columns <= n {
2465            return;
2466        }
2467        for r in n .. self.cells.rows - n {
2468            for c in n .. self.cells.columns - n {
2469                self.cells[(r,c)].colour = colour;
2470            }
2471        }
2472    }
2473
2474    // TODO: 50f325b5
2475    pub fn patch_in_shape(&self, other: &Self) -> (usize, usize) {
2476        for ch in self.cells.chunks(self.cells.columns) {
2477            //w.iter().for_each(|ch| print!("{:?},", ch.colour));
2478            let chr = ch.iter().map(|ch| format!("{:?}", ch.colour)).collect::<Vec<_>>().join(",");
2479println!("{}", chr);
2480            let mut iter = other.cells.iter();
2481            let c = iter.position(|c| { println!("{:?} {:?}", c[0].colour, ch[0].colour); c[0].colour != ch[0].colour});
2482            let c2 = iter.next();
2483            let c3 = iter.next();
2484    //println!("{:?},{:?},{:?}", c.unwrap()[0].colour, c2.colour, c3.colour);
2485    //println!("{:?}", c);
2486println!("{:?},{:?},{:?}", c, c2, c3);
2487        }
2488        println!();
2489        (0, 0)
2490    }
2491
2492    pub fn adjacent_r_or_c(&self, other: &Self) -> bool {
2493        self.orow + self.cells.rows == other.orow ||
2494        self.ocol + self.cells.columns == other.ocol ||
2495        other.orow + other.cells.rows == self.orow ||
2496        other.ocol + other.cells.columns == self.ocol
2497    }
2498
2499    // TODO: improave? % touching...
2500    pub fn touching(&self, other: &Self) -> bool {
2501        let sr = self.orow;
2502        let sc = self.ocol;
2503        let or = other.orow;
2504        let oc = other.ocol;
2505        let srl = self.cells.rows;
2506        let scl = self.cells.columns;
2507        let orl = other.cells.rows;
2508        let ocl = other.cells.columns;
2509
2510        sr + srl == or && oc <= sc && oc + ocl >= sc + scl ||
2511        sc + scl == oc && or >= sr && or + orl <= sr + srl ||
2512        or + orl == sr && sc <= oc && sc + scl >= oc + ocl ||
2513        oc + ocl == sc && sr >= or && sr + srl <= or + orl
2514    }
2515
2516    pub fn find_touching(&self, shapes: &Shapes) -> Shape {
2517        for s in shapes.shapes.iter() {
2518            if self.touching(s) {
2519                return s.clone();
2520            }
2521        }
2522
2523        Shape::trivial()
2524    }
2525
2526    pub fn single_colour(&self) -> Option<Colour> {
2527        let colour = self.cells[(0, 0)].colour;
2528
2529        for c in self.cells.values() {
2530            if c.colour != colour { return None; };
2531        }
2532
2533        Some(colour)
2534    }
2535
2536    pub fn is_single_colour(&self) -> bool {
2537        let mut first = true;
2538        let mut colour = NoColour;
2539
2540        for c in self.cells.values() {
2541            if first {
2542                colour = c.colour;
2543                first = false;
2544            } else if c.colour != colour {
2545                return false;
2546            }
2547        }
2548        
2549        true
2550    }
2551
2552    pub fn translate_row(&self, r: isize) -> Self {
2553        Self::translate(self, r, 0)
2554    }
2555
2556    pub fn translate_col(&self, c: isize) -> Self {
2557        Self::translate(self, 0, c)
2558    }
2559
2560    pub fn translate(&self, r: isize, c: isize) -> Self {
2561        let mut shape = self.clone();
2562
2563        if self.orow as isize + r < 0 || self.ocol as isize + c < 0 {
2564            return shape;
2565        }
2566
2567
2568        shape.orow = (shape.orow as isize + r) as usize;
2569        shape.ocol = (shape.ocol as isize + c) as usize;
2570
2571        shape.cells.iter_mut()
2572            .for_each(|cell| {
2573                cell.row = (cell.row as isize + r) as usize;
2574                cell.col = (cell.col as isize + c) as usize;
2575            });
2576
2577        shape
2578    }
2579
2580    pub fn translate_absolute_r(&self, r: usize) -> Self {
2581        Self::translate_absolute(self, r, 0)
2582    }
2583
2584    pub fn translate_absolute_c(&self, c: usize) -> Self {
2585        Self::translate_absolute(self, 0, c)
2586    }
2587
2588    pub fn translate_absolute(&self, r: usize, c: usize) -> Self {
2589        let mut shape = self.normalise_key();
2590
2591        shape.orow = r;
2592        shape.ocol = c;
2593
2594        shape.cells.iter_mut()
2595            .for_each(|cell| {
2596                cell.row += r;
2597                cell.col += c;
2598            });
2599
2600        shape
2601    }
2602
2603    // TODO!
2604    /*
2605    pub fn translate_absolute_clip(&self, x: isize, y: isize) -> Self {
2606        let offx = self.ox as isize + x;
2607        let offy = self.oy as isize + y;
2608        let rows = if offx < 0 { (self.cells.rows as isize + offx) as usize } else { self.cells.rows };
2609        let cols = if offy < 0 { (self.cells.columns as isize + offy) as isize as usize } else { self.cells.columns };
2610//println!("{offx}/{offy} {}/{}", rows, cols);
2611
2612        let mut shape = Shape::new_sized_coloured(rows, cols, Black);
2613
2614        shape.ox = if x < 0 { 0 } else { x as usize };
2615        shape.oy = if y < 0 { 0 } else { y as usize };
2616
2617        let x = if x < 0 { self.cells.rows - rows } else { x as usize };
2618        let y = if y < 0 { self.cells.columns - cols } else { y as usize };
2619
2620        shape.colour = self.colour;
2621
2622println!("{rows}/{cols} {}/{} {x}/{y} {}/{}", self.cells.rows, self.cells.columns, shape.ox, shape.oy);
2623        for xi in 0 .. rows {
2624            for yi in 0 .. cols {
2625                shape.cells[(xi, yi)].x = xi + shape.ox;
2626                shape.cells[(xi, yi)].y = yi + shape.oy;
2627                shape.cells[(xi, yi)].colour = self.cells[(xi + shape.ox, yi + shape.oy)].colour;
2628            }
2629        }
2630
2631        shape
2632    }
2633    */
2634
2635    /*
2636    fn quartered(&self, ox : usize, oy: usize) -> Option<Self> {
2637        if self.cells.rows % 2 == 1 || self.cells.columns % 2 == 1 {
2638            return None
2639        }
2640
2641        let xs = self.cells.rows / 2;
2642        let ys = self.cells.columns / 2;
2643
2644        let mut cells = Matrix::new(xs, ys, Cell::new(0, 0, 0));
2645
2646        for y in 0 .. ys {
2647            for x in 0 .. xs {
2648                cells[(x, y)].x = x;
2649                cells[(x, y)].y = y;
2650                cells[(x, y)].colour = self.cells[(ox + x, oy + y)].colour;
2651            }
2652        }
2653
2654        Some(Self::new_cells(&cells))
2655    }
2656
2657    pub fn quarter_tl(&self) -> Option<Self> {
2658        self.quartered(0, 0)
2659    }
2660
2661    pub fn quarter_tr(&self) -> Option<Self> {
2662        self.quartered(self.cells.columns / 2, 0)
2663    }
2664
2665    pub fn quarter_bl(&self) -> Option<Self> {
2666        self.quartered(0, self.cells.rows / 2)
2667    }
2668
2669    pub fn quarter_br(&self) -> Option<Self> {
2670        self.quartered(self.cells.columns / 2, self.cells.rows / 2)
2671    }
2672    */
2673
2674    /*
2675    #[allow(clippy::comparison_chain)]
2676    pub fn extend_x(&self, x: isize) -> Self {
2677        if x == 0 {
2678            return self.clone();
2679        }
2680
2681        let mut cells = self.cells.clone();
2682
2683        self.cells.iter()
2684            .for_each(|c| {
2685                if x < 0 {
2686                    for i in 0 .. -x {
2687                        let mut nc = c.clone();
2688
2689                        nc.x -= i + 1;
2690
2691                        if !cells.contains(&nc) { cells.push(nc); }
2692                    }
2693                } else if x > 0 {
2694                    for i in 0 .. x {
2695                        let mut nc = c.clone();
2696
2697                        nc.x += i + 1;
2698
2699                        if !cells.contains(&nc) { cells.push(nc); }
2700                    }
2701                }
2702            });
2703
2704        Self::new(&cells)
2705    }
2706
2707    #[allow(clippy::comparison_chain)]
2708    pub fn extend_y(&self, y: isize) -> Self {
2709        if y == 0 {
2710            return self.clone();
2711        }
2712
2713        let mut cells = self.cells.clone();
2714
2715        self.cells.iter()
2716            .for_each(|c| {
2717                if y < 0 {
2718                    for i in 0 .. -y {
2719                        let mut nc = c.clone();
2720
2721                        nc.y -= i + 1;
2722
2723                        if !cells.contains(&nc) { cells.push(nc); }
2724                    }
2725                } else if y > 0 {
2726                    for i in 0 .. y {
2727                        let mut nc = c.clone();
2728
2729                        nc.y += i + 1;
2730
2731                        if !cells.contains(&nc) { cells.push(nc); }
2732                    }
2733                }
2734            });
2735
2736        Self::new(&cells)
2737    }
2738    */
2739
2740    /*
2741    // Assumes they have overlapping x or y
2742    pub fn connect(&self, other: &Self, colour: Colour) -> Self {
2743        let (sx, sy) = self.centre_of();
2744        let (ox, oy) = other.centre_of();
2745        let (x, y) = if self.size() < other.size() { (sx, sy) } else { (ox, oy) };
2746        let cells = 
2747            if self.above(other) {
2748                let mut cells: Matrix<Cell> = Matrix::from_fn(1, oy - sy , |(_, _)| Cell::new_empty());
2749
2750                for i in sy .. oy {
2751                    let nc = Cell::new(i, y, colour.to_usize());
2752
2753                    if !self.cells.contains(&nc) && !other.cells.contains(&nc) {
2754                        cells[(0, i - sy)] = nc;
2755                    }
2756                }
2757
2758                cells
2759            } else if self.below(other) {
2760                let mut cells: Matrix<Cell> = Matrix::from_fn(1, sy - oy , |(_, _)| Cell::new_empty());
2761
2762                for i in oy .. sy {
2763                    let nc = Cell::new(i, y, colour.to_usize());
2764
2765                    if !self.cells.contains(&nc) && !other.cells.contains(&nc) {
2766                        cells[(0, i - oy)] = nc;
2767                    }
2768                }
2769
2770                cells
2771            } else if self.left(other) {
2772                let mut cells: Matrix<Cell> = Matrix::from_fn(sx - ox, 1, |(_, _)| Cell::new_empty());
2773
2774                for i in sx .. ox {
2775                    let nc = Cell::new(x, i, colour.to_usize());
2776
2777                    if !self.cells.contains(&nc) && !other.cells.contains(&nc) {
2778                        cells[(i - ox, 0)] = nc;
2779                    }
2780                }
2781
2782                cells
2783            } else /* right */ {
2784                let mut cells: Matrix<Cell> = Matrix::from_fn(ox - sx, 1, |(_, _)| Cell::new_empty());
2785
2786                for i in ox .. sx {
2787                    let nc = Cell::new(x, i, colour.to_usize());
2788
2789                    if !self.cells.contains(&nc) && !other.cells.contains(&nc) {
2790                        cells[(i - sx, 0)] = nc;
2791                    }
2792                }
2793
2794                cells
2795            };
2796
2797        Self::new_cells(&cells)
2798    }
2799
2800    // TODO fix plus x N
2801    pub fn connect_angle(&self, other: &Self, colour: Colour, horizontal: bool) -> Vec<Self> {
2802        let (sx, sy) = self.centre_of();
2803        let (ox, oy) = other.centre_of();
2804
2805        let cell = if horizontal {
2806            Cell::new(sx, oy, colour.to_usize())
2807        } else {
2808            Cell::new(ox, sy, colour.to_usize())
2809        };
2810
2811        let cells: Matrix<Cell> = Matrix::from_fn(cell.x, cell.y , |(_, _)| cell.clone());
2812        let joint = Self::new_cells(&cells);
2813        let arm_1 = self.connect(&joint, colour);
2814        let arm_2 = other.connect(&joint, colour);
2815
2816        vec![Self::new_cells(&arm_1.cells), Self::new_cells(&arm_2.cells)]
2817    }
2818    */
2819
2820    pub fn have_common_pixel_colour(&self, other: &Self) -> bool {
2821        let (colour_l, cnt_l) = self.colour_cnt(false);
2822        let (colour_r, cnt_r) = other.colour_cnt(false);
2823
2824        colour_l == colour_r && cnt_l == 1 && cnt_r == 1
2825    }
2826
2827    pub fn merge_on_common_pixel(&self, other: &Self) -> Option<Self> {
2828        let (colour_l, cnt_l) = self.colour_cnt(false);
2829        let (colour_r, cnt_r) = other.colour_cnt(false);
2830
2831        if colour_l != colour_r || cnt_l != 1 || cnt_r != 1 {
2832            return None;
2833        }
2834
2835        if let Some((r, c)) = self.pixel_coords(colour_l) {
2836            if let Some((or, oc)) = other.pixel_coords(colour_r) {
2837                let dr = (r - or) as isize;
2838                let dc = (c - oc) as isize;
2839
2840                Some(other.translate(dr, dc))
2841            } else {
2842                None
2843            }
2844        } else {
2845            None
2846        }
2847    }
2848
2849    pub fn normalise(&self, si: &Self) -> (Self, Self) {
2850        let mut o = self.clone();
2851        let mut i = si.clone();
2852
2853        i.orow -= self.orow;
2854        i.ocol -= self.ocol;
2855
2856        for c in i.cells.values_mut() {
2857            c.row -= self.orow;
2858            c.col -= self.ocol;
2859        }
2860
2861        o.orow -= self.orow;
2862        o.ocol -= self.ocol;
2863
2864        for c in o.cells.values_mut() {
2865            c.row -= self.orow;
2866            c.col -= self.ocol;
2867        }
2868
2869        (i, o)
2870    }
2871
2872    pub fn normalise_key(&self) -> Self {
2873        let mut i = self.clone();
2874        let or = if self.orow == 0 { self.orow } else { self.orow - 1 };
2875        let oc = if self.ocol == 0 { self.ocol } else { self.ocol - 1 };
2876
2877        i.orow -= or;
2878        i.ocol -= oc;
2879
2880        for c in i.cells.values_mut() {
2881            c.row -= or;
2882            c.col -= oc;
2883        }
2884
2885        i
2886    }
2887
2888    pub fn bare_corners(&self) -> bool {
2889        let rows = self.cells.rows;
2890        let cols = self.cells.columns;
2891
2892        self.cells[(0,0)].colour == Black && self.cells[(rows - 1,cols - 1)].colour == Black || self.cells[(rows - 1,0)].colour == Black && self.cells[(0,cols - 1)].colour == Black
2893    }
2894
2895    // TODO: needs backtracking
2896    pub fn fit_shape(&self, _shape: &Self) -> Self {
2897        self.clone()
2898    }
2899
2900    pub fn to_origin(&self) -> Self {
2901        self.to_position(0, 0)
2902    }
2903
2904    pub fn to_origin_mut(&mut self) {
2905        self.to_position_mut(0, 0)
2906    }
2907
2908    // relative so call to_origin first if absolute
2909    pub fn to_position(&self, r: usize, c: usize) -> Self {
2910        let mut i = self.clone();
2911
2912        i.to_position_mut(r, c);
2913
2914        i
2915    }
2916
2917    pub fn to_position_mut(&mut self, r: usize, c: usize) {
2918        for cell in self.cells.values_mut() {
2919            cell.row = cell.row + r - self.orow;
2920            cell.col = cell.col + c - self.ocol;
2921        }
2922
2923        self.orow = r;
2924        self.ocol = c;
2925    }
2926
2927    pub fn compare(&self, shape: &Self) -> bool {
2928        if self.cells.rows != shape.cells.rows || self.cells.columns != shape.cells.columns {
2929            return false;
2930        }
2931        let diffor = self.orow - shape.orow;
2932        let diffoc = self.ocol - shape.ocol;
2933
2934        for r in 0 .. self.cells.rows {
2935            for c in 0 .. self.cells.columns {
2936                let col1 = self.cells[(r,c)].colour;
2937                let col2 = shape.cells[(r,c)].colour;
2938                let diffr = self.cells[(r,c)].row - shape.cells[(r,c)].row;
2939                let diffc = self.cells[(r,c)].col - shape.cells[(r,c)].col;
2940
2941                if col1 != col2 || diffor != diffr || diffoc != diffc {
2942                    return false;
2943                }
2944            }
2945        }
2946
2947        true
2948    }
2949
2950    // Shapesmust be the sample size
2951    pub fn copy_into(&self, shape: &Self) -> Self {
2952        let mut s = shape.clone();
2953
2954        if self.width() != shape.width() || self.height() != shape.height() {
2955            return s;
2956        }
2957
2958        for ((r, c), cell) in self.cells.items() {
2959            s.cells[(r, c)].colour = cell.colour;
2960        }
2961
2962        s
2963    }
2964
2965    pub fn position(&self, ci: &Self) -> Self {
2966        let mut i = self.clone();
2967        let or = if ci.orow == 0 { ci.orow } else { ci.orow - 1 };
2968        let oc = if ci.ocol == 0 { ci.ocol } else { ci.ocol - 1 };
2969
2970        i.orow = or;
2971        i.ocol = oc;
2972
2973        for c in i.cells.values_mut() {
2974            c.row += or;
2975            c.col += oc;
2976        }
2977
2978        i
2979    }
2980
2981    /*
2982    pub fn shrink(&self) -> Self {
2983        let mut sx = 0;
2984        let mut ex = self.cells.rows;
2985        let mut sy = 0;
2986        let mut ey = self.cells.columns;
2987
2988        for x in 0 .. self.cells.rows {
2989            if (x .. self.cells.columns).filter(|&c| c != 0).count() == 0 {
2990                sx += 1;
2991            } else {
2992                break;
2993            }
2994        }
2995        for x in (0 .. self.cells.rows).rev() {
2996            if (x .. self.cells.columns).filter(|&c| c != 0).count() == 0 {
2997                ex -= 1;
2998            } else {
2999                break;
3000            }
3001        }
3002        if sx > ex { return self.clone(); }
3003        for y in 0 .. self.cells.columns {
3004            if (y .. self.cells.rows).filter(|&c| c != 0).count() == 0 {
3005                sy += 1;
3006            } else {
3007                break;
3008            }
3009        }
3010        for y in (0 .. self.cells.columns).rev() {
3011            if (y .. self.cells.rows).filter(|&c| c != 0).count() == 0 {
3012                ey -= 1;
3013            } else {
3014                break;
3015            }
3016        }
3017        if sy > ey { return self.clone(); }
3018println!("{sx} -> {ex}, {sy} -> {ey}");
3019        let mut m = Matrix::new(ex - sx, ey - sy, Cell::new(0, 0, 0));
3020
3021        for x in sx .. ex {
3022            for y in sy .. ey {
3023                m[(x - sx, y - sy)] = self.cells[(x, y)].clone();
3024            }
3025        }
3026println!("{sx} -> {ex}, {sy} -> {ey}");
3027
3028        Self::new_cells(&m)
3029    }
3030    */
3031
3032    pub fn has_border_cell(&self, other: &Self) -> bool {
3033        if self.orow == 0 && self.ocol == 0 {
3034            return true;
3035        }
3036
3037        for cell in self.cells.values() {
3038            if cell.row == other.cells.rows - 1 || cell.col == other.cells.columns - 1 {
3039                return true;
3040            }
3041        }
3042
3043        false
3044    }
3045
3046    pub fn is_subgrid(&self, other: &Self) -> bool {
3047        let (sr,sc) = self.dimensions();
3048        let (or,oc) = other.dimensions();
3049
3050        if or > sr || oc > sc {
3051            return false;
3052        }
3053
3054        for r in 0 ..= sr - or {
3055            for c in 0 ..= sc - oc {
3056                let mut is_sg = true;
3057
3058                for rr in 0 .. or {
3059                    for cc in 0 .. oc {
3060//println!("{} + {}, {} + {} --- {} {}", r, rr, c, cc, sr, sc);
3061                        let scol = self.cells[(r + rr,c + cc)].colour;
3062                        let ocol = other.cells[(rr,cc)].colour;
3063
3064                        if scol != ocol && ocol != Black || scol == Black {
3065                            is_sg = false;
3066                            break;
3067                        }
3068                    }
3069                    if !is_sg {
3070                        break;
3071                    }
3072                }
3073                if is_sg {
3074/*
3075println!(">>>>");
3076self.show();
3077other.show();
3078println!("<<<<");
3079println!("{}, {} --- {} {}", r, c, sc, oc);
3080*/
3081                    return true;
3082                }
3083            }
3084        }
3085
3086        false
3087    }
3088
3089    /*
3090    pub fn match_shapes(&self, other: &Self) -> Direction {
3091        fn check(s: &Shape, other: &Shape) -> bool {
3092            for (r, c) in other.cells.keys() {
3093                if s.cells[(r,c)].colour != s.colour || s.cells[(r,c)].colour == Black {
3094                    return false;
3095                }
3096            }
3097
3098            true
3099        }
3100
3101        let (sr, sc) = self.dimensions();
3102        let (or, oc) = other.dimensions();
3103println!("{sr}/{sc} {or}/{oc}");
3104self.show();
3105
3106        if sr == or && sc == oc {
3107println!("0");
3108            for (c1, c2) in self.cells.values().zip(other.cells.values()) {
3109                if c1.colour != c2.colour && c1.colour != Black && c2.colour != Black {
3110                    return Other;
3111                }
3112            }
3113
3114            return SameDir;
3115        }
3116        if sr == oc {
3117/*
3118println!("1");
3119self.show();
3120            let s = self.rotated_90();
3121
3122            if check(&s, other) {
3123                return Left;
3124            } else {
3125                let s = self.rotated_270();
3126
3127                if check(&s, other) {
3128                    return Right;
3129                }
3130            }
3131*/
3132        }
3133        if sc == or {
3134println!("2");
3135//self.show();
3136            let s = self.rotated_90();
3137
3138            if check(&s, other) {
3139println!("2L");
3140                return Left;
3141            } else if false {
3142                let s = self.rotated_270();
3143
3144                if check(&s, other) {
3145println!("2R");
3146                    return Right;
3147                }
3148            }
3149        }
3150        if sr == or {
3151println!("3");
3152        }
3153        if sc == oc {
3154println!("4");
3155        }
3156
3157        Other
3158    }
3159    */
3160
3161    pub fn find_black_patches_limit(&self, limit: usize) -> Shapes {
3162        let mut bp = self.to_grid().find_black_patches_limit(limit);
3163
3164        for s in bp.shapes.iter_mut() {
3165            s.orow += self.orow;
3166            s.ocol += self.ocol;
3167
3168            for cell in s.cells.values_mut() {
3169                cell.row += self.orow;
3170                cell.col += self.ocol;
3171            }
3172        }
3173
3174        bp
3175    }
3176
3177    pub fn has_arm(&self, limit: usize) -> (Direction, usize) {
3178        let mut bp = self.to_grid().find_black_patches_limit(limit);
3179
3180        // Remove internal shapes
3181        if bp.shapes.len() != 2 {
3182            for (i, s) in bp.shapes.clone().iter().enumerate() {
3183                if !s.has_border_cell(self) && i < bp.len() {
3184                    bp.shapes.remove(i);
3185                }
3186            }
3187        }
3188
3189        if bp.shapes.len() == 2 {
3190            let rows1 = bp.shapes[0].cells.rows;
3191            let cols1 = bp.shapes[0].cells.columns;
3192            let rows2 = bp.shapes[1].cells.rows;
3193            let cols2 = bp.shapes[1].cells.columns;
3194
3195            if self.cells[(0,0)].colour == Black && self.cells[(self.cells.rows - 1,0)].colour == Black && rows1 + rows2 + 1 == self.cells.rows {
3196                (Direction::Left, cols1)
3197            } else if self.cells[(0,self.cells.columns - 1)].colour == Black && self.cells[(self.cells.rows - 1,self.cells.columns - 1)].colour == Black && rows1 + rows2 + 1 == self.cells.rows {
3198                (Direction::Right, cols1)
3199            } else if cols1 + cols2 + 1 == self.cells.columns {
3200                if self.cells[(0,0)].colour == Black {
3201                    (Direction::Up, rows1)
3202                } else {
3203                    (Direction::Down, rows1)
3204                }
3205            } else {
3206                (Direction::Other, 0)
3207            }
3208        } else {
3209            (Direction::Other, 0)
3210        }
3211    }
3212
3213    /*
3214    pub fn get_arm(&self) -> (Direction, usize){
3215        for pat in &self.cats {
3216            match pat {
3217                ShapeCategory::ArmTop(n) =>
3218                    return (Up, *n),
3219                ShapeCategory::ArmBottom(n) => 
3220                    return (Down, *n),
3221                ShapeCategory::ArmLeft(n) => 
3222                    return (Left, *n),
3223                ShapeCategory::ArmRight(n) => 
3224                    return (Right, *n),
3225                _ => ()
3226            }
3227        }
3228
3229        (Other, 0)
3230    }
3231
3232    pub fn trim_arm(&self) -> Self {
3233        let (dir, distance) = self.get_arm();
3234//self.show_summary();
3235//println!("--- {:?} {}", dir, distance);
3236
3237        match dir {
3238            Up =>
3239                self.subshape(self.orow, self.cells.rows - distance, self.ocol, self.cells.columns),
3240            Down => 
3241                self.subshape(self.orow + distance, self.cells.rows - distance, self.ocol, self.cells.columns),
3242            Left => 
3243                self.subshape(self.orow, self.cells.rows, self.ocol, self.cells.columns - distance),
3244            Right => 
3245                self.subshape(self.orow + distance, self.cells.rows - distance, self.ocol + distance, self.cells.columns - distance),
3246            _ => self.clone(),
3247        }
3248    }
3249
3250    pub fn has_arm(&self) -> ShapeCategory {
3251        for ((x, y), c) in self.cells.items() {
3252            match c.cat {
3253                PointT => {
3254                    if self.cells.rows > 1 && self.cells.columns == 1 {
3255                        return ShapeCategory::VerticalLine;
3256                    }
3257                    let mut i = 1;
3258                    while x + i < self.cells.rows && self.cells[(x+i,y)].cat == InternalEdgeT {
3259                        i += 1;
3260                    }
3261                    if i >= 2 {
3262                        return ShapeCategory::ArmTop(i)
3263                    }
3264                },
3265                PointB => {
3266                    if self.cells.rows > 1 && self.cells.columns == 1 {
3267                        return ShapeCategory::VerticalLine;
3268                    }
3269                    let mut i = 1;
3270                    while x < i && self.cells[(x-i,y)].cat == InternalEdgeB {
3271                        i += 1;
3272                    }
3273                    if i >= 2 {
3274                        return ShapeCategory::ArmBottom(i)
3275                    }
3276                },
3277                PointL => {
3278                    if self.cells.rows == 1 && self.cells.columns > 1 {
3279                        return ShapeCategory::HorizontalLine;
3280                    }
3281                    let mut i = 1;
3282                    while y + i < self.cells.columns && self.cells[(x,y+i)].cat == InternalEdgeL {
3283                        i += 1;
3284                    }
3285                    if i >= 2 {
3286                        return ShapeCategory::ArmLeft(i)
3287                    }
3288                },
3289                PointR => {
3290                    if self.cells.rows == 1 && self.cells.columns > 1 {
3291                        return ShapeCategory::HorizontalLine;
3292                    }
3293                    let mut i = 1;
3294                    while y > i && self.cells[(x,y-i)].cat == InternalEdgeR {
3295                        i += 1;
3296                    }
3297                    if i >= 2 {
3298                        return ShapeCategory::ArmRight(i)
3299                    }
3300                },
3301                _ => continue,
3302            }
3303        }
3304
3305        ShapeCategory::Other
3306    }
3307    */
3308
3309    /*
3310    pub fn repeat(&self, x: isize, y: isize) -> Self {
3311    }
3312    */
3313
3314    // TODO
3315    // pub fn contract?
3316
3317    /*
3318    pub fn horizontal_stretch(&self, cells: Vec<Cell>) -> Self {
3319        self.clone()
3320    }
3321
3322    pub fn vertical_stretch(&self, cells: Vec<Cell>) -> Self {
3323        self.clone()
3324    }
3325
3326    // bool is true == Row axis, false = Col axis
3327    pub fn striped_x(&self) -> Colour {
3328        NoColour
3329    }
3330
3331    pub fn striped_y(&self) -> Colour {
3332        NoColour
3333    }
3334
3335    pub fn strip_colours_x(&self) -> Vec<Colour> {
3336        vec![]
3337    }
3338
3339    pub fn strip_colours_y(&self) -> Vec<Colour> {
3340        vec![]
3341    }
3342
3343    pub fn flip_colours(&self) -> Self {
3344        self.clone()
3345    }
3346
3347    pub fn box_it(&self) -> Self {
3348        self.clone()
3349    }
3350
3351    pub fn four_borders(&self, colour: Colour) -> Self {
3352        self.clone()
3353    }
3354
3355    pub fn four_diagonals(&self, colour: Colour) -> Self {
3356        self.clone()
3357    }
3358    */
3359
3360    pub fn bordered_shape(&self) -> bool {
3361        let colour = self.cells[(0,0)].colour;
3362
3363        if self.cells.rows < 3 || self.cells.columns < 3 || colour == Black {
3364            return false;
3365        }
3366        
3367        for ((r, c), cell) in self.cells.items() {
3368            if r == 0 && cell.colour != colour {
3369                return false;
3370            }
3371            if c == 0 && cell.colour != colour {
3372                return false;
3373            }
3374            if r == self.cells.rows - 1 && cell.colour != colour {
3375                return false;
3376            }
3377            if c == self.cells.columns - 1 && cell.colour != colour {
3378                return false;
3379            }
3380        }
3381
3382        true
3383    }
3384
3385    // Expensive!
3386    pub fn hollow(&self) -> bool {
3387        if self.cells.rows < 3 || self.cells.columns < 3 || self.cells[(1,1)].colour != Black && self.cells.rows == 3 && self.cells.columns == 3 && !self.is_full(){
3388            return false;
3389        }
3390//self.show();
3391
3392        'outer:
3393        for ((r, c), cell) in self.cells.items() {
3394            // Interior cells only interesting
3395            if r == 0 || c == 0 || r == self.cells.rows - 1 || c == self.cells.columns - 1 || cell.colour != Black {
3396                continue;
3397            }
3398
3399            let reachable = self.cells.bfs_reachable((r, c), true, |i| self.cells[i].colour != self.colour);
3400
3401            for (r,c) in &reachable {
3402                if *r == 0 || *c == 0 || *r == self.cells.rows - 1 || *c == self.cells.columns - 1 {
3403                    continue 'outer;
3404                }
3405            }
3406
3407            return true;
3408        }
3409//println!("{hollow}");
3410
3411        false
3412    }
3413
3414    /*
3415    pub fn find_hollows(&self) -> Shapes {
3416        if self.cells.rows < 3 || self.cells.columns < 3 || self.cells[(1,1)].colour != Black && self.cells.rows == 3 && self.cells.columns == 3 && !self.is_full(){
3417            return Shapes::new();
3418        }
3419//self.show();
3420        let mut shapes = Shapes::new_from_shape(self);
3421
3422        'outer:
3423        for ((x, y), c) in self.cells.items() {
3424            // Interior cells only interesting
3425            if x == 0 || y == 0 || x == self.cells.rows - 1 || y == self.cells.columns - 1 || c.colour != Black {
3426                continue;
3427            }
3428
3429            let reachable = self.cells.bfs_reachable((x, y), true, |i| self.cells[i].colour != self.colour);
3430
3431            for (x,y) in &reachable {
3432                if *x == 0 || *y == 0 || *x == self.cells.rows - 1 || *y == self.cells.columns - 1 {
3433                    continue 'outer;
3434                }
3435            }
3436
3437            let s = Shape::shape_from_reachable(self, &reachable);
3438
3439            shapes.shapes.push(s);
3440        }
3441//println!("{hollow}");
3442
3443        shapes
3444    }
3445    */
3446
3447    pub fn hollow_colour_count(&self) -> (Colour, usize) {
3448        let ss = self.fill_boundary_colour().to_grid().find_colour_patches(Black);
3449
3450        (self.colour, ss.shapes.len())
3451    }
3452
3453    pub fn full_shape(&self) -> bool {
3454        let colour = self.cells[(0,0)].colour;
3455
3456        for c in self.cells.values() {
3457            if c.colour != colour {
3458                return false;
3459            }
3460        }
3461
3462        true
3463    }
3464
3465    pub fn add_hugging_border(&self, colour: Colour) -> Self {
3466        if self.orow == 0 && self.ocol == 0 {
3467            return self.clone();
3468        }
3469
3470        let mut shape = self.add_border(colour);
3471
3472        if self.is_full() {
3473            return shape;
3474        }
3475
3476        let copy_shape = shape.clone();
3477        let rows = shape.cells.rows - 1;
3478        let cols = shape.cells.columns - 1;
3479
3480        for (r, c) in copy_shape.cells.keys() {
3481            match (r, c) {
3482                (0, _) if shape.cells[(1,c)].colour == Black => {
3483                    for r in 1 .. rows {
3484                        if shape.cells[(r,c)].colour == Black {
3485                            shape.cells[(r,c)].colour = colour;
3486                        } else {
3487                            break;
3488                        }
3489                    }
3490                },
3491                (_, 0) if shape.cells[(r,1)].colour == Black => {
3492                    for c in 1 .. cols {
3493                        if shape.cells[(r,c)].colour == Black {
3494                            shape.cells[(r,c)].colour = colour;
3495                        } else {
3496                            break;
3497                        }
3498                    }
3499                },
3500                (r, _) if r == rows && shape.cells[(r-1,c)].colour == Black => {
3501                    for r in (1 .. rows).rev() {
3502                        if shape.cells[(r,c)].colour == Black {
3503                            shape.cells[(r,c)].colour = colour;
3504                        } else {
3505                            break;
3506                        }
3507                    }
3508                },
3509                (_, c) if c == cols && shape.cells[(r,c-1)].colour == Black => {
3510                    for c in (1 .. cols).rev() {
3511                        if shape.cells[(r,c)].colour == Black {
3512                            shape.cells[(r,c)].colour = colour;
3513                        } else {
3514                            break;
3515                        }
3516                    }
3517                },
3518                __ => {
3519                },
3520            }
3521        }
3522
3523        let mut rc: Vec<(usize, usize)> = Vec::new();
3524
3525        for (r, c) in shape.cells.keys() {
3526            let (cnt, _) = surround_cnt(&shape.cells, r, c, colour);
3527
3528            if cnt == 8 {
3529                rc.push((r, c));
3530            }
3531        }
3532
3533        for rc in rc.iter() {
3534            shape.cells[rc].colour = Black;
3535        }
3536
3537        shape
3538    }
3539
3540    pub fn add_border(&self, colour: Colour) -> Self {
3541        if self.orow == 0 && self.ocol == 0 {
3542            let mut s = Shape::new_sized_coloured_position(self.orow, self.ocol, self.cells.rows + 1, self.cells.columns + 1, colour);
3543
3544            for ((r, c), cell) in self.cells.items() {
3545                s.cells[(r,c)] = cell.clone(); 
3546            }
3547
3548            s
3549        } else if self.orow == 0 {
3550            let mut s = Shape::new_sized_coloured_position(self.orow, self.ocol - 1 , self.cells.rows + 1, self.cells.columns + 2, colour);
3551
3552            for ((r, c), cell) in self.cells.items() {
3553                s.cells[(r,c+1)] = cell.clone(); 
3554            }
3555
3556            if s.ocol > 0 { s.ocol -= 1 };
3557
3558            s
3559        } else if self.ocol == 0 {
3560            let mut s = Shape::new_sized_coloured_position(self.orow - 1, self.ocol, self.cells.rows + 2, self.cells.columns + 2, colour);
3561
3562            for ((r, c), cell) in self.cells.items() {
3563                s.cells[(r+1,c)] = cell.clone(); 
3564            }
3565
3566            if s.orow > 0 { s.orow -= 1 };
3567
3568            s
3569        } else {
3570            let mut s = Shape::new_sized_coloured_position(self.orow - 1, self.ocol - 1, self.cells.rows + 2, self.cells.columns + 2, colour);
3571
3572            for ((r, c), cell) in self.cells.items() {
3573                s.cells[(r+1,c+1)] = cell.clone(); 
3574            }
3575
3576            if s.orow > 0 { s.orow -= 1 };
3577            if s.ocol > 0 { s.ocol -= 1 };
3578
3579            s
3580        }
3581    }
3582
3583    pub fn toddle_colour(&self, bg: Colour, fg: Colour) -> Self {
3584        let s = self.recolour(bg, ToBlack + bg).recolour(fg, bg);
3585
3586        s.recolour(ToBlack + bg, fg)
3587    }
3588
3589    pub fn extend_top(&self, n: usize) -> Self {
3590        let mut cells = Matrix::new(self.cells.rows + n, self.cells.columns, Cell::new(0, 0, 0));
3591        for r in 0 .. cells.columns {
3592            for c in 0 .. n {
3593                cells[(c, r)].row = c + self.orow;
3594                cells[(c, r)].col = r + self.ocol;
3595                cells[(c, r)].colour = self.cells[(0, r)].colour;
3596            }
3597        }
3598        for r in n .. cells.rows {
3599            for c in 0 .. cells.columns {
3600                cells[(r, c)].row = r + self.orow;
3601                cells[(r, c)].col = c + self.ocol;
3602                cells[(r, c)].colour = self.cells[(r - n, c)].colour;
3603            }
3604        }
3605
3606        Shape::new(self.orow, self.ocol, &cells)
3607    }
3608
3609    pub fn extend_bottom(&self, n: usize) -> Self {
3610        self.mirrored_r().extend_top(n).mirrored_r()
3611    }
3612
3613    pub fn extend_left(&self, n: usize) -> Self {
3614        let mut cells = Matrix::new(self.cells.rows, self.cells.columns + n, Cell::new(0, 0, 0));
3615
3616        for r in 0 .. cells.rows {
3617             for c in 0 .. n {
3618                cells[(r, c)].row = r + self.orow;
3619                cells[(r, c)].col = c + self.ocol;
3620                cells[(r, c)].colour = self.cells[(r, 0)].colour;
3621            }
3622        }
3623        for r in 0 .. cells.rows {
3624            for c in n .. cells.columns {
3625                cells[(r, c)].row = r + self.orow;
3626                cells[(r, c)].col = c + self.ocol;
3627                cells[(r, c)].colour = self.cells[(r, c - n)].colour;
3628            }
3629        }
3630
3631        Shape::new(self.orow, self.ocol, &cells)
3632    }
3633
3634    pub fn extend_right(&self, n: usize) -> Self {
3635        self.mirrored_c().extend_left(n).mirrored_c()
3636    }
3637
3638    pub fn dense(&self) -> bool {
3639        for c in self.cells.values() {
3640            if c.colour == Black {
3641                return false;
3642            }
3643        }
3644
3645        true
3646    }
3647
3648    pub fn split_shapes(&self) -> Shapes {
3649        Shapes::new_from_shape(self)
3650    }
3651
3652    // Single colour shapes only
3653    pub fn de_subshape(&self, shapes: &mut Shapes) {
3654        if self.size() > 9 {
3655            let ss = self.to_grid().to_shapes_sq();
3656
3657            if ss.len() > 1
3658            {
3659                for ns in &ss.shapes {
3660                    shapes.shapes.push(ns.clone());
3661                }
3662            } else {
3663                shapes.add(self);
3664            }
3665        } else {
3666            shapes.add(self);
3667        }
3668    }
3669
3670    pub fn draw_line(&self, other: &Self, colour: Colour) -> Shape {
3671        let s1 = self.centre_of();
3672        let s2 = other.centre_of();
3673
3674//println!("--- {s1:?} -> {s2:?}");
3675        let (r, c) = if s1 < s2 { s1 } else { s2 };
3676        let (rl, cl) = ((s1.0.max(s2.0) - s1.0.min(s2.0)).max(1), (s1.1.max(s2.1) - s1.1.min(s2.1)).max(1));
3677
3678        Shape::new_sized_coloured_position(r, c, rl, cl, colour)
3679    }
3680
3681    pub fn fill_lines(&self, colour: Colour) -> Self {
3682        let mut s = self.clone();
3683        let mut rows: BTreeMap<usize, usize> = BTreeMap::new();
3684        let mut cols: BTreeMap<usize, usize> = BTreeMap::new();
3685
3686        for ((row, col), c) in self.cells.items() {
3687            if c.colour != Black {
3688                *rows.entry(row).or_insert(0) += 1;
3689                *cols.entry(col).or_insert(0) += 1;
3690            }
3691        }
3692
3693        for ((row, col), cell) in s.cells.items_mut() {
3694            if let Some(r) = rows.get(&row) {
3695                if *r > 3 && cell.colour == Black {
3696                    cell.colour = colour;
3697                }
3698            }
3699            if let Some(c) = cols.get(&col) {
3700                if *c > 3 && cell.colour == Black {
3701                    cell.colour = colour;
3702                }
3703            }
3704        }
3705
3706        s
3707    }
3708
3709    pub fn find_first_blacks(&self) -> Vec<(usize,usize)> {
3710        self.find_first_colours(Black)
3711    }
3712
3713    pub fn find_first_colours(&self, colour: Colour) -> Vec<(usize,usize)> {
3714        let mut fb: Vec<(usize,usize)> = Vec::new();
3715        let mut bg = false;
3716        let mut nr = 0;
3717
3718        for ((r, c), cell) in self.cells.items() {
3719            if cell.colour == colour {
3720                if !bg && nr == r {
3721                    fb.push((r,c));
3722                }
3723            } else if c == 0 {
3724                nr = r + 1;
3725            }
3726            bg = cell.colour == colour;
3727        }
3728
3729        fb
3730    }
3731
3732    // Result may need trimming later
3733    pub fn surround(&self, thickness: usize, colour: Colour, all: bool, corners: bool) -> Self {
3734        if self.orow < thickness || self.ocol < thickness {
3735            return self.clone();
3736        }
3737
3738        let height = self.cells.rows + thickness * 2;
3739        let width = self.cells.columns + thickness * 2;
3740        let mut shape = Shape::new_sized_coloured(height, width, Transparent);
3741
3742        //let this = self.translate_absolute(100, 100);
3743//println!("{this:?}");
3744        let this = self.clone();
3745
3746        shape.colour = colour;
3747        shape.orow = this.orow - thickness;
3748        shape.ocol = this.ocol - thickness;
3749
3750        for r in 0 .. shape.cells.rows {
3751            for c in 0 .. shape.cells.columns {
3752                shape.cells[(r,c)].row = this.orow + r - thickness;
3753                shape.cells[(r,c)].col = this.ocol + c - thickness;
3754
3755                let bounds = r < thickness && c < thickness || r < thickness && c >= this.cells.columns + thickness || r >= this.cells.rows + thickness && c < thickness || r >= this.cells.rows + thickness && c >= this.cells.columns + thickness;
3756
3757                if !all && (!corners && bounds || corners && !bounds) {
3758                    continue;
3759                }
3760                if r < thickness || r >= this.cells.rows + thickness || c < thickness || c >= this.cells.columns + thickness {
3761                    shape.cells[(r,c)].colour = colour;
3762                }
3763            }
3764        }
3765
3766        shape
3767    }
3768
3769    /*
3770    pub fn categorise_shape(&mut self) {
3771        let has_border = self.has_border();
3772
3773        /*
3774        if has_border {
3775            self.cats.insert(ShapeCategory::SingleCell);
3776        }
3777        */
3778        if has_border && self.is_hollow() {
3779            self.cats.insert(ShapeCategory::HasHole);
3780        }
3781        if !has_border && self.cells.rows == self.cells.columns {
3782            if self.cells.rows == 1 {
3783                self.cats.insert(ShapeCategory::Pixel);
3784                //self.cats.insert(ShapeCategory::HorizontalLine);
3785                //self.cats.insert(ShapeCategory::VerticalLine);
3786            } else {
3787                self.cats.insert(ShapeCategory::Square);
3788            }
3789        }
3790        if !has_border {
3791            self.cats.insert(ShapeCategory::HasBorder);
3792        }
3793        if !has_border && self.has_open_border_top() {
3794            self.cats.insert(ShapeCategory::OpenTop);
3795        }
3796        if !has_border && self.has_open_border_bottom() {
3797            self.cats.insert(ShapeCategory::OpenBottom);
3798        }
3799        if !has_border && self.has_open_border_left() {
3800            self.cats.insert(ShapeCategory::OpenLeft);
3801        }
3802        if !has_border && self.has_open_border_right() {
3803            self.cats.insert(ShapeCategory::OpenRight);
3804        }
3805        if !has_border && self.has_open_hole_top() {
3806            self.cats.insert(ShapeCategory::OpenTopHole);
3807        }
3808        if !has_border && self.has_open_hole_bottom() {
3809            self.cats.insert(ShapeCategory::OpenBottomHole);
3810        }
3811        if !has_border && self.has_open_hole_left() {
3812            self.cats.insert(ShapeCategory::OpenLeftHole);
3813        }
3814        if !has_border && self.has_open_hole_right() {
3815            self.cats.insert(ShapeCategory::OpenRightHole);
3816        }
3817        //if !has_border && self.is_full() {
3818        if self.is_full() {
3819            self.cats.insert(ShapeCategory::Full);
3820        }
3821        /*
3822        // Only sensible when called tactically
3823        } else if !has_border {
3824            if self.is_mirror_x() {
3825                self.cats.insert(ShapeCategory::MirrorX);
3826            }
3827            if self.is_mirror_y() {
3828                self.cats.insert(ShapeCategory::MirrorY);
3829            }
3830        }
3831        else if !has_border && self.hollow() {
3832//println!("hhhh");
3833            // Too expensive
3834            self.cats.insert(ShapeCategory::Hollow);
3835        }
3836        */
3837
3838        /*
3839//        for _ in 0 .. 2 {
3840            let arm = self.has_arm();
3841            if !has_border && arm != ShapeCategory::Other {
3842//println!("-- {:?}", arm);
3843                self.cats.insert(arm);
3844            }
3845//        }
3846        */
3847//println!("{:?}", self.cats);
3848    }
3849    */
3850
3851    /*
3852    pub fn outer_cells(cells: &Matrix<Cell>) -> Vec<Cell> {
3853        for ((r, c), cell) in cells {
3854            if cell.colour 
3855        }
3856    }
3857    */
3858
3859    pub fn bg_count(&self) -> usize {
3860        let mut cnt = 0;
3861
3862        for cell in self.cells.values() {
3863            if cell.colour == Black {
3864                cnt += 1;
3865            }
3866        }
3867
3868        cnt
3869    }
3870
3871    pub fn split_2(&self) -> Shapes {
3872        self.to_grid().split_2()
3873    }
3874
3875    pub fn cell_category(cells: &Matrix<Cell>) -> Matrix<Cell> {
3876        Self::cell_category_bg(cells, Black)
3877    }
3878
3879    pub fn cell_category_bg(cells: &Matrix<Cell>, bg: Colour) -> Matrix<Cell> {
3880        let mut m = cells.clone();
3881
3882        for ((r, c), cell) in m.items_mut() {
3883            if cell.colour == bg { continue; }
3884
3885            let cat = 
3886                if r == 0 {
3887                    if (c == 0 || cells[(r,c-1)].colour == bg) && (c == cells.columns - 1 || cells[(r,c+1)].colour == bg) {
3888                        CellCategory::PointT
3889                    } else if c == 0 {
3890                        if cells.rows == 1 || cells[(r+1,c)].colour == bg {
3891                            CellCategory::PointL
3892                        } else {
3893                            CellCategory::CornerTL
3894                        }
3895                    } else if c == cells.columns - 1 {
3896                        CellCategory::CornerTR
3897                    } else if c < cells.columns - 1 && cells[(r,c+1)].colour == bg {
3898                        CellCategory::InternalCornerTR
3899                    } else if c > 0 && cells[(r,c-1)].colour == bg {
3900                        CellCategory::InternalCornerTL
3901                    } else if cells.rows == 1 || cells[(r+1,c)].colour == bg {
3902                        CellCategory::StemLR
3903                    } else {
3904                        CellCategory::EdgeT
3905                    }
3906                } else if r == cells.rows - 1 {
3907                    if (c == 0 || cells[(r,c-1)].colour == bg) && (c == cells.columns - 1 || cells[(r,c+1)].colour == bg) {
3908                        CellCategory::PointB
3909                    } else if c == 0 {
3910                        CellCategory::CornerBL
3911                    } else if c == cells.columns - 1 {
3912                        if cells[(r-1,c)].colour == bg {
3913                            CellCategory::PointR
3914                        } else {
3915                            CellCategory::CornerBR
3916                        }
3917                    } else if c < cells.columns - 1 && cells[(r,c+1)].colour == bg {
3918                        CellCategory::InternalCornerBR
3919                    } else if c > 0 && cells[(r,c-1)].colour == bg {
3920                        CellCategory::InternalCornerBL
3921                    } else if cells.rows == 1 || cells[(r-1,c)].colour == bg {
3922                        CellCategory::StemLR
3923                    } else {
3924                        CellCategory::EdgeB
3925                    }
3926                } else if c == 0 {
3927                    if (r == 0 || cells[(r-1,c)].colour == bg) && (r == cells.rows - 1 || cells[(r+1,c)].colour == bg) {
3928                        CellCategory::PointL
3929                    } else if r > 0 && cells[(r-1,c)].colour == bg {
3930                        CellCategory::InternalCornerTL
3931                    } else if cells.columns == 1 || cells[(r,c+1)].colour == bg {
3932                        CellCategory::StemTB
3933                    } else {
3934                        CellCategory::EdgeL
3935                    }
3936                } else if c == cells.columns - 1 {
3937                    if (r == 0 || cells[(r-1,c)].colour == bg) && (r == cells.rows - 1 || cells[(r+1,c)].colour == bg) {
3938                        CellCategory::PointR
3939                    } else if r > 0 && cells[(r-1,c)].colour == bg {
3940                        CellCategory::InternalCornerTR
3941                    } else if cells.columns == 1 || cells[(r,c-1)].colour == bg {
3942                        CellCategory::StemTB
3943                    } else {
3944                        CellCategory::EdgeR
3945                    }
3946                } else if cells[(r-1,c)].colour == bg && cells[(r+1,c)].colour == bg {
3947                    CellCategory::StemLR
3948                } else if cells[(r,c-1)].colour == bg && cells[(r,c+1)].colour == bg {
3949                    CellCategory::StemTB
3950                } else {
3951                    CellCategory::Middle
3952                };
3953
3954            cell.cat = cat;
3955        }
3956
3957        m
3958    }
3959
3960    pub fn fill_corners_mut(&mut self, pixels: usize, colour: Colour) {
3961        if pixels > 4 {
3962            return;
3963        }
3964        let rows = self.cells.rows;
3965        let cols = self.cells.columns;
3966
3967        if pixels >= 1 {
3968            self.cells[(0,0)].colour = colour;
3969        }
3970        if pixels >= 2 {
3971            self.cells[(rows - 1, 0)].colour = colour;
3972        }
3973        if pixels >= 3 {
3974            self.cells[(0, cols - 1)].colour = colour;
3975        }
3976        if pixels >= 4 {
3977            self.cells[(rows - 1, cols - 1)].colour = colour;
3978        }
3979    }
3980
3981    pub fn pixel_position(&self, min_colour: Colour) -> Direction {
3982        if self.colour != Mixed {
3983            return Other;
3984        }
3985        let hr = self.cells.rows / 2;
3986        let hc = self.cells.columns / 2;
3987        let mut left = 0;
3988        let mut right = 0;
3989        let mut top = 0;
3990        let mut bottom = 0;
3991
3992        for ((r, c), cell) in self.cells.items() {
3993            if cell.colour == min_colour {
3994                if r == hr { left += 1; right += 1; }
3995                else if r < hr { top += 1 }
3996                else { bottom += 1 }
3997
3998                if c == hc { top += 1; bottom += 1; }
3999                else if c < hr { left += 1 }
4000                else { right += 1 }
4001            }
4002        }
4003
4004        if top == bottom && top == left && top == right {
4005            Middle 
4006        } else if top == left && bottom == right && top > bottom {
4007            UpLeft
4008        } else if bottom == left && top == right && bottom > top {
4009            DownLeft
4010        } else if bottom == right && top < bottom && left < right {
4011            DownRight
4012        } else if top == right && top > bottom && right > left {
4013            UpRight
4014        } else if top > bottom && top > left && top > right {
4015            Up
4016        } else if right > top && right > bottom && right > left {
4017            Right
4018        } else if bottom > top && bottom > left && bottom > right {
4019            Down
4020        } else {
4021            Left
4022        }
4023    }
4024
4025    pub fn chequer(&self, rows: usize, cols: usize, pred: &dyn Fn(usize, usize) -> bool, func: &dyn Fn(&Self) -> Self, blank: bool) -> Shapes {
4026        let rs = rows * self.cells.rows;
4027        let cs = cols * self.cells.columns;
4028        let mut shapes = Shapes::new_sized(rs, cs);
4029
4030        for r in (0 .. rs).step_by(self.cells.rows) {
4031            for c in (0 .. cs).step_by(self.cells.columns) {
4032                let shape = if pred(r, c) {
4033                    &func(self)
4034                } else if blank {
4035                    &self.blank()
4036                } else {
4037                    self
4038                };
4039
4040                let s = shape.to_position(r, c);
4041
4042                shapes.shapes.push(s);
4043            }
4044        }
4045
4046        shapes
4047    }
4048
4049    pub fn combined_chequer(&self, rows: usize, cols: usize, func: &dyn Fn(&Self, usize, usize) -> Self) -> Shapes {
4050        let rs = rows * self.cells.rows;
4051        let cs = cols * self.cells.columns;
4052        let mut shapes = Shapes::new_sized(rs, cs);
4053
4054        for r in (0 .. rs).step_by(self.cells.rows) {
4055            for c in (0 .. cs).step_by(self.cells.columns) {
4056                let shape = &func(self, r, c);
4057
4058                let s = shape.to_position(r, c);
4059
4060                shapes.shapes.push(s);
4061            }
4062        }
4063
4064        shapes
4065    }
4066
4067    pub fn fit_chequer(&self, rc: usize, cc: usize, rstart: usize, cstart: usize, rgap: usize, cgap: usize, rs: usize, cs: usize, func: &dyn Fn(&Self, usize, usize) -> Self) -> Shapes {
4068//println!("{rc} {cc} {rstart} {cstart} {rgap} {cgap}");
4069        let mut shapes = Shapes::new_sized(rs, cs);
4070
4071        for i in 0 .. rc {
4072            let r = rstart + i * (rgap + self.cells.rows);
4073
4074            for j in 0 .. cc {
4075                let c = cstart + j * (cgap + self.cells.columns);
4076                let shape = &func(self, r, c);
4077
4078                let s = shape.to_position(r, c);
4079
4080                shapes.shapes.push(s);
4081            }
4082        }
4083
4084        shapes
4085    }
4086
4087    pub fn invert_colour(&self) -> Self {
4088        if self.colour == Mixed {
4089            return Self::trivial();
4090        }
4091
4092        let mut shape = self.clone();
4093
4094        for cell in shape.cells.values_mut() {
4095            cell.colour = if cell.colour == Black {
4096                self.colour
4097            } else {
4098                Black
4099            };
4100        }
4101
4102        shape
4103    }
4104
4105    pub fn blank(&self) -> Self {
4106        let mut shape = self.clone();
4107
4108        for cell in shape.cells.values_mut() {
4109            cell.colour = Black;
4110        }
4111
4112        shape
4113    }
4114
4115    pub fn copy(&self, other: &Self) -> Self {
4116        self.copy_not_colour(other, Black)
4117    }
4118
4119    // Must be compatable
4120    pub fn copy_not_colour(&self, other: &Self, nc: Colour) -> Self {
4121        let (g, mut shape) = if self.size() <= other.size() {
4122            (self, other.clone())
4123        } else {
4124            (other, self.clone())
4125        };
4126
4127        for row in 0 .. g.cells.rows {
4128            for col in 0 .. g.cells.columns {
4129
4130                if g.cells[(row, col)].colour != nc {
4131                    shape.cells[(row, col)].row = g.cells[(row, col)].row;
4132                    shape.cells[(row, col)].col = g.cells[(row, col)].col;
4133                    shape.cells[(row, col)].colour = g.cells[(row, col)].colour;
4134                }
4135            }
4136        }
4137
4138        shape
4139    }
4140
4141    pub fn get_joined(&self) -> Shapes {
4142        let mut shape = self.clone();
4143
4144        for ((r, c), cell) in self.cells.items() {
4145            // Must be internal
4146            if cell.colour != Black && r != 0 && c != 0 && r != self.cells.rows - 1 && c != self.cells.columns - 1 {
4147                if self.cells[(r+1,c)].colour == Black && self.cells[(r-1,c)].colour == Black || self.cells[(r,c+1)].colour == Black && self.cells[(r,c-1)].colour == Black {
4148                    shape.cells[(r,c)].colour = Black;
4149                };
4150            }
4151        }
4152
4153        shape.to_shapes()
4154    }
4155
4156    pub fn fill_centre_mut(&mut self, colour: Colour) {
4157        for r in 0 .. self.cells.rows {
4158            for c in 0 .. self.cells.columns {
4159                if r != 0 && c != 0 && r != self.cells.rows - 1 && c != self.cells.columns - 1 {
4160                    self.cells[(r,c)].colour = colour;
4161                }
4162            }
4163        }
4164    }
4165
4166    pub fn mid_pixel(&self) -> (usize, usize) {
4167        for (r, c) in self.cells.keys() {
4168            if self.cells[(r,c)].colour != Black && r != 0 && c != 0 && r != self.cells.rows - 1 && c != self.cells.columns - 1 && self.cells[(r-1,c)].colour != Black && self.cells[(r,c-1)].colour != Black && self.cells[(r+1,c)].colour != Black && self.cells[(r,c+1)].colour != Black {
4169                return (r, c);
4170            }
4171        }
4172
4173        return (9, 0)
4174    }
4175
4176    pub fn swap_colours(&mut self, cm: &BTreeMap<Colour, Colour>) {
4177        for cells in self.cells.values_mut() {
4178            cells.colour = cells.colour + ToBlack;
4179        }
4180
4181        for cells in self.cells.values_mut() {
4182            if let Some(colour) = cm.get(&cells.colour.to_base()) {
4183                cells.colour = *colour;
4184            }
4185        }
4186    }
4187
4188    // fix 0e671a1a
4189    pub fn adjacent_to_pixel(&self, grid: &Grid) -> Vec<Direction> {
4190        let r = self.orow;
4191        let c = self.ocol;
4192        let mut dir: Vec<Direction> = Vec::new();
4193
4194        if !self.is_pixel() || r == 0 || c == 0 || r == self.cells.rows - 1 || c == self.cells.columns - 1 {
4195            return dir;
4196        }
4197
4198        if grid.cells[(r,c)].colour != Black {
4199            if grid.cells[(r-1,c)].colour != Black { dir.push(Up) };
4200            if grid.cells[(r+1,c)].colour != Black { dir.push(Down) };
4201            if grid.cells[(r,c-1)].colour != Black { dir.push(Left) };
4202            if grid.cells[(r,c+1)].colour != Black { dir.push(Right) };
4203        }
4204
4205        dir
4206    }
4207
4208    /* Needs backtracking
4209    // first shape must be largest
4210    pub fn align(&self, other: &Self) -> Self {
4211        let mut r = other.orow;
4212        let mut c = other.ocol;
4213
4214        let mut shape = self.translate_absolute(other.orow, other.ocol);
4215
4216        shape.recolour_mut(self.colour, other.colour);
4217
4218        shape
4219    }
4220    */
4221
4222/*
4223    pub fn cell_category_bg(cells: &Matrix<Cell>, bg: Colour) -> Matrix<Cell> {
4224        let mut m = cells.clone();
4225
4226        // Special cases Single Pixel, H & V Lines
4227        if cells.rows == 1 && cells.columns == 1 {
4228            m[(0,0)].cat = Single;
4229
4230            return m;
4231        } else if cells.rows == 1 {
4232            for i in 0 .. m.columns {
4233                m[(0,i)].cat = LineTB;
4234            }
4235
4236            return m;
4237        } else if cells.columns == 1 {
4238            for i in 0 .. m.rows {
4239                m[(i,0)].cat = LineLR;
4240            }
4241
4242            return m;
4243        }
4244
4245        for ((rw, cl), c) in m.items_mut() {
4246            if c.colcheckerour == bg { continue; }
4247
4248            let lr = cells.rows - 1;
4249            let lc = cells.columns - 1;
4250
4251            let tlc = rw == 0 && cl == 0;
4252            let blc = rw == lr && cl == 0;
4253            let trc = rw == 0 && cl == lc;
4254            let brc = rw == lr && cl == lc;
4255            
4256            // Special case corners
4257            if tlc {
4258                c.cat = CornerTL;
4259                continue;
4260            } else if blc {
4261                c.cat = CornerBL;
4262                continue;
4263            } else if trc {
4264                c.cat = CornerTR;
4265                continue;
4266            } else if brc {
4267                c.cat = CornerBR;
4268                continue;
4269            }
4270
4271            // Surrounding cells
4272            let (tl, tt, tr, tb, br, bb, bl, bt) = if rw == 0 {
4273                (bg, bg, bg, cells[(rw,cl+1)].colour, cells[(rw+1,cl+1)].colour, cells[(rw+1,cl)].colour, cells[(rw+1,cl-1)].colour, cells[(rw,cl-1)].colour)
4274            } else if cl == 0 {
4275                (bg, cells[(rw-1,cl)].colour, cells[(rw-1,cl+1)].colour, cells[(rw,cl+1)].colour, cells[(rw+1,cl+1)].colour, cells[(rw+1,cl)].colour, bg, bg)
4276            } else if rw == lr {
4277                (cells[(rw-1,cl-1)].colour, cells[(rw-1,cl)].colour, cells[(rw-1,cl+1)].colour, cells[(rw,cl+1)].colour, bg, bg, bg, cells[(rw,cl-1)].colour)
4278            } else if cl == lc {
4279                (cells[(rw-1,cl-1)].colour, cells[(rw-1,cl)].colour, bg, bg, bg, cells[(rw+1,cl)].colour, cells[(rw+1,cl-1)].colour, cells[(rw,cl-1)].colour)
4280            } else {    // Somewhere inside
4281                (cells[(rw-1,cl-1)].colour, cells[(rw-1,cl)].colour, cells[(rw-1,cl+1)].colour, cells[(rw,cl+1)].colour, cells[(rw+1,cl+1)].colour, cells[(rw+1,cl)].colour, cells[(rw+1,cl-1)].colour, cells[(rw,cl-1)].colour)
4282            };
4283
4284            c.cat = if tl == bg && tt == bg && bt == bg {
4285                InternalCornerTL
4286            } else if bb == bg && bl == bg && bt == bg {
4287                InternalCornerBL
4288            } else if tt == bg && tr == bg && tb == bg {
4289                InternalCornerTR
4290            } else if tb == bg && br == bg && bb == bg {
4291                InternalCornerBR
4292                    /*
4293            } else if tl == bg && tt == bg && bt == bg {
4294                InsideCornerTL
4295            } else if bb == bg && bl == bg && bt == bg {
4296                InsideCornerBL
4297            } else if tt == bg && tr == bg && tb == bg {
4298                InsideCornerTR
4299            } else if tb == bg && br == bg && bb == bg {
4300                InsideCornerBR
4301                    */
4302            } else {
4303                Unknown
4304            };
4305
4306            /*
4307            c.cat = 
4308                if rw == 0 {            // Left Edge
4309                    match (tl, tt, tr, tb, br, bb, bl, bt) {
4310                        (false, true, _, true, _, true, false, false) => EdgeL,
4311                        (false, true, _, true, _, false, false, false) => InternalCornerBL,
4312                        (false, true, _, false, _, true, false, false) => HollowEdgeL,
4313                        (false, true, _, false, _, false, false, false) => BottomEdgeL,
4314                        (false, false, _, true, _, true, false, false) => InternalCornerTL,
4315                        (false, false, _, true, _, false, false, false) => PointL,
4316                        (false, false, _, false, _, true, false, false) => TopEdgeL,
4317                        (false, false, _, false, _, false, false, false) => SingleL,
4318                        _ => todo!(),
4319                    }
4320                } else if cl == 0 {     //Top Edge
4321                    match (tl, tt, tr, tb, br, bb, bl, bt) {
4322                        (false, false, false, true, _, true, _, true) => EdgeT,
4323                        (false, false, false, true, _, true, _, false) => InternalCornerTL,
4324                        (false, false, false, true, _, false, _, true) => HollowEdgeT,
4325                        (false, false, false, true, _, false, _, false) => LeftEdgeT,
4326                        (false, false, false, false, _, true, _, true) => InternalCornerTR,
4327                        (false, false, false, false, _, true, _, false) => PointT,
4328                        (false, false, false, false, _, false, _, true) => RightEdgeT,
4329                        (false, false, false, false, _, false, _, false) => SingleT,
4330                        _ => todo!(),
4331                    }
4332                } else {
4333                    BG
4334                };
4335            */
4336        }
4337//println!("{m:?}");
4338
4339        m
4340    }
4341*/
4342}
4343
4344#[derive(Debug, Clone, PartialEq)]
4345pub struct Shapes {
4346    pub nrows: usize,
4347    pub ncols: usize,
4348    pub colour: Colour,
4349    pub shapes: Vec<Shape>,
4350    //pub cats: BTreeSet<ShapeCategory>,
4351}
4352
4353/*
4354impl Default for Shapes {
4355    fn default() -> Self {
4356         Self::new()
4357    }
4358}
4359*/
4360
4361impl Shapes {
4362    pub fn new() -> Self {
4363        Self { nrows: 0, ncols: 0, colour: NoColour, shapes: Vec::new() }
4364    }
4365
4366    pub const fn trivial() -> Self {
4367        const SHAPES: Vec<Shape> = Vec::new();
4368
4369        Self { nrows: 0, ncols: 0, colour: NoColour, shapes: SHAPES }
4370    }
4371
4372    pub fn new_sized(nrows: usize, ncols: usize) -> Self {
4373        Self { nrows, ncols, colour: NoColour, shapes: Vec::new() }
4374    }
4375
4376    pub fn new_given(nrows: usize, ncols: usize, shapes: &Vec<Shape>) -> Self {
4377        Self { nrows, ncols, colour: Self::find_colour(shapes), shapes: shapes.to_vec() }
4378    }
4379
4380    pub fn new_from_shape(shape: &Shape) -> Self {
4381        Shapes::new_shapes(&[shape.clone()])
4382    }
4383
4384    // May be same size as source grid
4385    pub fn new_shapes(shapes: &[Shape]) -> Self {
4386        let mut new_shapes = Self::new();
4387        let mut colour = NoColour;
4388
4389        for s in shapes.iter() {
4390            new_shapes.add(s);
4391            if colour == NoColour {
4392                colour = s.colour;
4393            } else if colour != s.colour {
4394                colour = Mixed;
4395            }
4396        }
4397
4398        new_shapes.colour = colour;
4399
4400        new_shapes
4401    }
4402
4403    pub fn new_shapes_sized(nrows: usize, ncols: usize, shapes: &[Shape]) -> Self {
4404        let mut new_shapes = Self::new_sized(nrows, ncols);
4405        let mut colour = NoColour;
4406
4407        for s in shapes.iter() {
4408            new_shapes.add(s);
4409            if colour == NoColour {
4410                colour = s.colour;
4411            } else if colour != s.colour {
4412                colour = Mixed;
4413            }
4414        }
4415        new_shapes.colour = colour;
4416
4417        new_shapes
4418    }
4419
4420    pub fn clone_base(&self) -> Self {
4421        let mut this = Self::new_sized(self.nrows, self.ncols);
4422
4423        this.colour = self.colour;
4424
4425        this
4426    }
4427
4428    pub fn merge_mut(&mut self, other: &Self) {
4429        for s in &other.shapes {
4430            self.shapes.push(s.clone());
4431        }
4432    }
4433
4434    /*
4435       TODO 3490cc26
4436#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4437pub struct Pos(pub usize, pub usize);
4438pub struct Successor {
4439    pub pos: Pos,
4440    pub cost: usize,
4441}
4442impl PartialEq<(Pos, usize)> for Successor {
4443    fn eq(&self, other: &(Pos, usize)) -> bool {
4444        self.pos == other.0 && self.cost == other.1
4445    }
4446}
4447
4448    // Straight line nearest successors
4449    pub fn get_sln_successors(&self, r: usize, c: usize) -> Vec<Successor> {
4450        Vec
4451    }
4452    */
4453
4454    // Expensive : fd096ab6
4455    pub fn join_shapes_same_colour(&self) -> Self {
4456        let mut done: Vec<Shape> = Vec::new();
4457        let mut shapes = self.clone_base();
4458
4459        for s1 in &self.shapes {
4460            for s2 in &self.shapes {
4461                if s1 == s2 {
4462                    continue;
4463                }
4464                if s1.equals(&s2) == Same {
4465                    let orow = s1.orow.min(s2.orow);
4466                    let ocol = s1.ocol.min(s2.ocol);
4467                    let rdist = s1.orow.max(s2.orow) - orow;
4468                    let cdist = s1.ocol.max(s2.ocol) - ocol;
4469                    let rmax = (s1.orow + s1.cells.rows).max(s2.orow + s2.cells.rows);
4470                    let cmax = (s1.ocol + s1.cells.columns).max(s2.ocol + s2.cells.columns);
4471                    let rlen = rmax - orow;
4472                    let clen = cmax - ocol;
4473                    let mut ns = Shape::new_sized_coloured_position(orow, ocol, rlen, clen, Black);
4474
4475                    // assumes position of s1 <= s2
4476                    for ((r, c), cell) in s1.cells.items() {
4477                        if cell.colour != Black {
4478                            ns.cells[(r,c)].colour = cell.colour;
4479                        }
4480                    }
4481                    for ((r, c), cell) in s2.cells.items() {
4482                        if cell.colour != Black {
4483                            ns.cells[(r + rdist,c + cdist)].colour = cell.colour;
4484                        }
4485                    }
4486
4487                    if !done.contains(&ns) {
4488                        shapes.shapes.push(ns.clone());
4489                    }
4490                    done.push(s1.clone());
4491                    done.push(ns);
4492                    continue;
4493                }
4494            }
4495            if !done.contains(s1) {
4496                shapes.shapes.push(s1.clone());
4497            }
4498        }
4499
4500        shapes
4501    }
4502
4503    // TODO: doesn't work yet: 60a26a3e and others
4504    pub fn find_straight_pairs(&self) -> BTreeMap<Shape,Shape> {
4505        let mut ss: BTreeMap<Shape, Shape> = BTreeMap::new();
4506
4507        for s in self.shapes.iter() {
4508            let mut min_r = usize::MAX;
4509            let mut min_c = usize::MAX;
4510            let mut ns_r = Shape::trivial();
4511            let mut ns_c = Shape::trivial();
4512
4513            for si in self.shapes.iter() {
4514                if s != si {
4515                   if s.orow == si.orow {
4516                       let p = s.ocol.max(si.ocol) - s.ocol.min(si.ocol);
4517println!("Row {} => {} {} {} {}", s.orow, s.ocol, si.ocol, p, min_c);
4518
4519                       if min_c == usize::MAX || p < min_c {
4520                           if let Some(s2) = ss.get(&si) {
4521println!("##1##");
4522si.show_summary();
4523s2.show_summary();
4524println!("##1##");
4525                           }
4526                           if let Some(s2) = ss.get(&s) {
4527println!("##2##");
4528s.show_summary();
4529s2.show_summary();
4530println!("##2##");
4531                           }
4532                           min_c = p;
4533                           ns_r = si.clone();
4534                       }
4535                   }
4536                   if s.ocol == si.ocol {
4537println!("Col {} => {} {}", s.orow, s.ocol, si.ocol);
4538                       let p = s.orow.max(si.orow) - s.orow.min(si.orow);
4539
4540                       if min_r == usize::MAX || p < min_r {
4541                           min_r = p;
4542                           ns_c = si.clone();
4543                       }
4544                   }
4545                }
4546            }
4547
4548            if ns_r != Shape::trivial() {
4549                if s.orow < ns_r.orow {
4550                    ss.insert(s.clone(), ns_r);
4551                } else {
4552                    ss.insert(ns_r, s.clone());
4553                }
4554            }
4555            if ns_c != Shape::trivial() {
4556                if s.ocol < ns_c.ocol {
4557                    ss.insert(s.clone(), ns_c);
4558                } else {
4559                    ss.insert(ns_c, s.clone());
4560                }
4561            }
4562        }
4563
4564        ss
4565    }
4566
4567    pub fn group_containers(&self) -> BTreeMap<Shape, Vec<Shape>> {
4568        let mut ss: BTreeMap<Shape, Vec<Shape>> = BTreeMap::new();
4569
4570        for s in self.shapes.iter() {
4571            for si in self.shapes.iter() {
4572                if s != si && s.container(si) {
4573                   ss.entry(s.clone()).and_modify(|v| v.push(si.clone())).or_insert(vec![si.clone()]);
4574                }
4575            }
4576        }
4577
4578        ss
4579    }
4580
4581    pub fn coords_to_shape(&self) -> BTreeMap<(usize, usize), Shape> {
4582        let mut cts: BTreeMap<(usize, usize), Shape> = BTreeMap::new();
4583
4584        for s in self.shapes.iter() {
4585            cts.insert((s.orow, s.ocol), s.clone());
4586        }
4587
4588        cts
4589    }
4590
4591    pub fn centre_of(&self) -> BTreeMap<(usize, usize), Shape> {
4592        let mut ss: BTreeMap<(usize, usize), Shape> = BTreeMap::new();
4593
4594        for s in self.shapes.iter() {
4595            ss.insert(s.centre_of(), s.clone());
4596        }
4597
4598        ss
4599    }
4600
4601    pub fn border_gravity(&self) -> BTreeMap<Colour, Direction> {
4602        let mut ss: BTreeMap<Colour, Direction> = BTreeMap::new();
4603
4604        for s in self.shapes.iter() {
4605            for si in self.shapes.iter() {
4606                if s != si && s.container(si) {
4607                   if s.orow == si.orow {
4608                       ss.insert(s.colour, Up);
4609                   } else if s.ocol == si.ocol {
4610                       ss.insert(s.colour, Left);
4611                   } else if s.cells.rows == si.orow + si.cells.rows {
4612                       ss.insert(s.colour, Down);
4613                   } else if s.cells.columns == si.ocol + si.cells.columns {
4614                       ss.insert(s.colour, Right);
4615                   }
4616                }
4617            }
4618        }
4619
4620        ss
4621    }
4622
4623    pub fn in_range(&self, rc: usize, vertical: bool) -> bool {
4624        for s in self.shapes.iter() {
4625            if vertical && s.ocol <= rc && s.ocol + s.cells.columns > rc ||
4626               !vertical && s.orow <= rc && s.orow + s.cells.rows > rc {
4627                   return true;
4628            }
4629        }
4630
4631        false
4632    }
4633
4634    pub fn full_shapes(&self) -> Vec<Shape> {
4635        let mut shapes: Vec<Shape> = Vec::new();
4636
4637        for s in self.shapes.iter() {
4638            if s.is_full() {
4639                shapes.push(s.clone());
4640            }
4641        }
4642
4643        shapes
4644    }
4645
4646    pub fn full_shapes_sq(&self) -> Vec<Shape> {
4647        let mut shapes: Vec<Shape> = Vec::new();
4648
4649        for s in self.to_grid().to_shapes_sq().shapes.iter() {
4650            if s.is_full() {
4651                shapes.push(s.clone());
4652            }
4653        }
4654
4655        shapes
4656    }
4657
4658    pub fn all_shapes(&self) -> Vec<Shape> {
4659        let mut shapes: Vec<Shape> = Vec::new();
4660
4661        for s in self.shapes.iter() {
4662            shapes.push(s.clone());
4663        }
4664
4665        shapes
4666    }
4667
4668    pub fn contains_shape(&self, shape: &Shape) -> bool {
4669        for s in self.shapes.iter() {
4670            if s.equal_shape(shape) {
4671                return true;
4672            }
4673        }
4674
4675        false
4676    }
4677
4678    pub fn contains_origin(shapes: &Vec<&Shape>, r: usize, c: usize) -> bool {
4679        for s in shapes.iter() {
4680            if s.orow == r && s.ocol == c {
4681                return true;
4682            }
4683        }
4684
4685        false
4686    }
4687
4688    pub fn all_shapes_sq(&self) -> Vec<Shape> {
4689        let mut shapes: Vec<Shape> = Vec::new();
4690
4691        for s in self.to_grid().to_shapes_sq().shapes.iter() {
4692            shapes.push(s.clone());
4693        }
4694
4695        shapes
4696    }
4697
4698    pub fn shape_permutations(&self) -> Self {
4699        let mut shapes = self.clone();
4700
4701        let trans: Vec<_> = vec![Shape::mirrored_r, Shape::mirrored_c, Shape::rotated_90, Shape::rotated_180, Shape::rotated_270];
4702        for tr in trans.iter() {
4703            for s in self.shapes.iter() {
4704                let ns = &tr(s);
4705
4706                if !self.contains_shape(&ns) {
4707                    shapes.shapes.push(ns.clone());
4708                }
4709            }
4710        }
4711
4712        shapes
4713    }
4714
4715    /*
4716    pub fn chequer(&self, rs: usize, cs: usize) -> Shapes {
4717        let mut shapes = Shapes::new_sized(self.nrows * rs, self.ncols * cs);
4718
4719        let mut first = true;
4720        let mut rp = 0;
4721        let mut cp = 0;
4722
4723        for s in self.shapes.iter() {
4724            let s = s.to_position(rp, cp);
4725
4726            shapes.shapes.push(s);
4727
4728            rp = (rp + 1) % rs;
4729
4730            if !first && rp == 0  {
4731                cp = (cp + 1) % cs;
4732            }
4733            first = false;
4734        }
4735
4736        shapes
4737    }
4738    */
4739
4740    pub fn find_shape_colours(&self) -> Vec<Colour> {
4741        let mut colours = Vec::new();
4742
4743        for s in self.to_grid().to_shapes_sq().shapes.iter() {
4744            colours.push(s.colour);
4745        }
4746
4747        colours
4748    }
4749
4750    pub fn get_pixels(&self) -> Shapes {
4751        let mut shapes = self.clone_base();
4752
4753        for s in self.shapes.iter() {
4754            if s.is_pixel() {
4755                shapes.shapes.push(s.clone());
4756            }
4757        }
4758
4759        shapes
4760    }
4761
4762    pub fn is_line(&self) -> bool {
4763        if self.shapes.is_empty() {
4764            return false;
4765        }
4766        for s in self.shapes.iter() {
4767            if !s.is_line() {
4768                return false;
4769            }
4770        }
4771
4772        true
4773    }
4774
4775    pub fn has_band(&self) -> (Direction, usize) {
4776        for s in self.shapes.iter() {
4777            match s.has_band(self.nrows, self.ncols) {
4778                (Down, pos) => return (Down, pos),
4779                (Right, pos) => return (Right, pos),
4780                _ => (),
4781            }
4782        }
4783
4784        (Other, 0)
4785    }
4786
4787    pub fn is_square(&self) -> bool {
4788        if self.shapes.is_empty() {
4789            return false;
4790        }
4791        for s in self.shapes.iter() {
4792            if !s.is_square() {
4793                return false;
4794            }
4795        }
4796
4797        true
4798    }
4799
4800    pub fn is_square_same(&self) -> bool {
4801        if self.shapes.is_empty() || !self.shapes[0].is_square() || self.shapes[0].size() == 1 {
4802            return false;
4803        }
4804        let size = self.shapes[0].size();
4805
4806        for s in self.shapes.iter() {
4807            if !s.is_square() || s.size() != size {
4808                return false;
4809            }
4810        }
4811
4812        true
4813    }
4814
4815    pub fn anomalous_colour(&self) -> Option<Colour> {
4816        let h = self.colour_cnt();
4817
4818        if h.len() <= 1 {
4819            return None;
4820        }
4821
4822        if h.iter().filter(|&(_,&v)| v == 1).count() == 1 {
4823            for (k, v) in &h {
4824                if *v == 1 {
4825                    return Some(*k);
4826                }
4827            }
4828        }
4829
4830        None
4831    }
4832
4833    pub fn embellish(&self, colour: Colour) ->  Shapes {
4834        let mut shapes = self.clone();
4835
4836        for s in self.shapes.iter() {
4837            if s.is_pixel() {
4838                let ns = if s.orow == 0 && s.ocol == 0 {
4839                    let mut ns = Shape::new_sized_coloured_position(s.orow, s.ocol, 2, 2, Black);
4840                    ns.cells[(1,1)].colour = colour;
4841
4842                    ns
4843                } else if s.orow == 0 {
4844                    let mut ns = Shape::new_sized_coloured_position(s.orow, s.ocol - 1, 2, 3, Black);
4845                    ns.cells[(1,0)].colour = colour;
4846                    ns.cells[(1,2)].colour = colour;
4847
4848                    ns
4849                } else if s.ocol == 0 {
4850                    let mut ns = Shape::new_sized_coloured_position(s.orow - 1, s.ocol, 3, 2, Black);
4851                    ns.cells[(0,1)].colour = colour;
4852                    ns.cells[(2,1)].colour = colour;
4853
4854                    ns
4855                } else {
4856                    let mut ns = Shape::new_sized_coloured_position(s.orow - 1, s.ocol - 1, 3, 3, Black);
4857                    ns.cells[(0,0)].colour = colour;
4858                    ns.cells[(0,2)].colour = colour;
4859                    ns.cells[(2,0)].colour = colour;
4860                    ns.cells[(2,2)].colour = colour;
4861
4862                    ns
4863                };
4864
4865                shapes.shapes.push(ns);
4866//            } else {
4867//                shapes.shapes.push(s.clone());
4868            }
4869        }
4870
4871        shapes
4872    }
4873
4874    pub fn colours(&self) -> Vec<Colour> {
4875        self.shapes.iter().map(|s| s.colour).collect()
4876    }
4877
4878    pub fn find_repeats(&self) -> (usize, usize) {
4879        let r: BTreeSet<usize> = self.shapes.iter().map(|s| s.orow).collect();
4880        let c: BTreeSet<usize> = self.shapes.iter().map(|s| s.ocol).collect();
4881
4882        (r.len(), c.len())
4883    }
4884
4885    pub fn find_gaps(&self) -> (usize, usize) {
4886        let r: BTreeSet<usize> = self.shapes.iter().map(|s| s.orow).collect();
4887        let c: BTreeSet<usize> = self.shapes.iter().map(|s| s.ocol).collect();
4888
4889        let r: Vec<_> = r.iter().map(|i| i).collect();
4890        let c: Vec<_> = c.iter().map(|i| i).collect();
4891
4892        if r.len() < 2 || c.len() < 2 || r[1] - r[0] < 2 || c[1] - c[0] < 2 || r[1] - r[0] < self.shapes[0].cells.rows || c[1] - c[0] < self.shapes[0].cells.columns {
4893            return (0, 0);
4894        }
4895
4896        (r[1] - r[0] - self.shapes[0].cells.rows, c[1] - c[0] - self.shapes[0].cells.columns)
4897    }
4898
4899    // TODO: share code
4900    pub fn anomalous_size(&self) -> Option<usize> {
4901        let h = self.size_cnt();
4902
4903        if h.len() <= 1 {
4904            return None;
4905        }
4906
4907        if h.iter().filter(|&(_,&v)| v == 1).count() == 1 {
4908            for (k, v) in &h {
4909                if *v == 1 {
4910                    return Some(*k);
4911                }
4912            }
4913        }
4914
4915        None
4916    }
4917
4918    pub fn colour_groups_to_shapes(&self, bg: Colour) -> Shapes {
4919        let mut h: BTreeMap<Colour, Vec<Shape>> = BTreeMap::new();
4920
4921        for shape in self.shapes.iter() {
4922            if shape.is_pixel() {
4923                h.entry(shape.colour).or_default().push(shape.clone());
4924            }
4925        }
4926
4927        let mut max_r = 0;
4928        let mut max_c = 0;
4929
4930        for (_, v) in h.iter() {
4931            let mut smin_r = usize::MAX;
4932            let mut smax_r = 0;
4933            let mut smin_c = usize::MAX;
4934            let mut smax_c = 0;
4935
4936            for s in v.iter() {
4937                smin_r = smin_r.min(s.orow);
4938                smax_r = smax_r.max(s.orow + s.cells.rows - 1);
4939                smin_c = smin_c.min(s.ocol);
4940                smax_c = smax_c.max(s.ocol + s.cells.columns - 1);
4941            }
4942            max_r = max_r.max(smax_r - smin_r);
4943            max_c = max_c.max(smax_c - smin_c);
4944        }
4945
4946        let mut ss = Self::new_sized(max_r + 1, max_c + 1);
4947//println!("{} {}", max_r + 1, max_c + 1);
4948
4949        ss.shapes.push(Shape::new_sized_coloured(max_r + 1, max_c + 1, bg));
4950
4951        for (_, v) in h.iter() {
4952//println!("--- {k:?}");
4953            let mut orow = usize::MAX;
4954            let mut ocol = usize::MAX;
4955            let mut smax_r = 0;
4956            let mut smax_c = 0;
4957
4958            for s in v.iter() {
4959                orow = orow.min(s.orow);
4960                ocol = ocol.min(s.ocol);
4961                smax_r = smax_r.max(s.orow);
4962                smax_c = smax_c.max(s.ocol);
4963            }
4964
4965            for s in v.iter() {
4966                let r = (max_r - (smax_r - orow)) / 2;
4967                let c = (max_c - (smax_c - ocol)) / 2;
4968                let s = s.to_position(s.orow - orow + r, s.ocol - ocol + c);
4969
4970                ss.shapes.push(s)
4971            }
4972        }
4973
4974        ss
4975    }
4976
4977    pub fn colour_cnt(&self) -> BTreeMap<Colour, usize> {
4978        let mut h: BTreeMap<Colour, usize> = BTreeMap::new();
4979
4980        for s in self.shapes.iter() {
4981            *h.entry(s.colour).or_insert(0) += 1;
4982        }
4983
4984        h
4985    }
4986
4987    pub fn cell_colour_cnt(&self) -> BTreeMap<Colour, usize> {
4988        let mut h: BTreeMap<Colour, usize> = BTreeMap::new();
4989
4990        for s in self.shapes.iter() {
4991            for c in s.cells.values() {
4992                *h.entry(c.colour).or_insert(0) += 1;
4993            }
4994        }
4995
4996        h
4997    }
4998
4999    pub fn size_cnt(&self) -> BTreeMap<usize, usize> {
5000        let mut h: BTreeMap<usize, usize> = BTreeMap::new();
5001
5002        for s in self.shapes.iter() {
5003            *h.entry(s.size()).or_insert(0) += 1;
5004        }
5005
5006        h
5007    }
5008
5009    pub fn nearest_shape(&self, r: usize, c: usize) -> Shape {
5010        let mut dist = f32::MAX;
5011        let mut shape = Shape::trivial();
5012
5013        for s in self.shapes.iter() {
5014            let (cr, cc) = s.centre_of_exact();
5015            let r2_dist = ((cr - r as f32).powi(2) + (cc - c as f32).powi(2)).sqrt();
5016
5017            if shape == Shape::trivial() {
5018                shape = s.clone();
5019                dist = r2_dist;
5020            } else {
5021                if r2_dist < dist {
5022                    shape = s.clone();
5023                    dist = r2_dist;
5024                }
5025            }
5026        }
5027
5028        shape
5029    }
5030
5031    pub fn full_extent(&self) -> Shape {
5032        for s in self.shapes.iter() {
5033            if s.orow == 0 && s.cells.rows == self.nrows || s.ocol == 0 && s.cells.columns == self.ncols {
5034//s.show();
5035                return s.clone();
5036            }
5037        }
5038
5039        Shape::trivial()
5040    }
5041
5042    pub fn all_corners(&self) -> Vec<(usize, usize)> {
5043        let (tlr, tlc, brr, brc) = self.corners();
5044
5045        vec![(tlr, tlc), (tlr, brc), (brr, brc), (brr, tlc)]
5046    }
5047
5048    pub fn vec_corners(shapes: &Vec<Shape>) -> (usize, usize, usize, usize) {
5049        let mut min_r = usize::MAX;
5050        let mut min_c = usize::MAX;
5051        let mut max_r = 0;
5052        let mut max_c = 0;
5053
5054        for s in shapes.iter() {
5055            if min_r > s.orow {
5056                min_r = s.orow;
5057            }
5058            if min_c > s.ocol {
5059                min_c = s.ocol;
5060            }
5061            if max_r < s.orow + s.cells.rows {
5062                max_r = s.orow + s.cells.rows;
5063            }
5064            if max_c < s.ocol + s.cells.columns {
5065                max_c = s.ocol + s.cells.columns;
5066            }
5067        }
5068
5069        if min_r == usize::MAX {
5070            min_r = 0;
5071        }
5072        if min_c == usize::MAX {
5073            min_c = 0;
5074        }
5075
5076        (min_r, min_c, max_r, max_c)
5077    }
5078
5079    pub fn corners(&self) -> (usize, usize, usize, usize) {
5080        Shapes::vec_corners(&self.shapes)
5081    }
5082
5083    pub fn origins(shapes: &Vec<&Shape>) -> Vec<(usize, usize)> {
5084        let mut rvec: Vec<usize> = Vec::new();
5085        let mut cvec: Vec<usize> = Vec::new();
5086
5087        for s in shapes.iter() {
5088            rvec.push(s.orow);
5089            cvec.push(s.ocol);
5090        }
5091
5092        rvec.sort();
5093        rvec = rvec.unique();
5094        cvec.sort();
5095        cvec = cvec.unique();
5096
5097        if rvec.len() != 2 || cvec.len() != 2 {
5098            return Vec::new();
5099        }
5100
5101        // Clockwise origins
5102        vec![(rvec[0], cvec[0]), (rvec[0], cvec[1]), (rvec[1], cvec[1]), (rvec[1], cvec[0])]
5103    }
5104
5105    pub fn to_shape(&self) -> Shape {
5106        let (min_r, min_c, max_r, max_c) = self.corners();
5107
5108        let mut shape = Shape::new_sized_coloured_position(min_r, min_c, max_r - min_r, max_c - min_c, Black);
5109
5110        shape.colour = Mixed;
5111        shape.orow = min_r;
5112        shape.ocol = min_c;
5113
5114        for s in self.shapes.iter() {
5115            for c in s.cells.values() {
5116                shape.cells[(c.row - min_r, c.col - min_c)].row = c.row;
5117                shape.cells[(c.row - min_r, c.col - min_c)].col = c.col;
5118                shape.cells[(c.row - min_r, c.col - min_c)].colour = c.colour;
5119            }
5120        }
5121
5122        shape
5123    }
5124
5125    pub fn border_only(&self) -> Shape {
5126        let mut shape = Shape::trivial();
5127
5128        for s in self.shapes.iter() {
5129            if s.has_border() {
5130                shape = s.clone();
5131
5132                break;
5133            }
5134        }
5135
5136        shape
5137    }
5138
5139    pub fn all(&self) -> Vec<Shape> {
5140        self.shapes.clone()
5141    }
5142
5143    pub fn smallest(&self) -> Shape {
5144        let mut shape = Shape::trivial();
5145
5146        for s in self.shapes.iter() {
5147            if shape.size() == 0 || s.size() <= shape.size() {
5148                shape = s.clone();
5149            }
5150        }
5151
5152        shape
5153    }
5154
5155    pub fn largest(&self) -> Shape {
5156        let mut shape = Shape::trivial();
5157
5158        for s in self.shapes.iter() {
5159            if s.size() >= shape.size() {
5160                shape = s.clone();
5161            }
5162        }
5163
5164        shape
5165    }
5166
5167    pub fn largest_solid(&self) -> Shape {
5168        let mut shape = Shape::trivial();
5169
5170        for s in self.shapes.iter() {
5171            if s.size() >= shape.size() && s.size() == s.pixels() {
5172                shape = s.clone();
5173            }
5174        }
5175
5176        shape
5177    }
5178
5179    pub fn largest_solid_colour(&self, colour: Colour) -> Shape {
5180        let mut shape = Shape::trivial();
5181
5182        for s in self.shapes.iter() {
5183            if s.size() >= shape.size() && s.size() == s.pixels() && s.colour == colour {
5184                shape = s.clone();
5185            }
5186        }
5187
5188        shape
5189    }
5190
5191    pub fn hollow_cnt_colour_map(&self) -> BTreeMap<usize, Colour> {
5192        let mut h: BTreeMap<usize, Colour> = BTreeMap::new();
5193
5194        for s in &self.shapes {
5195            let (colour, n) = s.hollow_colour_count();
5196
5197            h.insert(n, colour);
5198        }
5199
5200        h
5201    }
5202
5203    pub fn hollow_cnt_max(&self) -> Shape {
5204        let mut shape = Shape::trivial();
5205        let mut n = 0;
5206
5207        for s in &self.shapes {
5208            let (_, cnt) = s.hollow_colour_count();
5209
5210            if cnt > n {
5211                n = cnt;
5212                shape = s.clone();
5213            }
5214        }
5215
5216        shape
5217    }
5218
5219    pub fn hollow_cnt_min(&self) -> Shape {
5220        let mut shape = Shape::trivial();
5221        let mut n = usize::MAX;
5222
5223        for s in &self.shapes {
5224            let (_, cnt) = s.hollow_colour_count();
5225
5226            if cnt < n {
5227                n = cnt;
5228                shape = s.clone();
5229            }
5230        }
5231
5232        shape
5233    }
5234
5235    pub fn hollow_cnt_map(&self) -> BTreeMap<usize, Vec<Shape>> {
5236        let mut h: BTreeMap<usize, Vec<Shape>> = BTreeMap::new();
5237
5238        for s in self.shapes.iter() {
5239            let (_, cnt) = s.hollow_colour_count();
5240
5241            h.entry(cnt).or_default().push(s.clone());
5242        }
5243
5244        h
5245    }
5246
5247    pub fn hollow_cnt_unique(&self) -> Shape {
5248        let mut shape = Shape::trivial();
5249        let h = self.hollow_cnt_map();
5250
5251        for sv in h.values() {
5252            if sv.len() == 1 {
5253                shape = sv[0].clone();
5254                break;
5255            }
5256        }
5257
5258        shape
5259    }
5260
5261    pub fn first(&self) -> Shape {
5262        if self.shapes.is_empty() {
5263            return Shape::trivial();
5264        }
5265
5266        self.shapes[0].clone()
5267    }
5268
5269    pub fn last(&self) -> Shape {
5270        if self.shapes.is_empty() {
5271            return Shape::trivial();
5272        }
5273
5274        self.shapes[self.shapes.len() - 1].clone()
5275    }
5276
5277    pub fn shape_colour_cnt_map(&self) -> BTreeMap<Colour, Vec<Shape>>  {
5278        let mut h: BTreeMap<Colour, Vec<Shape>> = BTreeMap::new();
5279
5280        for s in self.shapes.iter() {
5281            h.entry(s.colour).or_default().push(s.clone());
5282        }
5283
5284        h
5285    }
5286
5287    /*
5288    pub fn shape_colour_cnt_min(&self) -> Colour {
5289        let scm = self.shape_colour_cnt_map();
5290
5291        let m = scm.iter().min_by_key(|(_, v)| v.len());
5292println!("{m:?}");
5293
5294        NoColour
5295    }
5296    */
5297
5298    pub fn pixels_in_shapes(&self, shape: &Shape) -> Vec<Shape> {
5299        let mut shapes: Vec<Shape> = Vec::new();
5300        let pixels: Vec<&Shape> = self.shapes.iter()
5301            .filter(|s| s.is_pixel())
5302            .collect();
5303            
5304        if pixels.is_empty() {
5305            return shapes;
5306        }
5307
5308
5309        for pix in pixels.into_iter() {
5310            if pix.contained_by(&shape) {
5311                shapes.push(pix.clone());
5312            }
5313        }
5314
5315        shapes
5316    }
5317
5318    fn overlay_shapes(&self, same: bool) -> bool {
5319        for so in self.shapes.iter() {
5320            if so.size() <= 4 {
5321                continue;
5322            }
5323            for si in self.shapes.iter() {
5324                if si.size() >= so.size() {
5325                    continue;
5326                }
5327                if so.can_contain(si) && si.cells.rows < so.cells.rows && si.cells.columns < so.cells.columns && (same && si.colour == so.colour || !same && si.colour != so.colour) {
5328                    return true;
5329                }
5330            }
5331        }
5332
5333        false
5334    }
5335
5336    pub fn overlay_shapes_same_colour(&self) -> bool {
5337        self.overlay_shapes(true)
5338    }
5339
5340    pub fn overlay_shapes_diff_colour(&self) -> bool {
5341        self.overlay_shapes(false)
5342    }
5343
5344    // Alternative to patch_shapes
5345    pub fn consolidate_shapes(&self) -> Self {
5346        let mut shapes = self.clone();
5347        let mut removals: Vec<Shape> = Vec::new();
5348
5349        for so in shapes.shapes.iter_mut() {
5350            if so.size() <= 4 {
5351                continue;
5352            }
5353            for si in self.shapes.iter() {
5354                if so.can_contain(si) && si.cells.rows < so.cells.rows && si.cells.columns < so.cells.columns && si.colour == so.colour {
5355                    for (rc, c) in si.cells.items() {
5356                        let nrows = si.cells[rc].row;
5357                        let ncols = si.cells[rc].col;
5358
5359                        so.cells[(nrows - so.orow, ncols - so.ocol)].colour = c.colour;
5360                    }
5361                    removals.push(si.clone());
5362                }
5363            }
5364        }
5365
5366        // Now get rid of the small fry
5367        for s in removals.iter() {
5368            shapes.remove(s);
5369        }
5370//shapes.show();
5371
5372        shapes
5373    }
5374
5375    pub fn find_pixels(&self) -> Self {
5376        let mut pixels = Self::new_sized(self.nrows, self.ncols);
5377        let mut colour = NoColour;
5378
5379        for s in self.shapes.iter() {
5380            if s.is_pixel() {
5381                pixels.shapes.push(s.clone());
5382
5383                if colour == NoColour {
5384                    colour = s.colour;
5385                } else if colour != s.colour {
5386                    colour = Mixed;
5387                }
5388            }
5389        }
5390
5391        pixels.colour = colour;
5392
5393        pixels
5394    }
5395
5396    pub fn find_shapes(&self) -> Self {
5397        let mut shapes = Self::new_sized(self.nrows, self.ncols);
5398        let mut colour = NoColour;
5399
5400        for s in self.shapes.iter() {
5401            if !s.is_pixel() {
5402                shapes.shapes.push(s.clone());
5403
5404                if colour == NoColour {
5405                    colour = s.colour;
5406                } else if colour != s.colour {
5407                    colour = Mixed;
5408                }
5409            }
5410        }
5411
5412        shapes.colour = colour;
5413
5414        shapes
5415    }
5416
5417    pub fn size(&self) -> usize {
5418        self.nrows * self.ncols
5419    }
5420
5421    pub fn width(&self) -> usize {
5422        self.ncols
5423    }
5424
5425    pub fn height(&self) -> usize {
5426        self.nrows
5427    }
5428
5429    pub fn find_by_colour(&self, colour: Colour) -> Shape {
5430        for s in self.shapes.iter() {
5431            if s.colour == colour {
5432                return s.clone();
5433            }
5434        }
5435
5436        Shape::trivial()
5437    }
5438
5439    fn find_colour(shapes: &Vec<Shape>) -> Colour {
5440        let mut colour = NoColour;
5441
5442        for s in shapes {
5443            if s.colour != Black {
5444                if colour == NoColour {
5445                    colour = s.colour;
5446                } else if colour != s.colour {
5447                    colour = Mixed;
5448                    break;
5449                }
5450            }
5451        }
5452
5453        colour
5454    }
5455
5456    fn find_min_max(&self, min: bool) -> Shape {
5457        let mut ho: BTreeMap<Shape, usize> = BTreeMap::new();
5458        let mut hs: BTreeMap<Shape, Shape> = BTreeMap::new();
5459
5460        for s in &self.shapes {
5461            let os = s.to_origin();
5462            *ho.entry(os.clone()).or_insert(0) += 1;
5463            hs.insert(s.clone(), os);
5464        }
5465
5466        let mut shape = Shape::trivial();
5467        let mut n = if min { usize::MAX } else { 0 };
5468
5469        for (s, os) in hs {
5470            let c = if let Some(c) = ho.get(&os) {
5471                c
5472            } else {
5473                &if min { usize::MAX } else { 0 }
5474            };
5475            // Poor assumption that last is best?
5476            if (min && *c <= n) || (!min && *c >= n) {
5477                n = *c;
5478                shape = s;
5479            }
5480        }
5481
5482        shape
5483    }
5484
5485    pub fn find_min(&self) -> Shape {
5486        self.find_min_max(true)
5487    }
5488
5489    pub fn find_max(&self) -> Shape {
5490        self.find_min_max(false)
5491    }
5492
5493    fn find_sub_min_max(&self, min: bool) -> Shape {
5494        let mut h: BTreeMap<Shape, usize> = BTreeMap::new();
5495
5496        for s in &self.shapes {
5497            let ss = s.to_grid().to_shapes_sq();
5498
5499            *h.entry(s.clone()).or_insert(0) += ss.shapes.len();
5500        }
5501
5502        let mut n = if min { usize::MAX } else { 0 };
5503        let mut shape = Shape::trivial();
5504
5505        for (k, v) in h.iter() {
5506            if (min && *v <= n) || (!min && *v >= n) {
5507                n = *v;
5508                shape = k.clone();
5509            }
5510        }
5511
5512        shape
5513    }
5514
5515    pub fn find_sub_min(&self) -> Shape {
5516        self.find_sub_min_max(true)
5517    }
5518
5519    pub fn find_sub_max(&self) -> Shape {
5520        self.find_sub_min_max(false)
5521    }
5522
5523    pub fn find_pixels_min(&self) -> Shape {
5524        let mut shape = Shape::trivial();
5525        let mut pixels = usize::MAX;
5526
5527        for s in self.shapes.iter() {
5528            if s.pixels() < pixels {
5529                pixels = s.pixels();
5530                shape = s.clone();
5531            }
5532        }
5533
5534        shape
5535    }
5536
5537    pub fn find_pixels_max(&self) -> Shape {
5538        let mut shape = Shape::trivial();
5539        let mut pixels = 0;
5540
5541        for s in self.shapes.iter() {
5542            if s.pixels() > pixels {
5543                pixels = s.pixels();
5544                shape = s.clone();
5545            }
5546        }
5547
5548        shape
5549    }
5550
5551    pub fn find_max_colour_count(&self) -> Shape {
5552        let mut choice = &Shape::trivial();
5553        let mut n = 0;
5554        
5555        for s in &self.shapes {
5556            let cnt = s.distinct_colour_cnt();
5557
5558            if cnt > n {
5559                choice = s;
5560                n = cnt;
5561            }
5562        }
5563
5564        choice.clone()
5565    }
5566
5567    pub fn find_sub_largest_count(&self) -> Shape {
5568        let mut choice = &Shape::trivial();
5569        let mut biggest = 0;
5570        
5571        for s in &self.shapes {
5572            if s.size() > 1 {
5573                let ss = s.to_grid().to_shapes_sq();
5574                let mut sh: BTreeMap<Shape, usize> = BTreeMap::new();
5575
5576                for i in &ss.shapes  {
5577                    if i.size() > 1 && i.size() != s.size() {
5578                        let ni = i.to_origin();
5579                        *sh.entry(ni).or_insert(0) += 1;
5580                    }
5581                }
5582
5583                if let Some(mr) = sh.values().max() {
5584                    if *mr > biggest {
5585                        biggest = *mr;
5586                        choice = s;
5587                    }
5588                }
5589            }
5590        }
5591
5592        choice.clone()
5593    }
5594
5595    pub fn position_pixels(&self) -> Option<(Self, Self)> {
5596        let mut rp = usize::MAX;
5597        let mut cp = usize::MAX;
5598        let mut cellp = NoColour;
5599        let mut rgap = 0;
5600        let mut cgap = 0;
5601        let mut pos: Vec<Shape> = Vec::new();
5602        let mut shapes: Vec<Shape> = Vec::new();
5603
5604        for s in &self.shapes {
5605            if s.size() == 1 {
5606                if rp == usize::MAX {
5607                    rp = s.orow;
5608                    cp = s.ocol;
5609                    cellp = s.colour;
5610
5611                    let cell = Cell::new_colour(s.orow, s.ocol, cellp);
5612                    let cells = Matrix::new(1, 1, cell);
5613                    pos.push(Shape::new(s.orow, s.ocol, &cells));
5614                } else if s.colour == cellp {
5615                    if cp == s.ocol && s.orow > rp {
5616                        if rgap == 0 {
5617                            rgap = s.orow - rp;
5618                        } else if (s.orow - rp) % rgap != 0 {
5619                            return None;
5620                        }
5621                    }
5622                    if rp == s.orow && s.ocol > cp {
5623                        if cgap == 0 {
5624                            cgap = s.ocol - cp;
5625                        } else if (s.ocol - cp) % cgap != 0 {
5626                            return None;
5627                        }
5628                    }
5629
5630                    // needs to be a square, so equal gaps
5631                    if rgap > 0 && rgap != cgap {
5632                        return None;
5633                    }
5634
5635                    let cell = Cell::new_colour(s.orow, s.ocol, cellp);
5636                    let cells = Matrix::new(1, 1, cell);
5637                    pos.push(Shape::new(s.orow, s.ocol, &cells));
5638
5639                    // Add extra to right?
5640                    /*
5641                    if s.oy + ygap > s.cells.columns {
5642                        let cell = Cell::new_colour(s.ox, s.oy + ygap, cp);
5643                        let cells = Matrix::new(1, 1, cell);
5644                        pos.push(Shape::new(s.ox, s.oy + ygap, &cells));
5645                    }
5646                    */
5647                }
5648            } else {
5649                shapes.push(s.clone());
5650            }
5651        }
5652
5653        Some((Shapes::new_shapes_sized(self.nrows, self.ncols, &pos),
5654             Shapes::new_shapes_sized(self.nrows, self.ncols, &shapes)))
5655    }
5656
5657    /*
5658    pub fn position_centres(&self, positions: &Self) -> Self {
5659        //if positions.shapes.is_empty() || self.shapes[0].cells.rows <= 1 || (self.shapes[0].cells.rows > 1 && self.shapes[0].cells.rows != self.shapes[0].cells.columns) {
5660        if positions.shapes.is_empty() || self.shapes[0].cells.rows <= 1 || self.shapes[0].cells.rows != self.shapes[0].cells.columns {
5661            return Self::new();
5662        }
5663        let gap = positions.shapes[1].ocol as isize - positions.shapes[0].ocol as isize;
5664        if gap <= self.shapes[0].cells.rows as isize {
5665            return Self::new();
5666        }
5667        let offset = if gap % 2 == 0 {
5668            gap as usize - self.shapes[0].cells.rows
5669        } else {
5670            gap as usize - self.shapes[0].cells.rows - 1
5671        };
5672        let mut nps = self.clone();
5673
5674        for s in nps.shapes.iter_mut() {
5675            let p = s.nearest(positions);
5676            let roffset = if p.orow >= s.orow { offset } else { offset - 1 };
5677            let coffset = if p.ocol >= s.ocol { offset } else { offset - 1 };
5678
5679            *s = s.translate_absolute(p.orow + roffset, p.ocol + coffset);
5680        }
5681        for s in positions.shapes.iter() {
5682            nps.shapes.push(s.clone());
5683        }
5684
5685//nps.to_grid().show();
5686        nps
5687    }
5688
5689    pub fn categorise {
5690        self.categorise_shapes();
5691        categorise_io_edges(in_shapes: &mut Shapes, out_shapes: &Shapes) {
5692        self.categorise_shape_edges();
5693    }
5694    */
5695
5696    pub fn contained_pairs(&self) -> BTreeMap<Shape, Shape> {
5697        let mut pairs: BTreeMap<Shape, Shape> = BTreeMap::new();
5698
5699        for s1 in self.shapes.iter() {
5700            for s2 in self.shapes.iter() {
5701                if s1.contained_by(s2) {
5702                    pairs.insert(s2.clone(), s1.clone());
5703
5704                    break;
5705                }
5706            }
5707        }
5708
5709        pairs
5710    }
5711
5712    pub fn pair_shapes(&self, other: &Shapes, match_colour: bool) -> Vec<(Shape, Shape, bool)> {
5713        let mut pairs: Vec<(Shape, Shape, bool)> = Vec::new();
5714
5715        if self.shapes.len() != other.shapes.len() {
5716            return pairs;
5717        }
5718
5719//println!(">>> {:?} {:?}", self.cats, other.cats);
5720        let mut si = self.clone();
5721        if match_colour {
5722            si.shapes.sort_by(|a, b| (a.colour, a.orow, a.ocol, &a.to_json()).cmp(&(b.colour, b.orow, b.ocol, &b.to_json())));
5723        } else {
5724            si.shapes.sort();
5725        }
5726        let mut so = other.clone();
5727        if match_colour {
5728            //so.shapes.sort_by(|a, b| a.colour.cmp(&b.colour));
5729            so.shapes.sort_by(|a, b| (a.colour, a.orow, a.ocol, &a.to_json()).cmp(&(b.colour, b.orow, b.ocol, &b.to_json())));
5730        } else {
5731            so.shapes.sort();
5732        }
5733//so.categorise_shapes();
5734//println!("<<< {:?}", so.cats);
5735
5736        //for (si, so) in self.shapes.iter().zip(other.shapes.iter()) {
5737        for (si, so) in si.shapes.iter().zip(so.shapes.iter()) {
5738            let si_sid = Shape::sid(&si.cells, match_colour);
5739            let so_sid = Shape::sid(&so.cells, match_colour);
5740//println!(">>> {:?} {:?}", si.cats, so.cats);
5741
5742            pairs.push((si.clone(), so.clone(), si_sid == so_sid));
5743        }
5744
5745        pairs
5746    }
5747
5748    pub fn toddle_colours(&self) -> Self {
5749        let mut shapes = self.clone();
5750
5751        for s in shapes.shapes.iter_mut() {
5752            let mut h = s.cell_colour_cnt_map();
5753
5754            if h.len() != 2 {
5755                return Self::new();
5756            }
5757
5758            // Should never panic as preconditions satisfied
5759            let Some((lc, _)) = h.pop_first() else { todo!() };
5760            let Some((rc, _)) = h.pop_first() else { todo!() };
5761//println!("{l:?}, {r:?}");
5762
5763            for ((r, c), cell) in s.clone().cells.items() {
5764                if cell.colour == lc {
5765                    s.cells[(r,c)].colour = rc;
5766                } else {
5767                    s.cells[(r,c)].colour = lc;
5768                }
5769            }
5770        }
5771
5772        shapes
5773    }
5774
5775    pub fn min_size(&self, sz: usize) -> (usize, usize) {
5776        let mut mr = usize::MAX;
5777        let mut mc = usize::MAX;
5778
5779        for s in self.shapes.iter() {
5780            if s.size() > sz {
5781                mr = mr.min(s.height());
5782                mc = mc.min(s.width());
5783            }
5784        }
5785
5786        (mr, mc)
5787    }
5788
5789    pub fn split_size(&self, sz: usize) -> Self {
5790        let (mr, mc) = self.min_size(sz);
5791        let mut shapes = self.clone_base();
5792
5793        for s in self.shapes.iter() {
5794            if s.size() > sz && s.cells.rows >= mr && s.cells.columns >= mc  {
5795                if s.height() > mr * 2 {
5796                    for i in (0 .. s.height() + 1).step_by(mr + 1) {
5797                        if i + mr < s.height() { 
5798                            let ss = s.subshape_trim(i, mr + 1, 0, mc + 1);
5799//ss.show();
5800                            shapes.shapes.push(ss);
5801                        }
5802                    }
5803                } else if s.width() > mc * 2 {
5804                    for i in (0 .. s.width() + 1).step_by(mc + 1) {
5805                        if i + mc < s.width() {
5806                            let ss = s.subshape_trim(0, mr + 1, i, mc + 1);
5807//ss.show();
5808                            shapes.shapes.push(ss);
5809                        }
5810                    }
5811                } else {
5812                    shapes.shapes.push(s.clone());
5813                }
5814            }
5815        }
5816
5817        shapes
5818    }
5819
5820    pub fn majority_cell(&self) -> Shape {
5821
5822        if self.shapes.len() < 2 {
5823            return Shape::trivial();
5824        }
5825
5826        let mut shape = self.shapes[0].to_origin();
5827        let mut cnts: BTreeMap<Colour, usize> = BTreeMap::new();
5828
5829        for r in 0 .. shape.cells.rows {
5830            for c in 0 .. shape.cells.columns {
5831                for s in self.shapes.iter() {
5832                    if s.cells.rows <= r || s.cells.columns <= c {
5833                        return Shape::trivial();
5834                    }
5835
5836                    *cnts.entry(s.cells[(r,c)].colour).or_insert(0) += 1;
5837                }
5838
5839                let mx = cnts.iter().map(|(k,v)| (v, k)).max();
5840
5841                if let Some((_, colour)) = mx {
5842                    shape.cells[(r,c)].colour = *colour;
5843                }
5844
5845                cnts.clear();
5846            }
5847        }
5848
5849        shape
5850    }
5851
5852    pub fn ignore_pixels(&self) -> Self {
5853        let mut ss = self.clone_base();
5854
5855        for s in &self.shapes {
5856            if s.size() > 1 {
5857                ss.shapes.push(s.clone());
5858            }
5859        }
5860
5861        ss
5862    }
5863
5864    pub fn de_subshape(&self) -> Shapes {
5865        let mut ss = self.clone_base();
5866
5867        for s in &self.shapes {
5868            s.de_subshape(&mut ss);
5869        }
5870
5871        ss
5872    }
5873
5874    pub fn diff(&self, other: &Self) -> Option<Vec<Option<Shape>>> {
5875        if self.nrows != other.nrows || self.ncols != other.ncols || self.shapes.len() != other.shapes.len() {
5876            return None;
5877        }
5878
5879        let mut diffs: Vec<Option<Shape>> = Vec::new();
5880
5881        for (s1, s2) in self.shapes.iter().zip(other.shapes.iter()) {
5882            let gdiff = s1.diff(s2);
5883            if let Some(diff) = gdiff {
5884//diff.show_full();
5885                diffs.push(Some(diff));
5886            } else {
5887                diffs.push(None);
5888            }
5889        }
5890
5891        Some(diffs)
5892    }
5893
5894    pub fn len(&self) -> usize {
5895        self.shapes.len()
5896    }
5897
5898    pub fn is_empty(&self) -> bool {
5899        self.shapes.is_empty()
5900    }
5901
5902    // resizing only works for no-overallping shapes
5903    pub fn add(&mut self, shape: &Shape) {
5904        if shape.orow + shape.cells.rows > self.nrows {
5905            self.nrows = shape.orow + shape.cells.rows;
5906        }
5907        if shape.ocol + shape.cells.columns > self.ncols {
5908            self.ncols = shape.ocol + shape.cells.columns;
5909        }
5910        /*
5911        */
5912        if self.colour == NoColour {
5913            self.colour = shape.colour;
5914        } else if self.colour != shape.colour && self.colour != Black {
5915            self.colour = Mixed;
5916        }
5917
5918        self.shapes.push(shape.clone());
5919
5920/*
5921        // Resize if necessary
5922        for s in self.shapes.iter_mut() {
5923            //let ss = s.to_origin();
5924            for c in s.cells.values() {
5925                /*
5926                if c.x - s.ox >= self.nx {
5927                    self.nx = c.x - s.ox + s.cells.rows;
5928                }
5929                if c.y - s.oy >= self.ny {
5930                    self.ny = c.y - s.oy + s.cells.columns;
5931                }
5932                */
5933                if c.x >= self.nx {
5934                    self.nx = c.x;
5935                }
5936                if c.y >= self.ny {
5937                    self.ny = c.y;
5938                }
5939            }
5940        }
5941println!("{}/{} {}/{}", shape.ox + shape.cells.rows, shape.oy + shape.cells.columns, self.nx, self.ny);
5942*/
5943    }
5944
5945    // Must be supplied with single colour shapes
5946    pub fn noise_colour(&self) -> Colour {
5947        let mut size = self.shapes.len();
5948
5949        if size < 3 || self.colour != Mixed {
5950            return Black;
5951        }
5952
5953        let mut h: BTreeMap<usize, usize> = BTreeMap::new();
5954
5955        for c in &self.shapes {
5956//c.show();
5957            //if c.colour != Mixed {
5958            //    return Black;
5959            //} else {
5960                *h.entry(Colour::to_usize(c.colour)).or_insert(0) += 1;
5961            //}
5962        }
5963
5964        //if h.len() < 8 {
5965            //return Black;
5966        //}
5967
5968        size -= h.len();
5969
5970        for (c, cnt) in h {
5971            if cnt > size {
5972                return Colour::from_usize(c);
5973            }
5974        }
5975
5976        Black
5977    }
5978
5979    // Must be supplied with single colour shapes
5980    pub fn important_shapes(&self) -> Vec<Shape> {
5981        let shapes: Vec<Shape> = Vec::new();
5982        let size = self.shapes.len();
5983
5984        if size < 3 || self.colour != Mixed {
5985            return shapes;
5986        }
5987
5988        let mut h: BTreeMap<Shape, usize> = BTreeMap::new();
5989
5990        for s in &self.shapes {
5991            *h.entry(s.clone()).or_insert(0) += 1;
5992        }
5993
5994        h.iter().filter(|&(_, &cnt)| cnt == 1).map(|(s, _)| s.clone()).collect()
5995    }
5996
5997    pub fn remove(&mut self, shape: &Shape) {
5998        let index = self.shapes.iter().position(|r| *r == *shape);
5999
6000        if let Some(index) = index {
6001            self.shapes.remove(index);
6002        }
6003    }
6004
6005    pub fn hollow_shapes(&self) -> Shapes {
6006        let mut new_shapes = Self::new_sized(self.nrows, self.ncols);
6007
6008        for s in self.shapes.iter() {
6009            if s.size() != self.size() && s.hollow() {
6010                let ss = s.recolour(Blue, Teal);
6011
6012                new_shapes.add(&ss);
6013            }
6014        }
6015
6016        new_shapes
6017    }
6018
6019    pub fn merge_replace_shapes(&self, other: &Self) -> Self {
6020        let mut new_shapes = Self::new_sized(self.nrows, self.ncols);
6021
6022        for s in self.shapes.iter() {
6023            if !other.shapes.contains(s) {
6024                new_shapes.add(s);
6025            }
6026        }
6027        for s in other.shapes.iter() {
6028            new_shapes.add(s);
6029        }
6030
6031        new_shapes
6032    }
6033
6034    pub fn show_summary(&self) {
6035        for s in &self.shapes {
6036            s.show_summary();
6037            println!();
6038        }
6039        println!("--- {} / {} ---", self.nrows, self.ncols);
6040    }
6041
6042    pub fn show(&self) {
6043        for s in &self.shapes {
6044            s.show();
6045            println!();
6046        }
6047        println!("--- {} / {} ---", self.nrows, self.ncols);
6048    }
6049
6050    pub fn show_full(&self) {
6051        for s in &self.shapes {
6052            s.show_full();
6053            println!();
6054        }
6055        println!("--- {} / {} ---", self.nrows, self.ncols);
6056    }
6057
6058    /*
6059    pub fn add_in(&mut self) -> Self {
6060        let mut holes = Self::new();
6061
6062        for s in &self.shapes {
6063            if s.is_hollow() {
6064                holes.shapes.push(s.clone());
6065            }
6066        }
6067
6068        for h in &mut holes.shapes {
6069            for s in &mut self.shapes {
6070                if h.can_contain(s) {
6071                    h.put_all_in(s);
6072                }
6073            }
6074        }
6075
6076        holes
6077    }
6078    */
6079
6080    pub fn trim_grid(&self) -> Self {
6081        let mut trimmed = self.clone_base();
6082
6083        for s in self.shapes.iter() {
6084            if s.orow + s.cells.rows > self.nrows || s.ocol + s.cells.columns > self.ncols {
6085                let r = self.nrows.min(s.orow + s.cells.rows);
6086                let c = self.ncols.min(s.ocol + s.cells.columns);
6087
6088                if r < s.orow || c < s.ocol {
6089                    return Shapes::trivial();
6090                }
6091
6092                if let Ok(mat) = s.cells.slice(0 .. r - s.orow, 0 .. c - s.ocol) {
6093                    trimmed.shapes.push(Shape::new_cells(&mat));
6094                } 
6095            } else {
6096                trimmed.shapes.push(s.clone());
6097            }
6098        }
6099
6100        trimmed
6101    }
6102        
6103    pub fn trim_to_grid(&self) -> Grid {
6104        let trimmed = self.trim_grid();
6105
6106        trimmed.to_grid_impl(Black, false)
6107    }
6108
6109    pub fn trim_to_grid_transparent(&self) -> Grid {
6110        let trimmed = self.trim_grid();
6111
6112        trimmed.to_grid_impl(Black, true)
6113    }
6114
6115    pub fn to_grid(&self) -> Grid {
6116        self.to_grid_impl(Black, false)
6117    }
6118
6119    pub fn to_grid_transparent(&self) -> Grid {
6120        self.to_grid_impl(Black, true)
6121    }
6122
6123    pub fn to_grid_colour(&self, colour: Colour) -> Grid {
6124        self.to_grid_impl(colour, false)
6125    }
6126
6127    pub fn to_grid_colour_transparent(&self, colour: Colour) -> Grid {
6128        self.to_grid_impl(colour, true)
6129    }
6130
6131    pub fn to_grid_impl(&self, colour: Colour, transparent: bool) -> Grid {
6132        if self.nrows == 0 || self.ncols == 0 || self.nrows > 100 || self.ncols > 100 {
6133            return Grid::trivial();
6134        }
6135
6136        let mut grid = Grid::new(self.nrows, self.ncols, colour);
6137
6138        grid.colour = self.colour;
6139
6140        for shape in &self.shapes {
6141            for c in shape.cells.values() {
6142                if  grid.cells.rows <= c.row || grid.cells.columns <= c.col {
6143                    break;
6144                }
6145                if c.colour == Transparent {
6146                    continue;
6147                }
6148                if !transparent || c.colour != colour {
6149                    grid.cells[(c.row, c.col)].colour = c.colour;
6150                }
6151            }
6152        }
6153
6154        grid
6155    }
6156
6157    pub fn to_json(&self) -> String {
6158        let mut grid: Vec<Vec<usize>> = vec![vec![0; self.nrows]; self.ncols];
6159
6160        for shape in &self.shapes {
6161            for ((r, c), cell) in shape.cells.items() {
6162                grid[r][c] = cell.colour.to_usize();
6163            }
6164        }
6165
6166        serde_json::to_string(&grid).unwrap()
6167    }
6168
6169    /*
6170    pub fn cells(&self) -> Vec<Cell> {
6171        let mut cells: Matrix<Cell> = Matrix::from_fn(self.nx, self.ny, |(_, _)| Cell::new_empty());
6172
6173        for ((x, y), c) in &self.shapes.items() {
6174            for c in &s.cells {
6175                cells.push(c.clone());
6176            }
6177        }
6178
6179        cells
6180    }
6181    */
6182
6183    pub fn shape_counts(&self) -> BTreeMap<u32, usize> {
6184        let mut sc: BTreeMap<u32, usize> = BTreeMap::new();
6185
6186        for s in self.shapes.iter() {
6187            let sid = Shape::sid(&s.cells, true);
6188
6189            *sc.entry(sid).or_insert(0) += 1;
6190        }
6191
6192        sc
6193    }
6194
6195    // TODO
6196    pub fn holes_sizes(&self) -> Vec<(Shape, usize)> {
6197        vec![]
6198    }
6199
6200    pub fn have_common_pixel(&self) -> (Colour,Vec<Self>) {
6201        (NoColour, vec![])
6202    }
6203
6204    /*
6205    pub fn pack_common_centre(&self) -> Shape {
6206        Shape::new_empty()
6207    }
6208    */
6209
6210    // bool is true == Row axis, false = Column axis
6211    pub fn striped_r(&self) -> Colour {
6212        NoColour
6213    }
6214
6215    pub fn striped_c(&self) -> Colour {
6216        NoColour
6217    }
6218
6219    pub fn shrink(&self) -> Self {
6220         let mut shapes: Vec<Shape> = Vec::new();
6221
6222         for s in self.shapes.iter() {
6223             shapes.push(s.shrink());
6224         }
6225
6226         Self::new_shapes(&shapes)
6227    }
6228
6229    pub fn fill_missing(&self, to: Colour) -> Self {
6230        let mut shapes = Shapes::new_sized(self.nrows, self.ncols);
6231
6232        for shape in self.shapes.iter() {
6233            shapes.add(&shape.fill_missing(to));
6234        }
6235
6236        shapes
6237    }
6238
6239    pub fn pixel_dir(&self, grid: &Grid) -> BTreeMap<Shape, Vec<Direction>> {
6240        let mut cd: BTreeMap<Shape, Vec<Direction>> = BTreeMap::new();
6241
6242        for s in self.shapes.iter() {
6243            let adj = s.adjacent_to_pixel(grid);
6244
6245            if !adj.is_empty() {
6246                cd.insert(s.clone(), adj);
6247            }
6248        }
6249
6250        cd
6251    }
6252
6253    /*
6254    pub fn categorise_shapes(&mut self) {
6255        let the_shapes = &mut self.shapes;
6256
6257        if the_shapes.is_empty() {
6258            return;
6259        }
6260        if the_shapes.len() == 1 {
6261            self.cats.insert(ShapeCategory::SingleShape);
6262        }
6263        if the_shapes.len() > 1 {
6264            self.cats.insert(ShapeCategory::ManyShapes);
6265        }
6266
6267        for shape in the_shapes.iter_mut() {
6268            if self.cats.is_empty() {
6269                self.cats = shape.cats.clone();
6270            } else {
6271                self.cats = self.cats.union(&shape.cats).cloned().collect();
6272            }
6273        }
6274    }
6275    */
6276
6277    pub fn biggest_shape(&self) -> Shape {
6278        if self.shapes.is_empty() {
6279            return Shape::trivial();
6280        }
6281
6282        let mut biggest_size = 0;
6283        let mut biggest_idx = 0;
6284
6285        for (i, s) in self.shapes.iter().enumerate() {
6286            if s.size() > biggest_size {
6287                biggest_size = s.size();
6288                biggest_idx = i;
6289            }
6290        }
6291
6292        self.shapes[biggest_idx].clone()
6293    }
6294
6295    pub fn has_mirror_r(&self) -> Shape {
6296
6297        for s in &self.shapes  {
6298            if s.is_mirror_r() {
6299                return s.clone();
6300            }
6301        }
6302
6303        Shape::trivial()
6304    }
6305
6306    pub fn has_mirror_c(&self) -> Shape {
6307        for s in &self.shapes  {
6308            if s.is_mirror_c() {
6309                return s.clone();
6310            }
6311        }
6312
6313        Shape::trivial()
6314    }
6315
6316    pub fn cell_colour_cnts(&self, colour: Colour) -> Shape {
6317        let mut count = 0;
6318        let mut shape = Shape::trivial();
6319
6320        for s in &self.shapes {
6321            let h = s.cell_colour_cnt_map();
6322//println!("{h:?}");
6323            //let mut ordinal: Vec<(usize, Colour)> = h.iter().map(|(k, v)| (*v, *k)).collect();
6324
6325            //ordinal.sort();
6326//println!("{:?}", h.get(&colour));
6327
6328            //let (cnt, _colour) = ordinal[position];
6329            if let Some(cnt) = h.get(&colour) {
6330                if *cnt > count {
6331                    count = *cnt;
6332                    shape = s.clone();
6333                }
6334            }
6335        }
6336
6337        shape
6338    }
6339
6340    pub fn get_by_colour(&self, colour: Colour) -> Vec<Shape> {
6341        let mut shapes: Vec<Shape> = Vec::new();
6342
6343        for s in &self.shapes {
6344            if s.colour == colour {
6345                shapes.push(s.clone());
6346            }
6347        }
6348
6349        shapes
6350    }
6351
6352    /*
6353    pub fn categorise_io_edges(in_shapes: &mut Shapes, out_shapes: &Shapes) { //-> BTreeSet<ShapeEdgeCategory> {
6354        let shapes1 = &mut in_shapes.shapes;
6355        let shapes2 = &out_shapes.shapes;
6356//println!("{} == {}", shapes1.len(), shapes2.len());
6357        //let mut edges: BTreeSet<ShapeEdgeCategory> = BTreeSet::new();
6358//if shapes1.len() != shapes2.len() {
6359    //shapes1.show();
6360    //shapes2.show();
6361//}
6362
6363        'outer:
6364        for shape1 in shapes1.iter_mut() {
6365            for shape2 in shapes2.iter() {
6366                if shape1.orow == shape2.orow && shape1.ocol == shape2.ocol { // ???
6367//shape1.show();
6368//shape2.show();
6369                    if shape1.size() == 1 && shape2.size() == 1 {
6370                        if shape1.colour == shape2.colour {
6371                            shape1.io_edges.insert(ShapeEdgeCategory::SameSingle);
6372                        } else {
6373                            shape1.io_edges.insert(ShapeEdgeCategory::SingleDiffColour);
6374                        }
6375
6376                        continue 'outer;
6377                    }
6378
6379                    let same_colour = shape1.colour != Mixed && shape1.colour == shape2.colour;
6380                    let same_shape = shape1.same_shape(shape2);
6381                    let same_size = shape1.same_size(shape2);
6382                    let same_pixels = shape1.pixels() == shape2.pixels();
6383
6384                    if same_colour && same_shape && same_size && same_pixels {
6385                        shape1.io_edges.insert(ShapeEdgeCategory::Same);
6386
6387                        continue 'outer;
6388                    } else {
6389                        if same_colour {
6390                            shape1.io_edges.insert(ShapeEdgeCategory::SameColour);
6391                        }
6392                        if same_shape {
6393                            shape1.io_edges.insert(ShapeEdgeCategory::SameShape);
6394                        }
6395                        if same_size {
6396                            shape1.io_edges.insert(ShapeEdgeCategory::SameSize);
6397                        }
6398                        if same_pixels {
6399                            shape1.io_edges.insert(ShapeEdgeCategory::SamePixelCount);
6400                        }
6401                    }
6402
6403                    /*
6404                    let above = shape1.above(shape2);
6405                    let below = shape1.below(shape2);
6406                    let left = shape1.left(shape2);
6407                    let right = shape1.right(shape2);
6408
6409                    if above && left {
6410                        edges.insert(ShapeEdgeCategory::AboveLeft);
6411                    } else if above && right {
6412                        edges.insert(ShapeEdgeCategory::AboveRight);
6413                    } else if below && left {
6414                        edges.insert(ShapeEdgeCategory::BelowLeft);
6415                    } else if below && right {
6416                        edges.insert(ShapeEdgeCategory::BelowRight);
6417                    } else if left {
6418                        edges.insert(ShapeEdgeCategory::Left);
6419                    } else if right {
6420                        edges.insert(ShapeEdgeCategory::Right);
6421                    } else if above {
6422                        edges.insert(ShapeEdgeCategory::Above);
6423                    } else if below {
6424                        edges.insert(ShapeEdgeCategory::Below);
6425                    }
6426                    */
6427
6428                    if shape1.can_contain(shape2) {
6429                        shape1.io_edges.insert(ShapeEdgeCategory::CanContain);
6430                    }
6431                    if shape1.adjacent(shape2) {
6432                        shape1.io_edges.insert(ShapeEdgeCategory::Adjacent);
6433                    }
6434                    if shape1.have_common_pixel_colour(shape2) {
6435                        shape1.io_edges.insert(ShapeEdgeCategory::CommonPixel);
6436                    }
6437                    if false {
6438                        shape1.io_edges.insert(ShapeEdgeCategory::HasArm);
6439                    }
6440                    if false {
6441                        shape1.io_edges.insert(ShapeEdgeCategory::Gravity);
6442                    }
6443
6444                    /*
6445                    if same {
6446                        in_shapes.edges.insert(shape2.clone(), edges);
6447                    } else {
6448                        in_shapes.io_edges.insert(shape2.clone(), edges);
6449                    }
6450                    */
6451
6452                    let mirrored_r = shape1.is_mirrored_r(shape2);
6453                    let mirrored_c = shape1.is_mirrored_c(shape2);
6454
6455                    if mirrored_r && mirrored_c {
6456                        shape1.io_edges.insert(ShapeEdgeCategory::Symmetric);
6457                    } else {
6458                        if mirrored_r {
6459                            shape1.io_edges.insert(ShapeEdgeCategory::MirroredRow);
6460                        }
6461                        if mirrored_c {
6462                            shape1.io_edges.insert(ShapeEdgeCategory::MirroredCol);
6463                        }
6464                        if shape1.is_rotated_90(shape2) {
6465                            shape1.io_edges.insert(ShapeEdgeCategory::Rot90);
6466                        }
6467                        if shape1.is_rotated_180(shape2) {
6468                            shape1.io_edges.insert(ShapeEdgeCategory::Rot180);
6469                        }
6470                        if shape1.is_rotated_270(shape2) {
6471                            shape1.io_edges.insert(ShapeEdgeCategory::Rot270);
6472                        }
6473                    }
6474                }
6475            }
6476//println!("---- {:?}", shape1.io_edges);
6477        }
6478
6479        //edges
6480    }
6481
6482    pub fn categorise_shape_edges(&mut self) {
6483        Self::categorise_io_edges(self, &self.clone());
6484    }
6485    */
6486}
6487