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::*;
8use 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,
19pub cells: Matrix<Cell>,
21 }
24
25impl 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 impl 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 }
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 new_cells = Self::cell_category(&new_cells);
94
95 let res = Self { orow, ocol, colour, cells: new_cells };
96
97 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 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
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 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 Self { orow, ocol, colour, cells }
136 }
137
138 pub fn new_empty() -> Self {
139 let cells = Matrix::new(0, 0, Cell::new_empty());
140 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 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 {
247if self.size() != other.size() || self.cells.rows != other.cells.rows {
249 return false;
250 }
251
252 for (rc, c) in self.cells.items() {
253if c.colour != Black && c.colour != other.cells[rc].colour {
255 return false;
256 }
257 }
258true
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 });
292let 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}
315
316 let s1 = this.subshape(0, self.cells.rows, 1, len);
317 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}
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 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 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 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 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 }
676shape
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 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 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 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 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 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 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 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 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 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 = 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 cols - indent - depth .. cols - indent {
1413 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}
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 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 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)].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 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 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 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 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 pub fn patch_in_shape(&self, other: &Self) -> (usize, usize) {
2476 for ch in self.cells.chunks(self.cells.columns) {
2477 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, 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 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 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 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 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 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 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 {
3060let 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 {
3074return true;
3082 }
3083 }
3084 }
3085
3086 false
3087 }
3088
3089 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 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 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 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'outer:
3393 for ((r, c), cell) in self.cells.items() {
3394 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 }
3409false
3412 }
3413
3414 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 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
3674let (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 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.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 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 {
4068let 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 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 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 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 }
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 }
4352
4353impl 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 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 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 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 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 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}
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 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);
4947ss.shapes.push(Shape::new_sized_coloured(max_r + 1, max_c + 1, bg));
4950
4951 for (_, v) in h.iter() {
4952let 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 {
5034return 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 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 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 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 for s in removals.iter() {
5368 shapes.remove(s);
5369 }
5370shapes
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 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 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 }
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 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
5719let 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, a.orow, a.ocol, &a.to_json()).cmp(&(b.colour, b.orow, b.ocol, &b.to_json())));
5730 } else {
5731 so.shapes.sort();
5732 }
5733for (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);
5740pairs.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 let Some((lc, _)) = h.pop_first() else { todo!() };
5760 let Some((rc, _)) = h.pop_first() else { todo!() };
5761for ((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);
5799shapes.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);
5807shapes.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 {
5884diffs.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 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 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}
5944
5945 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*h.entry(Colour::to_usize(c.colour)).or_insert(0) += 1;
5961 }
5963
5964 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 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 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 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 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 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 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();
6322if 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 }
6487