arc_agi/
cats.rs

1use std::collections::BTreeSet;
2use std::ops::{Add, Sub};
3use strum_macros::{EnumIter, EnumString};
4
5#[repr(usize)]
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
7pub enum Colour {
8    Black = 0,
9    Blue = 1,
10    Red = 2,
11    Green = 3,
12    Yellow = 4,
13    Grey = 5,
14    Fuchsia = 6,
15    Orange = 7,
16    Teal = 8,
17    Brown = 9,
18    ToBlack = 10,
19    ToBlue = 11,
20    ToRed = 12,
21    ToGreen = 13,
22    ToYellow = 14,
23    ToGrey = 15,
24    ToFuchsia = 16,
25    ToOrange = 17,
26    ToTeal = 18,
27    ToBrown = 19,
28    FromBlack = 20,
29    FromBlue = 21,
30    FromRed = 22,
31    FromGreen = 23,
32    FromYellow = 24,
33    FromGrey = 25,
34    FromFuchsia = 26,
35    FromOrange = 27,
36    FromTeal = 28,
37    FromBrown = 29,
38    SameBlack = 30,
39    SameBlue = 31,
40    SameRed = 32,
41    SameGreen = 33,
42    SameYellow = 34,
43    SameGrey = 35,
44    SameFuchsia = 36,
45    SameOrange = 37,
46    SameTeal = 38,
47    SameBrown = 39,
48    DiffBlack = 40,
49    DiffBlue = 41,
50    DiffRed = 42,
51    DiffGreen = 43,
52    DiffYellow = 44,
53    DiffGrey = 45,
54    DiffFuchsia = 46,
55    DiffOrange = 47,
56    DiffTeal = 48,
57    DiffBrown = 49,
58    OrigBlack = 50,
59    OrigBlue = 51,
60    OrigRed = 52,
61    OrigGreen = 53,
62    OrigYellow = 54,
63    OrigGrey = 55,
64    OrigFuchsia = 56,
65    OrigOrange = 57,
66    OrigTeal = 58,
67    OrigBrown = 59,
68    NoColour = 90,
69    Mixed = 91,
70    Transparent = 92,   // Naughty overlading of enum
71    DiffShape = 93,     // Naughty overlading of enum
72    Same = 94,          // Naughty overlading of enum
73}
74
75impl Colour {
76    pub fn new(colour: usize) -> Self {
77        Colour::from_usize(colour)
78    }
79
80    pub fn from_usize(colour: usize) -> Self {
81        match colour {
82            0 => Self::Black,
83            1 => Self::Blue,
84            2 => Self::Red,
85            3 => Self::Green,
86            4 => Self::Yellow,
87            5 => Self::Grey,
88            6 => Self::Fuchsia,
89            7 => Self::Orange,
90            8 => Self::Teal,
91            9 => Self::Brown,
92            10 => Self::ToBlack,
93            11 => Self::ToBlue,
94            12 => Self::ToRed,
95            13 => Self::ToGreen,
96            14 => Self::ToYellow,
97            15 => Self::ToGrey,
98            16 => Self::ToFuchsia,
99            17 => Self::ToOrange,
100            18 => Self::ToTeal,
101            19 => Self::ToBrown,
102            20 => Self::FromBlack,
103            21 => Self::FromBlue,
104            22 => Self::FromRed,
105            23 => Self::FromGreen,
106            24 => Self::FromYellow,
107            25 => Self::FromGrey,
108            26 => Self::FromFuchsia,
109            27 => Self::FromOrange,
110            28 => Self::FromTeal,
111            29 => Self::FromBrown,
112            30 => Self::SameBlack,
113            31 => Self::SameBlue,
114            32 => Self::SameRed,
115            33 => Self::SameGreen,
116            34 => Self::SameYellow,
117            35 => Self::SameGrey,
118            36 => Self::SameFuchsia,
119            37 => Self::SameOrange,
120            38 => Self::SameTeal,
121            39 => Self::SameBrown,
122            40 => Self::DiffBlack,
123            41 => Self::DiffBlue,
124            42 => Self::DiffRed,
125            43 => Self::DiffGreen,
126            44 => Self::DiffYellow,
127            45 => Self::DiffGrey,
128            46 => Self::DiffFuchsia,
129            47 => Self::DiffOrange,
130            48 => Self::DiffTeal,
131            49 => Self::DiffBrown,
132            50 => Self::OrigBlack,
133            51 => Self::OrigBlue,
134            52 => Self::OrigRed,
135            53 => Self::OrigGreen,
136            54 => Self::OrigYellow,
137            55 => Self::OrigGrey,
138            56 => Self::OrigFuchsia,
139            57 => Self::OrigOrange,
140            58 => Self::OrigTeal,
141            59 => Self::OrigBrown,
142            90 => Self::NoColour,
143            91 => Self::Mixed,
144            92 => Self::Transparent,
145            93 => Self::DiffShape,    // Naughty overlaying of enum
146            94 => Self::Same,         // Naughty overlaying of enum
147            _ => Self::NoColour
148        }
149    }
150
151    pub fn to_usize(self) -> usize {
152        match self {
153            Self::Black => 0,
154            Self::Blue => 1,
155            Self::Red => 2,
156            Self::Green => 3,
157            Self::Yellow => 4,
158            Self::Grey => 5,
159            Self::Fuchsia => 6,
160            Self::Orange => 7,
161            Self::Teal => 8,
162            Self::Brown => 9,
163            Self::ToBlack => 10,
164            Self::ToBlue => 11,
165            Self::ToRed => 12,
166            Self::ToGreen => 13,
167            Self::ToYellow => 14,
168            Self::ToGrey => 15,
169            Self::ToFuchsia => 16,
170            Self::ToOrange => 17,
171            Self::ToTeal => 18,
172            Self::ToBrown => 19,
173            Self::FromBlack => 20,
174            Self::FromBlue => 21,
175            Self::FromRed => 22,
176            Self::FromGreen => 23,
177            Self::FromYellow => 24,
178            Self::FromGrey => 25,
179            Self::FromFuchsia => 26,
180            Self::FromOrange => 27,
181            Self::FromTeal => 28,
182            Self::FromBrown => 29,
183            Self::SameBlack => 30,
184            Self::SameBlue => 31,
185            Self::SameRed => 32,
186            Self::SameGreen => 33,
187            Self::SameYellow => 34,
188            Self::SameGrey => 35,
189            Self::SameFuchsia => 36,
190            Self::SameOrange => 37,
191            Self::SameTeal => 38,
192            Self::SameBrown => 39,
193            Self::DiffBlack => 40,
194            Self::DiffBlue => 41,
195            Self::DiffRed => 42,
196            Self::DiffGreen => 43,
197            Self::DiffYellow => 44,
198            Self::DiffGrey => 45,
199            Self::DiffFuchsia => 46,
200            Self::DiffOrange => 47,
201            Self::DiffTeal => 48,
202            Self::DiffBrown => 49,
203            Self::OrigBlack => 50,
204            Self::OrigBlue => 51,
205            Self::OrigRed => 52,
206            Self::OrigGreen => 53,
207            Self::OrigYellow => 54,
208            Self::OrigGrey => 55,
209            Self::OrigFuchsia => 56,
210            Self::OrigOrange => 57,
211            Self::OrigTeal => 58,
212            Self::OrigBrown => 59,
213            Self::NoColour => 90,
214            Self::Mixed => 91,
215            Self::Transparent => 92,    // Naughty overlaying of enum
216            Self::DiffShape => 93,    // Naughty overlaying of enum
217            Self::Same => 94,         // Naughty overlaying of enum
218            //_ => todo!()
219        }
220    }
221
222    pub fn to_base(self) -> Self {
223        Self::from_usize(Self::to_usize(self) % 10)
224    }
225
226    pub fn to_base_sub(self, colour: Self) -> Self {
227        Self::from_usize(Self::to_usize(self) - Self::to_usize(colour))
228    }
229
230    pub fn is_colour(self) -> bool {
231        self == Self::Same || self < Self::NoColour
232    }
233
234    pub fn in_range(c: usize) -> bool {
235         c < 60 || c >= 90 && c <= 94
236    }
237
238    pub fn colours() -> Vec<Self> {
239        (1..=9).map(Self::from_usize).collect()
240    }
241
242    pub const fn base_colours() -> &'static [Self] {
243        &[Self::Black, Self::Blue, Self::Red, Self::Green, Self::Yellow, Self::Grey, Self::Fuchsia, Self::Orange, Self::Teal, Self::Brown]
244    }
245
246    pub fn is_unit(self) -> bool {
247        self > Self::Black && self <= Self::Brown
248    }
249
250    pub fn is_to(self) -> bool {
251        self > Self::ToBlack && self <= Self::ToBrown
252    }
253
254    pub fn is_from(self) -> bool {
255        self >= Self::FromBlack && self <= Self::FromBrown
256    }
257
258    pub fn is_same(self) -> bool {
259        self >= Self::SameBlack && self <= Self::SameBrown
260    }
261
262    pub fn is_diff(self) -> bool {
263        self >= Self::DiffBlack && self <= Self::DiffBrown
264    }
265
266    pub fn is_orig(self) -> bool {
267        self >= Self::OrigBlack && self <= Self::OrigBrown
268    }
269
270    pub fn and(self, other: Self) -> Self {
271        if self == Self::Black || other == Self::Black || self != other {
272            Self::Black
273        } else {
274            self
275        }
276    }
277
278    pub fn or(self, other: Self) -> Self {
279        if self == Self::Black {
280            if other == Self::Black {
281                Self::Black
282            } else {
283                other
284            }
285        } else if other == Self::Black || self == other {
286            self
287        } else {
288            Self::Black
289        }
290    }
291
292    pub fn xor(self, other: Self) -> Self {
293        if self == Self::Black {
294            if other == Self::Black {
295                Self::Black
296            } else {
297                other
298            }
299        } else if other == Self::Black {
300            self
301        } else {
302            Self::Black
303        }
304    }
305
306    pub fn single_colour_vec(v: &[Self]) -> bool {
307        if v.is_empty() {
308            return false;
309        }
310
311        let c = v[0];
312
313        for col in v.iter() {
314            if *col != c {
315                return false;
316            }
317        }
318
319        true
320    }
321
322    pub fn all_colours() -> BTreeSet<Self> {
323        (0 ..= 9).map(Colour::from_usize).collect()
324    }
325
326    pub fn get_position(self, v: &[Colour]) -> usize {
327        v.iter().position(|&ac| ac == self).unwrap_or(0)
328    }
329}
330
331impl Add for Colour {
332    type Output = Colour;
333
334    fn add(self, other: Colour) -> Self::Output {
335        Self::from_usize(Self::to_usize(self) + Self::to_usize(other))
336    }
337}
338
339impl Sub for Colour {
340    type Output = Colour;
341
342    fn sub(self, other: Colour) -> Self::Output {
343        Self::from_usize(Self::to_usize(self) - Self::to_usize(other))
344    }
345}
346
347#[repr(usize)]
348#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
349pub enum GridCategory {
350    HasArms,
351    BareCornersIn,
352    BareCornersOut,
353    BGGridInBlack,
354    BGGridInColoured,
355    BGGridOutBlack,
356    BGGridOutColoured,
357    BlackPatches,
358    BlankIn,
359    BlankOut,
360    BorderBottomIn,
361    BorderBottomOut,
362    BorderLeftIn,
363    BorderLeftOut,
364    BorderRightIn,
365    BorderRightOut,
366    BorderTopIn,
367    BorderTopOut,
368    DiagonalOutOrigin,
369    DiagonalOutNotOrigin,
370    Div9In,
371    Div9Out,
372    Double,
373    CatchAll,
374    EmptyOutput,
375    EvenRowsIn,
376    EvenRowsOut,
377    FullyPopulatedIn,
378    FullyPopulatedOut,
379    GravityDown,
380    GravityLeft,
381    GravityRight,
382    GravityUp,
383    GridLikelyhood,
384    HasBGShape,
385    HasBGShapeColoured,
386    IdenticalColours,
387    IdenticalNoColours,
388    IdenticalNoPixels,
389    InEmpty,
390    InLessCountOut,
391    InLessCountOutColoured,
392    InLessThanOut,
393    InLine,
394    InOutSameShapes,
395    InOutSameShapesColoured,
396    InOutSameSize,
397    InOutShapeCount,
398    InOutShapeCountColoured,
399    InOutSquare,
400    InOutSquareSameSize,
401    InOutSquareSameSizeEven,
402    InOutSquareSameSizeOdd,
403    InSameCountOut,
404    InSameCountOutColoured,
405    InSameSize,
406    InSquare,
407    InToSquaredOut,
408    InvTranspose,
409    InROutHeight(usize),
410    InROutWidth(usize),
411    Is3x3In,
412    Is3x3Out,
413    IsPanelledRIn,
414    IsPanelledROut,
415    IsPanelledCIn,
416    IsPanelledCOut,
417    MirroredR,
418    MirroredC,
419    MirrorRIn,
420    MirrorROut,
421    MirrorCIn,
422    MirrorCOut,
423    NoColouredShapesIn(usize),
424    NoColouredShapesOut(usize),
425    NoColoursIn(usize),
426    NoColoursOut(usize),
427    NoNetColouredShapesIn,
428    NoNetColouredShapesOut,
429    NoShapesIn(usize),
430    NoShapesOut(usize),
431    NotCat,
432    NxNIn(usize),
433    NxNOut(usize),
434    OutLessCountIn,
435    OutLessCountInColoured,
436    OutLessThanIn,
437    OutLine,
438    OutRInHeight(usize),
439    OutRInWidth(usize),
440    OutSameSize,
441    OutSquare,
442    OverlayInSame,
443    OverlayOutSame,
444    OverlayInDiff,
445    OverlayOutDiff,
446    Rot180,
447    Rot270,
448    Rot90,
449    SameColour,
450    ShapeMaxCntIn(usize),
451    ShapeMaxCntOut(usize),
452    ShapeMinCntIn(usize),
453    ShapeMinCntOut(usize),
454    SingleColouredShapeIn,
455    SingleColouredShapeOut,
456    SingleColourCountIn(usize),
457    SingleColourCountOut(usize),
458    SingleColourIn2xOut,
459    SingleColourIn4xOut,
460    SingleColourOut2xIn,
461    SingleColourOut4xIn,
462    SingleColourIn,
463    SingleColourOut,
464    SinglePixelOut,
465    SingleShapeIn,
466    SingleShapeOut,
467    SquareShapeSide(usize),
468    SquareShapeSize(usize),
469    SurroundOut,
470    SymmetricIn,
471    SymmetricInLR,
472    SymmetricInUD,
473    SymmetricOut,
474    SymmetricOutLR,
475    SymmetricOutUD,
476    Transpose,
477//    GridToSize,
478//    GridCalculated,
479//    Shapes,
480}
481
482impl GridCategory {
483    pub fn equal(&self, other: &Self) -> bool {
484        self.same(other) && self.get_para() == other.get_para()
485    }
486
487    pub fn lt(&self, other: &Self) -> bool {
488        self.same(other) && self.get_para() < other.get_para()
489    }
490
491    pub fn gt(&self, other: &Self) -> bool {
492        self.same(other) && self.get_para() > other.get_para()
493    }
494
495    pub fn lte(&self, other: &Self) -> bool {
496        self.same(other) && self.get_para() <= other.get_para()
497    }
498
499    pub fn gte(&self, other: &Self) -> bool {
500        self.same(other) && self.get_para() >= other.get_para()
501    }
502
503    pub fn get_para(&self) -> usize {
504        match self {
505            GridCategory::InROutHeight(i) => *i,
506            GridCategory::InROutWidth(i) => *i,
507            GridCategory::NoColoursIn(i) => *i,
508            GridCategory::NoColoursOut(i) => *i,
509            GridCategory::NoColouredShapesIn(i) => *i,
510            GridCategory::NoColouredShapesOut(i) => *i,
511            GridCategory::NoShapesIn(i) => *i,
512            GridCategory::NoShapesOut(i) => *i,
513            GridCategory::NxNIn(i) => *i,
514            GridCategory::NxNOut(i) => *i,
515            GridCategory::OutRInHeight(i) => *i,
516            GridCategory::OutRInWidth(i) => *i,
517            GridCategory::ShapeMaxCntIn(i) => *i,
518            GridCategory::ShapeMaxCntOut(i) => *i,
519            GridCategory::ShapeMinCntIn(i) => *i,
520            GridCategory::ShapeMinCntOut(i) => *i,
521            GridCategory::SingleColourCountIn(i) => *i,
522            GridCategory::SingleColourCountOut(i) => *i,
523            GridCategory::SquareShapeSide(i) => *i,
524            GridCategory::SquareShapeSize(i) => *i,
525            _ => usize::MAX
526        }
527    }
528
529    pub fn same(&self, other: &Self) -> bool {
530        core::mem::discriminant(self) == core::mem::discriminant(other)
531    }
532
533    pub fn exists(&self, set: &BTreeSet<GridCategory>) -> bool {
534        for i in set.iter() {
535            if self.same(&i) {
536                return true;
537            }
538        }
539
540        false
541    }
542
543    pub fn get(&self, set: &BTreeSet<GridCategory>) -> GridCategory {
544        for cat in set.iter() {
545            if self.same(&cat) {
546                return *cat;
547            }
548        }
549
550        GridCategory::NotCat
551    }
552
553    pub fn value(&self, set: &BTreeSet<GridCategory>) -> usize {
554        for cat in set.iter() {
555            if self.same(&cat) {
556                return cat.get_para();
557            }
558        }
559
560        usize::MAX
561    }
562
563    pub fn eq_value(&self, other: &Self, cats: &BTreeSet<GridCategory>) -> bool {
564        self.same(other) && self.value(cats) == other.value(cats)
565    }
566
567    pub fn lt_value(&self, other: &Self, cats: &BTreeSet<GridCategory>) -> bool {
568        self.same(other) && self.value(cats) < other.value(cats)
569    }
570
571    pub fn gt_value(&self, other: &Self, cats: &BTreeSet<GridCategory>) -> bool {
572        self.same(other) && self.value(cats) > other.value(cats)
573    }
574
575    pub fn lte_value(&self, other: &Self, cats: &BTreeSet<GridCategory>) -> bool {
576        self.same(other) && self.value(cats) <= other.value(cats)
577    }
578
579    pub fn gte_value(&self, other: &Self, cats: &BTreeSet<GridCategory>) -> bool {
580        self.same(other) && self.value(cats) >= other.value(cats)
581    }
582
583}
584
585#[repr(usize)]
586#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
587pub enum ShapeCategory {
588    ArmBottom(usize),
589    ArmLeft(usize),
590    ArmRight(usize),
591    ArmTop(usize),
592    Full,
593    HasBorder,
594    HasEmptyHole,
595    HasHole,
596    //Hollow,   //expensive
597    HorizontalLine,
598    ManyShapes,
599    //MirrorX,  //expensive
600    //MirrorY,  //expensive
601    OpenBottom,
602    OpenBottomHole,
603    OpenLeft,
604    OpenLeftHole,
605    OpenRight,
606    OpenRightHole,
607    OpenTop,
608    OpenTopHole,
609    Pixel,
610    SingleCell,
611    SingleShape,
612    Square,
613    VerticalLine,
614    Other,
615}
616
617#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
618pub enum Direction {
619    Up,
620    Down,
621    Left,
622    Right,
623    UpLeft,
624    UpRight,
625    DownLeft,
626    DownRight,
627    FromUpLeft,
628    FromUpRight,
629    FromDownLeft,
630    FromDownRight,
631    Vertical,
632    Horizontal,
633    Middle,
634    Other,
635    SameDir,
636    CalcDir,
637}
638
639impl Direction {
640    pub fn inverse(&self) -> Self {
641        match self {
642            Self::Up            => Self::Down,
643            Self::Down          => Self::Up,
644            Self::Left          => Self::Right,
645            Self::Right         => Self::Left,
646            Self::UpLeft        => Self::DownRight,
647            Self::UpRight       => Self::DownLeft,
648            Self::DownLeft      => Self::UpRight,
649            Self::DownRight     => Self::UpLeft,
650            Self::FromUpLeft    => Self::FromDownRight,
651            Self::FromUpRight   => Self::FromDownLeft,
652            Self::FromDownLeft  => Self::FromUpRight,
653            Self::FromDownRight => Self::FromUpLeft,
654            Self::Other         => Self::Other,
655            Self::SameDir       => Self::SameDir,
656            Self::CalcDir       => Self::CalcDir,
657            Self::Vertical      => Self::Vertical,
658            Self::Horizontal    => Self::Horizontal,
659            Self::Middle        => Self::Middle,
660        }
661    }
662
663    pub fn rot(&self) -> Self {
664        match self {
665            Self::Up            => Self::Right,
666            Self::Down          => Self::Left,
667            Self::Left          => Self::Up,
668            Self::Right         => Self::Down,
669            Self::UpLeft        => Self::UpRight,
670            Self::UpRight       => Self::UpLeft,
671            Self::DownLeft      => Self::DownRight,
672            Self::DownRight     => Self::DownLeft,
673            Self::FromUpLeft    => Self::FromUpRight,
674            Self::FromUpRight   => Self::FromUpLeft,
675            Self::FromDownLeft  => Self::FromDownRight,
676            Self::FromDownRight => Self::FromDownLeft,
677            Self::Other         => Self::Other,
678            Self::SameDir       => Self::SameDir,
679            Self::CalcDir       => Self::CalcDir,
680            Self::Vertical      => Self::Vertical,
681            Self::Horizontal    => Self::Horizontal,
682            Self::Middle        => Self::Middle,
683        }
684    }
685}
686
687#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, EnumIter, EnumString)]
688pub enum Transformation {   // TODO mimimise this list, some are equivalent
689    NoTrans,
690    MirrorRow,
691    MirrorCol,
692    Trans,
693    Rotate90,
694    Rotate180,
695    Rotate270,
696    Rotate90MirrorRow,
697    Rotate180MirrorRow,
698    Rotate270MirrorRow,
699    Rotate90MirrorCol,
700    Rotate180MirrorCol,
701    Rotate270MirrorCol,
702    MirrorRowRotate90,
703    MirrorRowRotate180,
704    MirrorRowRotate270,
705    MirrorColRotate90,
706    MirrorColRotate180,
707    MirrorColRotate270,
708}
709
710impl Transformation {
711    pub fn inverse(&self) -> Self {
712        match self {
713            Self::NoTrans           => Self::NoTrans,
714            Self::MirrorRow           => Self::MirrorRow,
715            Self::MirrorCol           => Self::MirrorCol,
716            Self::Trans             => Self::Trans,
717            Self::Rotate90          => Self::Rotate270,
718            Self::Rotate180         => Self::Rotate180,
719            Self::Rotate270         => Self::Rotate90,
720            Self::Rotate90MirrorRow   => Self::MirrorRowRotate270,
721            Self::Rotate180MirrorRow  => Self::MirrorRowRotate180,
722            Self::Rotate270MirrorRow  => Self::MirrorRowRotate90,
723            Self::Rotate90MirrorCol   => Self::MirrorColRotate270,
724            Self::Rotate180MirrorCol  => Self::MirrorColRotate180,
725            Self::Rotate270MirrorCol  => Self::MirrorColRotate90,
726            Self::MirrorRowRotate90   => Self::Rotate270MirrorRow,
727            Self::MirrorRowRotate180  => Self::Rotate180MirrorRow,
728            Self::MirrorRowRotate270  => Self::Rotate90MirrorRow,
729            Self::MirrorColRotate90   => Self::Rotate270MirrorCol,
730            Self::MirrorColRotate180  => Self::Rotate180MirrorCol,
731            Self::MirrorColRotate270  => Self::Rotate90MirrorCol,
732        }
733    }
734}
735
736/*
737impl FromStr for Transformation {
738    type Err = ();
739
740    fn from(input: &str) -> Result<Self, Self::Err> {
741        match input {
742            "NoTrans"        	  => Ok(Self::NoTrans),
743            "MirrorRow"        	  => Ok(Self::MirrorRow),
744            "MirrorCol"	          => Ok(Self::MirrorCol),
745            "Trans"	              => Ok(Self::Trans),
746            "Rotate90"	          => Ok(Self::Rotate90),
747            "Rotate180"	          => Ok(Self::Rotate180),
748            "Rotate270"	          => Ok(Self::Rotate270),
749            "Rotate90MirrorRow"	  => Ok(Self::Rotate90MirrorRow),
750            "Rotate180MirrorRow"  => Ok(Self::Rotate180MirrorRow),
751            "Rotate270MirrorRow"  => Ok(Self::Rotate270MirrorRow),
752            "Rotate90MirrorCol"	  => Ok(Self::Rotate90MirrorCol),
753            "Rotate180MirrorCol"  => Ok(Self::Rotate180MirrorCol),
754            "Rotate270MirrorCol"  => Ok(Self::Rotate270MirrorCol),
755            "MirrorRowRotate90"	  => Ok(Self::MirrorRowRotate90),
756            "MirrorRowRotate180"  => Ok(Self::MirrorRowRotate180),
757            "MirrorRowRotate270"  => Ok(Self::MirrorRowRotate270),
758            "MirrorColRotate90"	  => Ok(Self::MirrorColRotate90),
759            "MirrorColRotate180"  => Ok(Self::MirrorColRotate180),
760            "MirrorColRotate270"  => Ok(Self::MirrorColRotate270),
761            _ => todo!(),
762        }
763    }
764}
765*/
766
767#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
768pub enum Tag {
769    Colour,
770    Arm,
771    Shape,
772    Other,
773}
774
775#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
776pub enum Action {
777    Together,
778    Reach,
779}
780
781#[repr(usize)]
782#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
783pub enum ShapeEdgeCategory {
784    //NotExample,
785    Above,
786    AboveLeft,
787    AboveRight,
788    Adjacent,
789    Below,
790    BelowLeft,
791    BelowRight,
792    CanContain,
793    CommonPixel,
794    Gravity,
795    HasArm,
796    Left,
797    MirroredRow,
798    MirroredCol,
799    Right,
800    Rot180,
801    Rot270,
802    Rot90,
803    Same,
804    SameColour,
805    SamePixelCount,
806    SameShape,
807    SameSingle,
808    SameSize,
809    SingleColour,
810    SingleDiffColour,
811    SinglePixel,
812    Symmetric,
813    Transposed,
814}
815
816/*
817#[repr(usize)]
818#[derive(Clone)]
819pub enum DiffStates<'a> {
820    Start,
821    CopyToFirst(&'a dyn Fn(&Example)),
822    CopyToLast,
823    MoveToFirst,
824    MoveToLast,
825}
826*/
827
828#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
829pub enum CellCategory {
830    CornerTL,
831    CornerTR,
832    CornerBL,
833    CornerBR,
834    InsideCornerTL,
835    InsideCornerTR,
836    InsideCornerBL,
837    InsideCornerBR,
838    InternalCornerTL,
839    InternalCornerTR,
840    InternalCornerBL,
841    InternalCornerBR,
842    InternalEdgeT,
843    InternalEdgeB,
844    InternalEdgeL,
845    InternalEdgeR,
846    EdgeT,
847    EdgeB,
848    EdgeL,
849    EdgeR,
850    TopEdgeT,
851    TopEdgeB,
852    TopEdgeL,
853    TopEdgeR,
854    BottomEdgeT,
855    BottomEdgeB,
856    BottomEdgeL,
857    BottomEdgeR,
858    LeftEdgeT,
859    LeftEdgeB,
860    LeftEdgeL,
861    LeftEdgeR,
862    RightEdgeT,
863    RightEdgeB,
864    RightEdgeL,
865    RightEdgeR,
866    HollowEdgeT,
867    HollowEdgeB,
868    HollowEdgeL,
869    HollowEdgeR,
870    PointT,
871    PointB,
872    PointL,
873    PointR,
874    //DiagTL,
875    //DiagTR,
876    //DiagBL,
877    //DiagBR,
878    LineTB,
879    LineLR,
880    MiddleTB,
881    MiddleLR,
882    Middle,
883    Single,
884    SingleT,
885    SingleB,
886    SingleL,
887    SingleR,
888    Unknown,
889    StemLR,
890    StemTB,
891    BG,
892}
893
894impl CellCategory {
895    pub fn edge_corner(self) -> bool {
896        self >= Self::CornerTL && self <= Self::CornerBR
897    }
898
899    pub fn internal_corner(self) -> bool {
900        self >= Self::InternalCornerTL && self <= Self::InternalCornerBR
901    }
902
903    pub fn inside_corner(self) -> bool {
904        self >= Self::InsideCornerTL && self <= Self::InsideCornerBR
905    }
906
907    pub fn outer_corner(self) -> bool {
908        self.edge_corner() || self.internal_corner()
909    }
910
911    pub fn has_point(self) -> bool {
912        matches!(self, Self::PointT | Self::PointB | Self::PointL | Self::PointR)
913    }
914}