cube_core/cube/core/
grid.rs

1use crate::{
2    utils::{
3        cube_utils::{Axis, Color},
4    },
5    cube::{
6        slice::{CubeMove, CubeSliceOrder}
7    }
8};
9
10const PRINT_CHAR: &str = "██";
11const ANSI_RESET: &str = "\x1b[0m";
12
13#[derive(Debug, Clone)]
14pub enum MoveDirection {
15    Clockwise,
16    CounterClockwise,
17    Double,
18}
19
20impl MoveDirection {
21    pub fn flip(self) -> MoveDirection {
22        match self {
23            Self::Clockwise => Self::CounterClockwise,
24            Self::CounterClockwise => Self::Clockwise,
25            Self::Double => Self::Double,
26        }
27    }
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
31pub enum GridSide {
32    Top,
33    Front,
34    Bottom,
35    Left,
36    Right,
37    Back,
38    MiddleX,
39    MiddleY,
40    MiddleZ,
41}
42
43impl GridSide {
44    pub fn idx(&self) -> usize {
45        match self {
46            GridSide::Top => 0,
47            GridSide::Left => 1,
48            GridSide::Front => 2,
49            GridSide::Right => 3,
50            GridSide::Back => 4,
51            GridSide::Bottom => 5,
52            _ => panic!()
53        }
54    }
55
56    pub fn from_idx(idx: usize) -> GridSide {
57        match idx {
58            0 => GridSide::Top,
59            1 => GridSide::Left,
60            2 => GridSide::Front,
61            3 => GridSide::Right,
62            4 => GridSide::Back,
63            5 => GridSide::Bottom,
64            _ => panic!(),
65        }
66    }
67
68    pub fn middle_layer_from_axis(axis: &Axis) -> GridSide {
69        match axis {
70            Axis::X => GridSide::MiddleX,
71            Axis::Y => GridSide::MiddleY,
72            Axis::Z => GridSide::MiddleZ
73        }
74    }
75
76    pub fn axis(&self) -> Axis {
77        match self {
78            GridSide::Top => Axis::Y,
79            GridSide::Left => Axis::X,
80            GridSide::Front => Axis::Z,
81            GridSide::Right => Axis::X,
82            GridSide::Back => Axis::Z,
83            GridSide::Bottom => Axis::Y,
84            GridSide::MiddleX => Axis::X,
85            GridSide::MiddleY => Axis::Y,
86            GridSide::MiddleZ => Axis::Z,
87        }
88    }
89
90    pub fn order(&self) -> CubeSliceOrder {
91        match self {
92            GridSide::Top => CubeSliceOrder::FIRST,
93            GridSide::Left => CubeSliceOrder::FIRST,
94            GridSide::Front => CubeSliceOrder::FIRST,
95            GridSide::Right => CubeSliceOrder::LAST,
96            GridSide::Back => CubeSliceOrder::LAST,
97            GridSide::Bottom => CubeSliceOrder::LAST,
98            GridSide::MiddleX => CubeSliceOrder::MIDDLE,
99            GridSide::MiddleY => CubeSliceOrder::MIDDLE,
100            GridSide::MiddleZ => CubeSliceOrder::MIDDLE,
101        }
102    }
103
104    pub fn is_middle(&self) -> bool {
105        match self {
106            GridSide::MiddleX => true,
107            GridSide::MiddleY => true,
108            GridSide::MiddleZ => true,
109            _ => false
110        }
111    }
112
113    pub fn middle_layer_adjacent(self) -> GridSide {
114        match self {
115            GridSide::MiddleX => GridSide::Left,
116            GridSide::MiddleY => GridSide::Bottom,
117            GridSide::MiddleZ => GridSide::Front,
118            _ => self
119        }
120    }
121}
122
123enum SliceType {
124    Top,
125    Bottom,
126    Left,
127    Right,
128    Vertical,
129    VerticalFlipped,
130    Horizontal,
131    HorizontalFlipped,
132}
133
134pub struct NeighborSlice {
135    side: GridSide,
136    slice_type: SliceType,
137}
138
139impl NeighborSlice {
140    pub fn read_from(&self, grid: &Grid) -> [Color; 3] {
141        let face = &grid.faces[self.side.idx()];
142        match self.slice_type {
143            SliceType::Top => {
144                [
145                    face.grid[0][0],
146                    face.grid[0][1],
147                    face.grid[0][2],
148                ]
149            },
150            SliceType::Bottom => {
151                [
152                    face.grid[2][2],
153                    face.grid[2][1],
154                    face.grid[2][0],
155                ]
156            },
157            SliceType::Left => {
158                [
159                    face.grid[2][0],
160                    face.grid[1][0],
161                    face.grid[0][0],
162                ]
163            },
164            SliceType::Right => {
165                [
166                    face.grid[0][2],
167                    face.grid[1][2],
168                    face.grid[2][2],
169                ]
170            },
171            SliceType::Vertical => {
172                [
173                    face.grid[2][1],
174                    face.grid[1][1],
175                    face.grid[0][1],
176                ]
177            },
178            SliceType::VerticalFlipped => {
179                [
180                    face.grid[0][1],
181                    face.grid[1][1],
182                    face.grid[2][1],
183                ]
184            },
185            SliceType::Horizontal => {
186                [
187                    face.grid[1][0],
188                    face.grid[1][1],
189                    face.grid[1][2],
190                ]
191            },
192            SliceType::HorizontalFlipped => {
193                [
194                    face.grid[1][2],
195                    face.grid[1][1],
196                    face.grid[1][0],
197                ]
198            },
199        }
200    }
201
202    fn write_to(&self, grid: &mut Grid, colors: [Color; 3]) {
203        let face = &mut grid.faces[self.side.idx()];
204        match self.slice_type {
205            SliceType::Top => {
206                face.grid[0][0] = colors[0];
207                face.grid[0][1] = colors[1];
208                face.grid[0][2] = colors[2];
209            },
210            SliceType::Bottom => {
211                face.grid[2][2] = colors[0];
212                face.grid[2][1] = colors[1];
213                face.grid[2][0] = colors[2];
214            },
215            SliceType::Left => {
216                face.grid[2][0] = colors[0];
217                face.grid[1][0] = colors[1];
218                face.grid[0][0] = colors[2];
219            },
220            SliceType::Right => {
221                face.grid[0][2] = colors[0];
222                face.grid[1][2] = colors[1];
223                face.grid[2][2] = colors[2];
224            },
225            SliceType::Vertical => {
226                face.grid[2][1] = colors[0];
227                face.grid[1][1] = colors[1];
228                face.grid[0][1] = colors[2];
229            },
230            SliceType::VerticalFlipped => {
231                face.grid[2][1] = colors[2];
232                face.grid[1][1] = colors[1];
233                face.grid[0][1] = colors[0];
234            },
235            SliceType::Horizontal => {
236                face.grid[1][0] = colors[0];
237                face.grid[1][1] = colors[1];
238                face.grid[1][2] = colors[2];
239            },
240            SliceType::HorizontalFlipped => {
241                face.grid[1][0] = colors[2];
242                face.grid[1][1] = colors[1];
243                face.grid[1][2] = colors[0];
244            },
245        }
246    }
247}
248
249#[derive(Debug, Clone, Copy, PartialEq, Eq)]
250pub struct GridFace {
251    pub grid: [[Color; 3]; 3],
252}
253
254impl GridFace {
255    pub fn new(color: Color) -> GridFace {
256        GridFace {
257            grid: [[color; 3]; 3],
258        }
259    }
260
261    pub fn empty() -> GridFace {
262        Self::new(Color::Gray)
263    }
264
265    fn is_one_color(&self) -> bool {
266        let first_color = &self.grid[0][0];
267        for row in self.grid.iter() {
268            for color in row {
269                if first_color != color {
270                    return false;
271                }
272            }
273        }
274        true
275    }
276
277    pub fn print(&self) {
278        for row in self.grid.iter() {
279            for color in row {
280                print!("{}{}{}", color.to_ansi(), PRINT_CHAR, ANSI_RESET);
281            }
282            println!();
283        }
284    }
285
286    pub fn print_row(&self, idx: usize) {
287        for color in self.grid[idx] {
288            print!("{}{}{}", color.to_ansi(), PRINT_CHAR, ANSI_RESET);
289        }
290    }
291
292    pub fn rotate(&mut self, direction: &MoveDirection) {
293        match direction {
294            MoveDirection::Clockwise => self.rotate_clockwise(),
295            MoveDirection::CounterClockwise => self.rotate_counter_clockwise(),
296            MoveDirection::Double => {
297                self.rotate_clockwise();
298                self.rotate_clockwise();
299            }
300        }
301    }
302
303    pub fn rotate_clockwise(&mut self) {
304        // rotate corners
305        let tmp = self.grid[0][0];
306        self.grid[0][0] = self.grid[2][0];
307        self.grid[2][0] = self.grid[2][2];
308        self.grid[2][2] = self.grid[0][2];
309        self.grid[0][2] = tmp;
310
311        // rotate edges
312        let tmp = self.grid[0][1];
313        self.grid[0][1] = self.grid[1][0];
314        self.grid[1][0] = self.grid[2][1];
315        self.grid[2][1] = self.grid[1][2];
316        self.grid[1][2] = tmp;
317    }
318
319    pub fn rotate_counter_clockwise(&mut self) {
320        // rotate corners
321        let tmp = self.grid[0][0];
322        self.grid[0][0] = self.grid[0][2];
323        self.grid[0][2] = self.grid[2][2];
324        self.grid[2][2] = self.grid[2][0];
325        self.grid[2][0] = tmp;
326
327        // rotate edges
328        let tmp = self.grid[0][1];
329        self.grid[0][1] = self.grid[1][2];
330        self.grid[1][2] = self.grid[2][1];
331        self.grid[2][1] = self.grid[1][0];
332        self.grid[1][0] = tmp;
333    }
334}
335
336pub struct Grid {
337    pub faces: [GridFace; 6],
338}
339
340impl Grid {
341    pub fn new() -> Grid {
342        Grid {
343            faces: [
344                GridFace::new(Color::White),
345                GridFace::new(Color::Orange),
346                GridFace::new(Color::Green),
347                GridFace::new(Color::Red),
348                GridFace::new(Color::Blue),
349                GridFace::new(Color::Yellow),
350            ]
351        }
352    }
353
354    pub fn is_solved(&self) -> bool {
355        for face in self.faces.iter() {
356            if !face.is_one_color() {
357                return false;
358            }
359        }
360        true
361    }
362
363    pub fn apply_move(&mut self, mv: CubeMove) {
364        self.move_face(mv.grid_side, mv.direction);
365    }
366
367    pub fn print(&self) {
368        fn print_blank_row() {
369            for _ in 0..3 {
370                print!("{}{}{}", Color::Gray.to_ansi(), PRINT_CHAR, ANSI_RESET);
371            }
372        }
373
374        for row in 0..3 {
375            print_blank_row();
376            self.faces[0].print_row(row);
377            print_blank_row();
378            print_blank_row();
379            println!();
380        }
381
382        for row in 0..3 {
383            for face in 1..5 {
384                self.faces[face].print_row(row);
385            }
386            println!();
387        }
388
389        for row in 0..3 {
390            print_blank_row();
391            self.faces[5].print_row(row);
392            print_blank_row();
393            print_blank_row();
394            println!();
395        }
396
397        print!("\n\n\n");
398    }
399
400    fn rotate_buffers(buffers: &mut Vec<[Color; 3]>, grid_side: &GridSide, direction: MoveDirection) {
401        match grid_side {
402            GridSide::Left 
403                | GridSide::Top
404                | GridSide::Front
405                | GridSide::MiddleX
406                | GridSide::MiddleZ => match direction {
407                MoveDirection::Clockwise => buffers.rotate_right(1),
408                MoveDirection::CounterClockwise => buffers.rotate_left(1),
409                MoveDirection::Double => buffers.rotate_right(2),
410            }
411            _ => match direction {
412                MoveDirection::Clockwise => buffers.rotate_left(1),
413                MoveDirection::CounterClockwise => buffers.rotate_right(1),
414                MoveDirection::Double => buffers.rotate_right(2),
415            }
416        };
417        
418    }
419
420    pub fn move_face(&mut self, side: GridSide, direction: MoveDirection) {
421        if !side.is_middle() {
422            let idx = side.idx();
423            self.faces[idx].rotate(&direction);
424        }
425
426        let neighbors = self.get_neighbors(side);
427        let mut buffers: Vec<[Color; 3]> = neighbors.iter()
428            .map(|ns| {
429                    ns.read_from(self)
430                }
431            )
432            .collect();
433
434        Grid::rotate_buffers(&mut buffers, &side, direction);
435
436        for (slice, colors) in neighbors.into_iter().zip(buffers) {
437            slice.write_to(self, colors);
438        }        
439    }
440
441    pub fn get_neighbors(&self, side: GridSide) -> [NeighborSlice; 4] {
442        match side {
443            GridSide::Top => [
444                NeighborSlice {slice_type: SliceType::Top, side: GridSide::Back},
445                NeighborSlice {slice_type: SliceType::Top, side: GridSide::Right},
446                NeighborSlice {slice_type: SliceType::Top, side: GridSide::Front},
447                NeighborSlice {slice_type: SliceType::Top, side: GridSide::Left},
448            ],
449            GridSide::Front => [
450                NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Top},
451                NeighborSlice {slice_type: SliceType::Left, side: GridSide::Right},
452                NeighborSlice {slice_type: SliceType::Top, side: GridSide::Bottom},
453                NeighborSlice {slice_type: SliceType::Right, side: GridSide::Left},
454            ],
455            GridSide::Bottom => [
456                NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Back},
457                NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Right},
458                NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Front},
459                NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Left},
460            ],
461            GridSide::Left => [
462                NeighborSlice {slice_type: SliceType::Left, side: GridSide::Top},
463                NeighborSlice {slice_type: SliceType::Left, side: GridSide::Front},
464                NeighborSlice {slice_type: SliceType::Left, side: GridSide::Bottom},
465                NeighborSlice {slice_type: SliceType::Right, side: GridSide::Back},
466            ],
467            GridSide::Right => [
468                NeighborSlice {slice_type: SliceType::Right, side: GridSide::Top},
469                NeighborSlice {slice_type: SliceType::Right, side: GridSide::Front},
470                NeighborSlice {slice_type: SliceType::Right, side: GridSide::Bottom},
471                NeighborSlice {slice_type: SliceType::Left, side: GridSide::Back},
472            ],
473            GridSide::Back => [
474                NeighborSlice {slice_type: SliceType::Top, side: GridSide::Top},
475                NeighborSlice {slice_type: SliceType::Right, side: GridSide::Right},
476                NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Bottom},
477                NeighborSlice {slice_type: SliceType::Left, side: GridSide::Left},
478            ],
479            GridSide::MiddleX => [
480                NeighborSlice {slice_type: SliceType::Vertical, side: GridSide::Top},
481                NeighborSlice {slice_type: SliceType::Vertical, side: GridSide::Front},
482                NeighborSlice {slice_type: SliceType::Vertical, side: GridSide::Bottom},
483                NeighborSlice {slice_type: SliceType::VerticalFlipped, side: GridSide::Back},
484            ],
485            GridSide::MiddleY => [
486                NeighborSlice {slice_type: SliceType::Horizontal, side: GridSide::Back},
487                NeighborSlice {slice_type: SliceType::Horizontal, side: GridSide::Right},
488                NeighborSlice {slice_type: SliceType::Horizontal, side: GridSide::Front},
489                NeighborSlice {slice_type: SliceType::Horizontal, side: GridSide::Left},
490            ],
491            GridSide::MiddleZ => [
492                NeighborSlice {slice_type: SliceType::HorizontalFlipped, side: GridSide::Top},
493                NeighborSlice {slice_type: SliceType::Vertical, side: GridSide::Right},
494                NeighborSlice {slice_type: SliceType::Horizontal, side: GridSide::Bottom},
495                NeighborSlice {slice_type: SliceType::VerticalFlipped, side: GridSide::Left},
496            ],
497        }
498    }
499}
500
501#[cfg(test)]
502mod tests {
503    use super::*;
504    use crate::utils::cube_utils::Color;
505    use Color::*;
506
507    fn assert_whole_color(grid: &Grid, side: GridSide, color: Color) -> bool {
508        let face = &grid.faces[side.idx()];
509        for row in face.grid {
510            for c in row {
511                if c != color {
512                    return false;
513                }
514            }
515        };
516        true
517    }
518
519    fn assert_right_color(grid: &Grid, side: GridSide, color: Color) -> bool {
520        let face_grid = &grid.faces[side.idx()].grid;
521        face_grid[0][2] == color && face_grid[1][2] == color && face_grid[2][2] == color
522    }
523
524    fn assert_left_color(grid: &Grid, side: GridSide, color: Color) -> bool {
525        let face_grid = &grid.faces[side.idx()].grid;
526        face_grid[0][0] == color && face_grid[1][0] == color && face_grid[2][0] == color
527    }
528
529    fn assert_top_color(grid: &Grid, side: GridSide, color: Color) -> bool {
530        let face_grid = &grid.faces[side.idx()].grid;
531        face_grid[0][0] == color && face_grid[0][1] == color && face_grid[0][2] == color
532    }
533
534    fn assert_bottom_color(grid: &Grid, side: GridSide, color: Color) -> bool {
535        let face_grid = &grid.faces[side.idx()].grid;
536        face_grid[2][0] == color && face_grid[2][1] == color && face_grid[2][2] == color
537    }
538
539    fn assert_solved_cube(grid: &Grid) -> bool {
540        assert_whole_color(grid, GridSide::Top, Color::White) 
541            && assert_whole_color(grid, GridSide::Left, Color::Orange)
542            && assert_whole_color(grid, GridSide::Front, Color::Green)
543            && assert_whole_color(grid, GridSide::Right, Color::Red)
544            && assert_whole_color(grid, GridSide::Back, Color::Blue)
545            && assert_whole_color(grid, GridSide::Bottom, Color::Yellow)
546    }
547
548    fn new_custom_face(grid: [[Color; 3]; 3]) -> GridFace {
549        GridFace { grid }
550    }
551
552    fn create_solved_grid() -> Grid {
553        Grid {
554            faces: [
555                GridFace::new(White),   // TOP
556                GridFace::new(Orange),  // LEFT
557                GridFace::new(Green),   // FRONT
558                GridFace::new(Red),     // RIGHT
559                GridFace::new(Blue),    // BACK
560                GridFace::new(Yellow),  // BOTTOM
561            ],
562        }
563    }
564
565    fn create_mixed_grid() -> Grid {
566        Grid {
567            faces: [
568                // TOP
569                new_custom_face([
570                    [Red, White, Green],
571                    [Green, White, Blue],
572                    [White, Blue, Blue],
573                ]),
574                // LEFT
575                new_custom_face([
576                    [Blue, Orange, Red],
577                    [Yellow, Orange, Yellow],
578                    [Green, Green, Orange],
579                ]),
580                // FRONT
581                new_custom_face([
582                    [Blue, Red, Orange],
583                    [Green, Green, Orange],
584                    [Yellow, Yellow, Green],
585                ]),
586                // RIGHT
587                new_custom_face([
588                    [White, Orange, Orange],
589                    [Yellow, Red, Orange],
590                    [Red, Red, Green],
591                ]),
592                // BACK
593                new_custom_face([
594                    [Yellow, Green, Yellow],
595                    [White, Blue, Red],
596                    [White, White, White],
597                ]),
598                // BOTTOM
599                new_custom_face([
600                    [Blue, Blue, Yellow],
601                    [Red, Yellow, White],
602                    [Orange, Blue, Red],
603                ]),
604            ],
605        }
606    }
607
608    #[test]
609    fn test_move_right() {
610        let mut grid = create_solved_grid();
611        grid.move_face(GridSide::Right, MoveDirection::Clockwise);
612        
613        assert!(assert_whole_color(&grid, GridSide::Right, Color::Red));
614        assert!(assert_right_color(&grid, GridSide::Front, Color::Yellow));
615        assert!(assert_right_color(&grid, GridSide::Top, Color::Green));
616        assert!(assert_left_color(&grid, GridSide::Back, Color::White));
617        assert!(assert_right_color(&grid, GridSide::Bottom, Color::Blue));
618
619        grid.move_face(GridSide::Right, MoveDirection::CounterClockwise);
620
621        assert!(assert_solved_cube(&grid));
622    }
623
624    #[test]
625    fn test_move_left() {
626        let mut grid = create_solved_grid();
627        grid.move_face(GridSide::Left, MoveDirection::Clockwise);
628
629        assert!(assert_whole_color(&grid, GridSide::Left, Color::Orange));
630        assert!(assert_left_color(&grid, GridSide::Front, Color::White));
631        assert!(assert_left_color(&grid, GridSide::Top, Color::Blue));
632        assert!(assert_right_color(&grid, GridSide::Back, Color::Yellow));
633        assert!(assert_left_color(&grid, GridSide::Bottom, Color::Green));
634
635        grid.move_face(GridSide::Left, MoveDirection::CounterClockwise);
636
637        assert!(assert_solved_cube(&grid));
638    }
639
640    #[test]
641    fn test_move_front() {
642        let mut grid = create_solved_grid();
643        grid.move_face(GridSide::Front, MoveDirection::Clockwise);
644
645        assert!(assert_whole_color(&grid, GridSide::Front, Color::Green));
646        assert!(assert_bottom_color(&grid, GridSide::Top, Color::Orange));
647        assert!(assert_left_color(&grid, GridSide::Right, Color::White));
648        assert!(assert_top_color(&grid, GridSide::Bottom, Color::Red));
649        assert!(assert_right_color(&grid, GridSide::Left, Color::Yellow));
650
651        grid.move_face(GridSide::Front, MoveDirection::CounterClockwise);
652
653        assert!(assert_solved_cube(&grid));
654    }
655
656    #[test]
657    fn test_move_top() {
658        let mut grid = create_solved_grid();
659        grid.move_face(GridSide::Top, MoveDirection::Clockwise);
660
661        assert!(assert_whole_color(&grid, GridSide::Top, Color::White));
662        assert!(assert_top_color(&grid, GridSide::Front, Color::Red));
663        assert!(assert_top_color(&grid, GridSide::Left, Color::Green));
664        assert!(assert_top_color(&grid, GridSide::Right, Color::Blue));
665        assert!(assert_top_color(&grid, GridSide::Back, Color::Orange));
666
667        grid.move_face(GridSide::Top, MoveDirection::CounterClockwise);
668
669        assert!(assert_solved_cube(&grid));
670    }
671
672    #[test]
673    fn test_move_bottom() {
674        let mut grid = create_solved_grid();
675        grid.move_face(GridSide::Bottom, MoveDirection::Clockwise);
676
677        assert!(assert_whole_color(&grid, GridSide::Bottom, Color::Yellow));
678        assert!(assert_bottom_color(&grid, GridSide::Front, Color::Orange));
679        assert!(assert_bottom_color(&grid, GridSide::Left, Color::Blue));
680        assert!(assert_bottom_color(&grid, GridSide::Right, Color::Green));
681        assert!(assert_bottom_color(&grid, GridSide::Back, Color::Red));
682
683        grid.move_face(GridSide::Bottom, MoveDirection::CounterClockwise);
684
685        assert!(assert_solved_cube(&grid));
686    }
687
688    #[test]
689    fn test_move_back() {
690        let mut grid = create_solved_grid();
691        grid.move_face(GridSide::Back, MoveDirection::Clockwise);
692
693        assert!(assert_whole_color(&grid, GridSide::Back, Color::Blue));
694        assert!(assert_top_color(&grid, GridSide::Top, Color::Red));
695        assert!(assert_right_color(&grid, GridSide::Right, Color::Yellow));
696        assert!(assert_left_color(&grid, GridSide::Left, Color::White));
697        assert!(assert_bottom_color(&grid, GridSide::Bottom, Color::Orange));
698
699        grid.move_face(GridSide::Back, MoveDirection::CounterClockwise);
700
701        assert!(assert_solved_cube(&grid));
702    }
703
704    #[test]
705    fn test_middle_move_m() {
706        use GridSide::*;
707        use MoveDirection::*;
708
709        let mut grid = create_solved_grid();
710
711        grid.move_face(Top, Clockwise);
712        grid.move_face(Bottom, Clockwise);
713        grid.move_face(Front, Clockwise);
714        grid.move_face(Right, Clockwise);
715        grid.move_face(Top, Clockwise);
716        
717        grid.move_face(MiddleX, Clockwise);
718
719        let front = &grid.faces[Front.idx()];
720        assert_eq!(front, &new_custom_face([
721                    [White, White, White],
722                    [Orange, White, Yellow],
723                    [Orange, Red, Yellow],
724                ]));
725
726        let top = &grid.faces[Top.idx()];
727        assert_eq!(top, &new_custom_face([
728                    [Blue, Red, White],
729                    [Orange, Blue, White],
730                    [Red, Green, Red],
731                ]));
732
733        let back = &grid.faces[Back.idx()];
734        assert_eq!(back, &new_custom_face([
735                    [Green, Yellow, Yellow],
736                    [White, Yellow, Blue],
737                    [White, Red, Red],
738                ]));
739
740        let bottom = &grid.faces[Bottom.idx()];
741        assert_eq!(bottom, &new_custom_face([
742                    [Green, White, Red],
743                    [Yellow, Green, Blue],
744                    [Yellow, Green, Orange],
745                ]));
746    }
747
748    #[test]
749    fn test_middle_move_m_counter_clockwise() {
750        use GridSide::*;
751        use MoveDirection::*;
752
753        let mut grid = create_solved_grid();
754
755        grid.move_face(Top, Clockwise);
756        grid.move_face(Bottom, Clockwise);
757        grid.move_face(Front, Clockwise);
758        grid.move_face(Right, Clockwise);
759        grid.move_face(Top, Clockwise);
760        
761        grid.move_face(MiddleX, CounterClockwise);
762
763        let front = &grid.faces[Front.idx()];
764        assert_eq!(front, &new_custom_face([
765                    [White, Red, White],
766                    [Orange, Yellow, Yellow],
767                    [Orange, Yellow, Yellow],
768                ]));
769
770        let top = &grid.faces[Top.idx()];
771        assert_eq!(top, &new_custom_face([
772                    [Blue, White, White],
773                    [Orange, Green, White],
774                    [Red, Green, Red],
775                ]));
776
777        let back = &grid.faces[Back.idx()];
778        assert_eq!(back, &new_custom_face([
779                    [Green, Red, Yellow],
780                    [White, White, Blue],
781                    [White, White, Red],
782                ]));
783
784        let bottom = &grid.faces[Bottom.idx()];
785        assert_eq!(bottom, &new_custom_face([
786                    [Green, Red, Red],
787                    [Yellow, Blue, Blue],
788                    [Yellow, Green, Orange],
789                ]));
790    }
791
792    #[test]
793    fn test_middle_move_s() {
794        use GridSide::*;
795        use MoveDirection::*;
796
797        let mut grid = create_solved_grid();
798
799        grid.move_face(Top, Clockwise);
800        grid.move_face(Bottom, Clockwise);
801        grid.move_face(Right, Clockwise);
802        grid.move_face(Back, Clockwise);
803        grid.move_face(Top, Clockwise);
804
805        grid.move_face(MiddleZ, Clockwise);
806
807        let top = &grid.faces[Top.idx()];
808        assert_eq!(top, &new_custom_face([
809                    [White, White, Blue],
810                    [Blue, Orange, Red],
811                    [Orange, Green, Blue],
812                ]));
813
814        let right = &grid.faces[Right.idx()];
815        assert_eq!(right, &new_custom_face([
816                    [White, White, White],
817                    [Green, White, Yellow],
818                    [Green, Blue, Yellow],
819                ]));
820                
821        let bottom = &grid.faces[Bottom.idx()];
822        assert_eq!(bottom, &new_custom_face([
823                    [Yellow, Yellow, Red],
824                    [Red, Red, White],
825                    [Green, Orange, Blue],
826                ]));
827
828        let left = &grid.faces[Left.idx()];
829        assert_eq!(left, &new_custom_face([
830                    [Red, Yellow, Yellow],
831                    [White, Yellow, Orange],
832                    [White, Blue, Blue],
833                ]));
834
835    }
836
837    #[test]
838    fn test_middle_move_s_counter_clockwise() {
839        use GridSide::*;
840        use MoveDirection::*;
841
842        let mut grid = create_solved_grid();
843
844        grid.move_face(Top, Clockwise);
845        grid.move_face(Bottom, Clockwise);
846        grid.move_face(Right, Clockwise);
847        grid.move_face(Back, Clockwise);
848        grid.move_face(Top, Clockwise);
849
850        grid.move_face(MiddleZ, CounterClockwise);
851
852        let top = &grid.faces[Top.idx()];
853        assert_eq!(top, &new_custom_face([
854                    [White, White, Blue],
855                    [White, Red, Red],
856                    [Orange, Green, Blue],
857                ]));
858
859        let right = &grid.faces[Right.idx()];
860        assert_eq!(right, &new_custom_face([
861                    [White, Blue, White],
862                    [Green, Yellow, Yellow],
863                    [Green, Yellow, Yellow],
864                ]));
865                
866        let bottom = &grid.faces[Bottom.idx()];
867        assert_eq!(bottom, &new_custom_face([
868                    [Yellow, Yellow, Red],
869                    [Red, Orange, Blue],
870                    [Green, Orange, Blue],
871                ]));
872
873        let left = &grid.faces[Left.idx()];
874        assert_eq!(left, &new_custom_face([
875                    [Red, Blue, Yellow],
876                    [White, White, Orange],
877                    [White, White, Blue],
878                ]));
879
880    }
881
882    #[test]
883    fn test_middle_move_e() {
884        use GridSide::*;
885        use MoveDirection::*;
886
887        let mut grid = create_solved_grid();
888
889        grid.move_face(Front, Clockwise);
890        grid.move_face(Back, Clockwise);
891        grid.move_face(Right, Clockwise);
892        grid.move_face(Top, Clockwise);
893        grid.move_face(Front, Clockwise);
894
895        grid.move_face(MiddleY, Clockwise);
896
897        let front = &grid.faces[Front.idx()];
898        assert_eq!(front, &new_custom_face([
899                    [Green, Green, White],
900                    [White, Orange, Red],
901                    [Orange, Yellow, White],
902                ]));
903
904        let right = &grid.faces[Right.idx()];
905        assert_eq!(right, &new_custom_face([
906                    [Green, Blue, Blue],
907                    [Green, Green, White],
908                    [Green, Yellow, Yellow],
909                ]));
910                
911        let back = &grid.faces[Back.idx()];
912        assert_eq!(back, &new_custom_face([
913                    [White, Orange, Yellow],
914                    [Green, Red, Red],
915                    [Red, Blue, Blue],
916                ]));
917
918        let left = &grid.faces[Left.idx()];
919        assert_eq!(left, &new_custom_face([
920                    [Green, Green, Red],
921                    [White, Blue, Blue],
922                    [White, Orange, Blue],
923                ]));
924
925    }
926
927    #[test]
928    fn test_middle_move_e_counter_clockwise() {
929        use GridSide::*;
930        use MoveDirection::*;
931
932        let mut grid = create_solved_grid();
933
934        grid.move_face(Front, Clockwise);
935        grid.move_face(Back, Clockwise);
936        grid.move_face(Right, Clockwise);
937        grid.move_face(Top, Clockwise);
938        grid.move_face(Front, Clockwise);
939
940        grid.move_face(MiddleY, CounterClockwise);
941
942        let front = &grid.faces[Front.idx()];
943        assert_eq!(front, &new_custom_face([
944                    [Green, Green, White],
945                    [Green, Red, Red],
946                    [Orange, Yellow, White],
947                ]));
948
949        let right = &grid.faces[Right.idx()];
950        assert_eq!(right, &new_custom_face([
951                    [Green, Blue, Blue],
952                    [White, Blue, Blue],
953                    [Green, Yellow, Yellow],
954                ]));
955                
956        let back = &grid.faces[Back.idx()];
957        assert_eq!(back, &new_custom_face([
958                    [White, Orange, Yellow],
959                    [White, Orange, Red],
960                    [Red, Blue, Blue],
961                ]));
962
963        let left = &grid.faces[Left.idx()];
964        assert_eq!(left, &new_custom_face([
965                    [Green, Green, Red],
966                    [Green, Green, White],
967                    [White, Orange, Blue],
968                ]));
969
970    }
971
972    #[test]
973    fn test_solving_mixed_cube() {
974        use GridSide::*;
975        use MoveDirection::*;
976
977        let mut grid = create_mixed_grid();
978
979        let moves = vec![
980            (Bottom, Clockwise),
981            (Left, CounterClockwise),
982            (Front, Clockwise),
983            (Right, CounterClockwise),
984            
985            (Bottom, Clockwise),
986            (Right, Clockwise),
987            (Right, Clockwise),
988            (Left, Clockwise),
989
990            (Front, Clockwise),
991            (Left, CounterClockwise),
992            (Right, Clockwise),
993            (Right, Clockwise),
994
995            (Front, CounterClockwise),
996            (Top, Clockwise),
997            (Top, Clockwise),
998            (Back, CounterClockwise),
999
1000            (Right, Clockwise),
1001            (Right, Clockwise),
1002            (Back, Clockwise),
1003            (Top, Clockwise),
1004            (Top, Clockwise),
1005
1006            (Front, CounterClockwise),
1007            (Left, Clockwise),
1008            (Left, Clockwise),
1009
1010            (Top, Clockwise),
1011            (Top, Clockwise),
1012            (Back, Clockwise),
1013        ];
1014
1015        for (side, direction) in moves {
1016            grid.move_face(side, direction);
1017        }
1018
1019        assert!(assert_solved_cube(&grid))
1020    }
1021}