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    pub fn print(&self) {
266        for row in self.grid.iter() {
267            for color in row {
268                print!("{}{}{}", color.to_ansi(), PRINT_CHAR, ANSI_RESET);
269            }
270            println!();
271        }
272    }
273
274    pub fn print_row(&self, idx: usize) {
275        for color in self.grid[idx] {
276            print!("{}{}{}", color.to_ansi(), PRINT_CHAR, ANSI_RESET);
277        }
278    }
279
280    pub fn rotate(&mut self, direction: &MoveDirection) {
281        match direction {
282            MoveDirection::Clockwise => self.rotate_clockwise(),
283            MoveDirection::CounterClockwise => self.rotate_counter_clockwise(),
284            MoveDirection::Double => {
285                self.rotate_clockwise();
286                self.rotate_clockwise();
287            }
288        }
289    }
290
291    pub fn rotate_clockwise(&mut self) {
292        // rotate corners
293        let tmp = self.grid[0][0];
294        self.grid[0][0] = self.grid[2][0];
295        self.grid[2][0] = self.grid[2][2];
296        self.grid[2][2] = self.grid[0][2];
297        self.grid[0][2] = tmp;
298
299        // rotate edges
300        let tmp = self.grid[0][1];
301        self.grid[0][1] = self.grid[1][0];
302        self.grid[1][0] = self.grid[2][1];
303        self.grid[2][1] = self.grid[1][2];
304        self.grid[1][2] = tmp;
305    }
306
307    pub fn rotate_counter_clockwise(&mut self) {
308        // rotate corners
309        let tmp = self.grid[0][0];
310        self.grid[0][0] = self.grid[0][2];
311        self.grid[0][2] = self.grid[2][2];
312        self.grid[2][2] = self.grid[2][0];
313        self.grid[2][0] = tmp;
314
315        // rotate edges
316        let tmp = self.grid[0][1];
317        self.grid[0][1] = self.grid[1][2];
318        self.grid[1][2] = self.grid[2][1];
319        self.grid[2][1] = self.grid[1][0];
320        self.grid[1][0] = tmp;
321    }
322}
323
324pub struct Grid {
325    pub faces: [GridFace; 6],
326}
327
328impl Grid {
329    pub fn new() -> Grid {
330        Grid {
331            faces: [
332                GridFace::new(Color::White),
333                GridFace::new(Color::Orange),
334                GridFace::new(Color::Green),
335                GridFace::new(Color::Red),
336                GridFace::new(Color::Blue),
337                GridFace::new(Color::Yellow),
338            ]
339        }
340    }
341
342    pub fn apply_move(&mut self, mv: CubeMove) {
343        self.move_face(mv.grid_side, mv.direction);
344    }
345
346    pub fn print(&self) {
347        fn print_blank_row() {
348            for _ in 0..3 {
349                print!("{}{}{}", Color::Gray.to_ansi(), PRINT_CHAR, ANSI_RESET);
350            }
351        }
352
353        for row in 0..3 {
354            print_blank_row();
355            self.faces[0].print_row(row);
356            print_blank_row();
357            print_blank_row();
358            println!();
359        }
360
361        for row in 0..3 {
362            for face in 1..5 {
363                self.faces[face].print_row(row);
364            }
365            println!();
366        }
367
368        for row in 0..3 {
369            print_blank_row();
370            self.faces[5].print_row(row);
371            print_blank_row();
372            print_blank_row();
373            println!();
374        }
375
376        print!("\n\n\n");
377    }
378
379    fn rotate_buffers(buffers: &mut Vec<[Color; 3]>, grid_side: &GridSide, direction: MoveDirection) {
380        match grid_side {
381            GridSide::Left 
382                | GridSide::Top
383                | GridSide::Front
384                | GridSide::MiddleX
385                | GridSide::MiddleZ => match direction {
386                MoveDirection::Clockwise => buffers.rotate_right(1),
387                MoveDirection::CounterClockwise => buffers.rotate_left(1),
388                MoveDirection::Double => buffers.rotate_right(2),
389            }
390            _ => match direction {
391                MoveDirection::Clockwise => buffers.rotate_left(1),
392                MoveDirection::CounterClockwise => buffers.rotate_right(1),
393                MoveDirection::Double => buffers.rotate_right(2),
394            }
395        };
396        
397    }
398
399    pub fn move_face(&mut self, side: GridSide, direction: MoveDirection) {
400        if !side.is_middle() {
401            let idx = side.idx();
402            self.faces[idx].rotate(&direction);
403        }
404
405        let neighbors = self.get_neighbors(side);
406        let mut buffers: Vec<[Color; 3]> = neighbors.iter()
407            .map(|ns| {
408                    ns.read_from(self)
409                }
410            )
411            .collect();
412
413        Grid::rotate_buffers(&mut buffers, &side, direction);
414
415        for (slice, colors) in neighbors.into_iter().zip(buffers) {
416            slice.write_to(self, colors);
417        }        
418    }
419
420    pub fn get_neighbors(&self, side: GridSide) -> [NeighborSlice; 4] {
421        match side {
422            GridSide::Top => [
423                NeighborSlice {slice_type: SliceType::Top, side: GridSide::Back},
424                NeighborSlice {slice_type: SliceType::Top, side: GridSide::Right},
425                NeighborSlice {slice_type: SliceType::Top, side: GridSide::Front},
426                NeighborSlice {slice_type: SliceType::Top, side: GridSide::Left},
427            ],
428            GridSide::Front => [
429                NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Top},
430                NeighborSlice {slice_type: SliceType::Left, side: GridSide::Right},
431                NeighborSlice {slice_type: SliceType::Top, side: GridSide::Bottom},
432                NeighborSlice {slice_type: SliceType::Right, side: GridSide::Left},
433            ],
434            GridSide::Bottom => [
435                NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Back},
436                NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Right},
437                NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Front},
438                NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Left},
439            ],
440            GridSide::Left => [
441                NeighborSlice {slice_type: SliceType::Left, side: GridSide::Top},
442                NeighborSlice {slice_type: SliceType::Left, side: GridSide::Front},
443                NeighborSlice {slice_type: SliceType::Left, side: GridSide::Bottom},
444                NeighborSlice {slice_type: SliceType::Right, side: GridSide::Back},
445            ],
446            GridSide::Right => [
447                NeighborSlice {slice_type: SliceType::Right, side: GridSide::Top},
448                NeighborSlice {slice_type: SliceType::Right, side: GridSide::Front},
449                NeighborSlice {slice_type: SliceType::Right, side: GridSide::Bottom},
450                NeighborSlice {slice_type: SliceType::Left, side: GridSide::Back},
451            ],
452            GridSide::Back => [
453                NeighborSlice {slice_type: SliceType::Top, side: GridSide::Top},
454                NeighborSlice {slice_type: SliceType::Right, side: GridSide::Right},
455                NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Bottom},
456                NeighborSlice {slice_type: SliceType::Left, side: GridSide::Left},
457            ],
458            GridSide::MiddleX => [
459                NeighborSlice {slice_type: SliceType::Vertical, side: GridSide::Top},
460                NeighborSlice {slice_type: SliceType::Vertical, side: GridSide::Front},
461                NeighborSlice {slice_type: SliceType::Vertical, side: GridSide::Bottom},
462                NeighborSlice {slice_type: SliceType::VerticalFlipped, side: GridSide::Back},
463            ],
464            GridSide::MiddleY => [
465                NeighborSlice {slice_type: SliceType::Horizontal, side: GridSide::Back},
466                NeighborSlice {slice_type: SliceType::Horizontal, side: GridSide::Right},
467                NeighborSlice {slice_type: SliceType::Horizontal, side: GridSide::Front},
468                NeighborSlice {slice_type: SliceType::Horizontal, side: GridSide::Left},
469            ],
470            GridSide::MiddleZ => [
471                NeighborSlice {slice_type: SliceType::HorizontalFlipped, side: GridSide::Top},
472                NeighborSlice {slice_type: SliceType::Vertical, side: GridSide::Right},
473                NeighborSlice {slice_type: SliceType::Horizontal, side: GridSide::Bottom},
474                NeighborSlice {slice_type: SliceType::VerticalFlipped, side: GridSide::Left},
475            ],
476        }
477    }
478}
479
480#[cfg(test)]
481mod tests {
482    use super::*;
483    use crate::utils::cube_utils::Color;
484    use Color::*;
485
486    fn assert_whole_color(grid: &Grid, side: GridSide, color: Color) -> bool {
487        let face = &grid.faces[side.idx()];
488        for row in face.grid {
489            for c in row {
490                if c != color {
491                    return false;
492                }
493            }
494        };
495        true
496    }
497
498    fn assert_right_color(grid: &Grid, side: GridSide, color: Color) -> bool {
499        let face_grid = &grid.faces[side.idx()].grid;
500        face_grid[0][2] == color && face_grid[1][2] == color && face_grid[2][2] == color
501    }
502
503    fn assert_left_color(grid: &Grid, side: GridSide, color: Color) -> bool {
504        let face_grid = &grid.faces[side.idx()].grid;
505        face_grid[0][0] == color && face_grid[1][0] == color && face_grid[2][0] == color
506    }
507
508    fn assert_top_color(grid: &Grid, side: GridSide, color: Color) -> bool {
509        let face_grid = &grid.faces[side.idx()].grid;
510        face_grid[0][0] == color && face_grid[0][1] == color && face_grid[0][2] == color
511    }
512
513    fn assert_bottom_color(grid: &Grid, side: GridSide, color: Color) -> bool {
514        let face_grid = &grid.faces[side.idx()].grid;
515        face_grid[2][0] == color && face_grid[2][1] == color && face_grid[2][2] == color
516    }
517
518    fn assert_solved_cube(grid: &Grid) -> bool {
519        assert_whole_color(grid, GridSide::Top, Color::White) 
520            && assert_whole_color(grid, GridSide::Left, Color::Orange)
521            && assert_whole_color(grid, GridSide::Front, Color::Green)
522            && assert_whole_color(grid, GridSide::Right, Color::Red)
523            && assert_whole_color(grid, GridSide::Back, Color::Blue)
524            && assert_whole_color(grid, GridSide::Bottom, Color::Yellow)
525    }
526
527    fn new_custom_face(grid: [[Color; 3]; 3]) -> GridFace {
528        GridFace { grid }
529    }
530
531    fn create_solved_grid() -> Grid {
532        Grid {
533            faces: [
534                GridFace::new(White),   // TOP
535                GridFace::new(Orange),  // LEFT
536                GridFace::new(Green),   // FRONT
537                GridFace::new(Red),     // RIGHT
538                GridFace::new(Blue),    // BACK
539                GridFace::new(Yellow),  // BOTTOM
540            ],
541        }
542    }
543
544    fn create_mixed_grid() -> Grid {
545        Grid {
546            faces: [
547                // TOP
548                new_custom_face([
549                    [Red, White, Green],
550                    [Green, White, Blue],
551                    [White, Blue, Blue],
552                ]),
553                // LEFT
554                new_custom_face([
555                    [Blue, Orange, Red],
556                    [Yellow, Orange, Yellow],
557                    [Green, Green, Orange],
558                ]),
559                // FRONT
560                new_custom_face([
561                    [Blue, Red, Orange],
562                    [Green, Green, Orange],
563                    [Yellow, Yellow, Green],
564                ]),
565                // RIGHT
566                new_custom_face([
567                    [White, Orange, Orange],
568                    [Yellow, Red, Orange],
569                    [Red, Red, Green],
570                ]),
571                // BACK
572                new_custom_face([
573                    [Yellow, Green, Yellow],
574                    [White, Blue, Red],
575                    [White, White, White],
576                ]),
577                // BOTTOM
578                new_custom_face([
579                    [Blue, Blue, Yellow],
580                    [Red, Yellow, White],
581                    [Orange, Blue, Red],
582                ]),
583            ],
584        }
585    }
586
587    #[test]
588    fn test_move_right() {
589        let mut grid = create_solved_grid();
590        grid.move_face(GridSide::Right, MoveDirection::Clockwise);
591        
592        assert!(assert_whole_color(&grid, GridSide::Right, Color::Red));
593        assert!(assert_right_color(&grid, GridSide::Front, Color::Yellow));
594        assert!(assert_right_color(&grid, GridSide::Top, Color::Green));
595        assert!(assert_left_color(&grid, GridSide::Back, Color::White));
596        assert!(assert_right_color(&grid, GridSide::Bottom, Color::Blue));
597
598        grid.move_face(GridSide::Right, MoveDirection::CounterClockwise);
599
600        assert!(assert_solved_cube(&grid));
601    }
602
603    #[test]
604    fn test_move_left() {
605        let mut grid = create_solved_grid();
606        grid.move_face(GridSide::Left, MoveDirection::Clockwise);
607
608        assert!(assert_whole_color(&grid, GridSide::Left, Color::Orange));
609        assert!(assert_left_color(&grid, GridSide::Front, Color::White));
610        assert!(assert_left_color(&grid, GridSide::Top, Color::Blue));
611        assert!(assert_right_color(&grid, GridSide::Back, Color::Yellow));
612        assert!(assert_left_color(&grid, GridSide::Bottom, Color::Green));
613
614        grid.move_face(GridSide::Left, MoveDirection::CounterClockwise);
615
616        assert!(assert_solved_cube(&grid));
617    }
618
619    #[test]
620    fn test_move_front() {
621        let mut grid = create_solved_grid();
622        grid.move_face(GridSide::Front, MoveDirection::Clockwise);
623
624        assert!(assert_whole_color(&grid, GridSide::Front, Color::Green));
625        assert!(assert_bottom_color(&grid, GridSide::Top, Color::Orange));
626        assert!(assert_left_color(&grid, GridSide::Right, Color::White));
627        assert!(assert_top_color(&grid, GridSide::Bottom, Color::Red));
628        assert!(assert_right_color(&grid, GridSide::Left, Color::Yellow));
629
630        grid.move_face(GridSide::Front, MoveDirection::CounterClockwise);
631
632        assert!(assert_solved_cube(&grid));
633    }
634
635    #[test]
636    fn test_move_top() {
637        let mut grid = create_solved_grid();
638        grid.move_face(GridSide::Top, MoveDirection::Clockwise);
639
640        assert!(assert_whole_color(&grid, GridSide::Top, Color::White));
641        assert!(assert_top_color(&grid, GridSide::Front, Color::Red));
642        assert!(assert_top_color(&grid, GridSide::Left, Color::Green));
643        assert!(assert_top_color(&grid, GridSide::Right, Color::Blue));
644        assert!(assert_top_color(&grid, GridSide::Back, Color::Orange));
645
646        grid.move_face(GridSide::Top, MoveDirection::CounterClockwise);
647
648        assert!(assert_solved_cube(&grid));
649    }
650
651    #[test]
652    fn test_move_bottom() {
653        let mut grid = create_solved_grid();
654        grid.move_face(GridSide::Bottom, MoveDirection::Clockwise);
655
656        assert!(assert_whole_color(&grid, GridSide::Bottom, Color::Yellow));
657        assert!(assert_bottom_color(&grid, GridSide::Front, Color::Orange));
658        assert!(assert_bottom_color(&grid, GridSide::Left, Color::Blue));
659        assert!(assert_bottom_color(&grid, GridSide::Right, Color::Green));
660        assert!(assert_bottom_color(&grid, GridSide::Back, Color::Red));
661
662        grid.move_face(GridSide::Bottom, MoveDirection::CounterClockwise);
663
664        assert!(assert_solved_cube(&grid));
665    }
666
667    #[test]
668    fn test_move_back() {
669        let mut grid = create_solved_grid();
670        grid.move_face(GridSide::Back, MoveDirection::Clockwise);
671
672        assert!(assert_whole_color(&grid, GridSide::Back, Color::Blue));
673        assert!(assert_top_color(&grid, GridSide::Top, Color::Red));
674        assert!(assert_right_color(&grid, GridSide::Right, Color::Yellow));
675        assert!(assert_left_color(&grid, GridSide::Left, Color::White));
676        assert!(assert_bottom_color(&grid, GridSide::Bottom, Color::Orange));
677
678        grid.move_face(GridSide::Back, MoveDirection::CounterClockwise);
679
680        assert!(assert_solved_cube(&grid));
681    }
682
683    #[test]
684    fn test_middle_move_m() {
685        use GridSide::*;
686        use MoveDirection::*;
687
688        let mut grid = create_solved_grid();
689
690        grid.move_face(Top, Clockwise);
691        grid.move_face(Bottom, Clockwise);
692        grid.move_face(Front, Clockwise);
693        grid.move_face(Right, Clockwise);
694        grid.move_face(Top, Clockwise);
695        
696        grid.move_face(MiddleX, Clockwise);
697
698        let front = &grid.faces[Front.idx()];
699        assert_eq!(front, &new_custom_face([
700                    [White, White, White],
701                    [Orange, White, Yellow],
702                    [Orange, Red, Yellow],
703                ]));
704
705        let top = &grid.faces[Top.idx()];
706        assert_eq!(top, &new_custom_face([
707                    [Blue, Red, White],
708                    [Orange, Blue, White],
709                    [Red, Green, Red],
710                ]));
711
712        let back = &grid.faces[Back.idx()];
713        assert_eq!(back, &new_custom_face([
714                    [Green, Yellow, Yellow],
715                    [White, Yellow, Blue],
716                    [White, Red, Red],
717                ]));
718
719        let bottom = &grid.faces[Bottom.idx()];
720        assert_eq!(bottom, &new_custom_face([
721                    [Green, White, Red],
722                    [Yellow, Green, Blue],
723                    [Yellow, Green, Orange],
724                ]));
725    }
726
727    #[test]
728    fn test_middle_move_m_counter_clockwise() {
729        use GridSide::*;
730        use MoveDirection::*;
731
732        let mut grid = create_solved_grid();
733
734        grid.move_face(Top, Clockwise);
735        grid.move_face(Bottom, Clockwise);
736        grid.move_face(Front, Clockwise);
737        grid.move_face(Right, Clockwise);
738        grid.move_face(Top, Clockwise);
739        
740        grid.move_face(MiddleX, CounterClockwise);
741
742        let front = &grid.faces[Front.idx()];
743        assert_eq!(front, &new_custom_face([
744                    [White, Red, White],
745                    [Orange, Yellow, Yellow],
746                    [Orange, Yellow, Yellow],
747                ]));
748
749        let top = &grid.faces[Top.idx()];
750        assert_eq!(top, &new_custom_face([
751                    [Blue, White, White],
752                    [Orange, Green, White],
753                    [Red, Green, Red],
754                ]));
755
756        let back = &grid.faces[Back.idx()];
757        assert_eq!(back, &new_custom_face([
758                    [Green, Red, Yellow],
759                    [White, White, Blue],
760                    [White, White, Red],
761                ]));
762
763        let bottom = &grid.faces[Bottom.idx()];
764        assert_eq!(bottom, &new_custom_face([
765                    [Green, Red, Red],
766                    [Yellow, Blue, Blue],
767                    [Yellow, Green, Orange],
768                ]));
769    }
770
771    #[test]
772    fn test_middle_move_s() {
773        use GridSide::*;
774        use MoveDirection::*;
775
776        let mut grid = create_solved_grid();
777
778        grid.move_face(Top, Clockwise);
779        grid.move_face(Bottom, Clockwise);
780        grid.move_face(Right, Clockwise);
781        grid.move_face(Back, Clockwise);
782        grid.move_face(Top, Clockwise);
783
784        grid.move_face(MiddleZ, Clockwise);
785
786        let top = &grid.faces[Top.idx()];
787        assert_eq!(top, &new_custom_face([
788                    [White, White, Blue],
789                    [Blue, Orange, Red],
790                    [Orange, Green, Blue],
791                ]));
792
793        let right = &grid.faces[Right.idx()];
794        assert_eq!(right, &new_custom_face([
795                    [White, White, White],
796                    [Green, White, Yellow],
797                    [Green, Blue, Yellow],
798                ]));
799                
800        let bottom = &grid.faces[Bottom.idx()];
801        assert_eq!(bottom, &new_custom_face([
802                    [Yellow, Yellow, Red],
803                    [Red, Red, White],
804                    [Green, Orange, Blue],
805                ]));
806
807        let left = &grid.faces[Left.idx()];
808        assert_eq!(left, &new_custom_face([
809                    [Red, Yellow, Yellow],
810                    [White, Yellow, Orange],
811                    [White, Blue, Blue],
812                ]));
813
814    }
815
816    #[test]
817    fn test_middle_move_s_counter_clockwise() {
818        use GridSide::*;
819        use MoveDirection::*;
820
821        let mut grid = create_solved_grid();
822
823        grid.move_face(Top, Clockwise);
824        grid.move_face(Bottom, Clockwise);
825        grid.move_face(Right, Clockwise);
826        grid.move_face(Back, Clockwise);
827        grid.move_face(Top, Clockwise);
828
829        grid.move_face(MiddleZ, CounterClockwise);
830
831        let top = &grid.faces[Top.idx()];
832        assert_eq!(top, &new_custom_face([
833                    [White, White, Blue],
834                    [White, Red, Red],
835                    [Orange, Green, Blue],
836                ]));
837
838        let right = &grid.faces[Right.idx()];
839        assert_eq!(right, &new_custom_face([
840                    [White, Blue, White],
841                    [Green, Yellow, Yellow],
842                    [Green, Yellow, Yellow],
843                ]));
844                
845        let bottom = &grid.faces[Bottom.idx()];
846        assert_eq!(bottom, &new_custom_face([
847                    [Yellow, Yellow, Red],
848                    [Red, Orange, Blue],
849                    [Green, Orange, Blue],
850                ]));
851
852        let left = &grid.faces[Left.idx()];
853        assert_eq!(left, &new_custom_face([
854                    [Red, Blue, Yellow],
855                    [White, White, Orange],
856                    [White, White, Blue],
857                ]));
858
859    }
860
861    #[test]
862    fn test_middle_move_e() {
863        use GridSide::*;
864        use MoveDirection::*;
865
866        let mut grid = create_solved_grid();
867
868        grid.move_face(Front, Clockwise);
869        grid.move_face(Back, Clockwise);
870        grid.move_face(Right, Clockwise);
871        grid.move_face(Top, Clockwise);
872        grid.move_face(Front, Clockwise);
873
874        grid.move_face(MiddleY, Clockwise);
875
876        let front = &grid.faces[Front.idx()];
877        assert_eq!(front, &new_custom_face([
878                    [Green, Green, White],
879                    [White, Orange, Red],
880                    [Orange, Yellow, White],
881                ]));
882
883        let right = &grid.faces[Right.idx()];
884        assert_eq!(right, &new_custom_face([
885                    [Green, Blue, Blue],
886                    [Green, Green, White],
887                    [Green, Yellow, Yellow],
888                ]));
889                
890        let back = &grid.faces[Back.idx()];
891        assert_eq!(back, &new_custom_face([
892                    [White, Orange, Yellow],
893                    [Green, Red, Red],
894                    [Red, Blue, Blue],
895                ]));
896
897        let left = &grid.faces[Left.idx()];
898        assert_eq!(left, &new_custom_face([
899                    [Green, Green, Red],
900                    [White, Blue, Blue],
901                    [White, Orange, Blue],
902                ]));
903
904    }
905
906    #[test]
907    fn test_middle_move_e_counter_clockwise() {
908        use GridSide::*;
909        use MoveDirection::*;
910
911        let mut grid = create_solved_grid();
912
913        grid.move_face(Front, Clockwise);
914        grid.move_face(Back, Clockwise);
915        grid.move_face(Right, Clockwise);
916        grid.move_face(Top, Clockwise);
917        grid.move_face(Front, Clockwise);
918
919        grid.move_face(MiddleY, CounterClockwise);
920
921        let front = &grid.faces[Front.idx()];
922        assert_eq!(front, &new_custom_face([
923                    [Green, Green, White],
924                    [Green, Red, Red],
925                    [Orange, Yellow, White],
926                ]));
927
928        let right = &grid.faces[Right.idx()];
929        assert_eq!(right, &new_custom_face([
930                    [Green, Blue, Blue],
931                    [White, Blue, Blue],
932                    [Green, Yellow, Yellow],
933                ]));
934                
935        let back = &grid.faces[Back.idx()];
936        assert_eq!(back, &new_custom_face([
937                    [White, Orange, Yellow],
938                    [White, Orange, Red],
939                    [Red, Blue, Blue],
940                ]));
941
942        let left = &grid.faces[Left.idx()];
943        assert_eq!(left, &new_custom_face([
944                    [Green, Green, Red],
945                    [Green, Green, White],
946                    [White, Orange, Blue],
947                ]));
948
949    }
950
951    #[test]
952    fn test_solving_mixed_cube() {
953        use GridSide::*;
954        use MoveDirection::*;
955
956        let mut grid = create_mixed_grid();
957
958        let moves = vec![
959            (Bottom, Clockwise),
960            (Left, CounterClockwise),
961            (Front, Clockwise),
962            (Right, CounterClockwise),
963            
964            (Bottom, Clockwise),
965            (Right, Clockwise),
966            (Right, Clockwise),
967            (Left, Clockwise),
968
969            (Front, Clockwise),
970            (Left, CounterClockwise),
971            (Right, Clockwise),
972            (Right, Clockwise),
973
974            (Front, CounterClockwise),
975            (Top, Clockwise),
976            (Top, Clockwise),
977            (Back, CounterClockwise),
978
979            (Right, Clockwise),
980            (Right, Clockwise),
981            (Back, Clockwise),
982            (Top, Clockwise),
983            (Top, Clockwise),
984
985            (Front, CounterClockwise),
986            (Left, Clockwise),
987            (Left, Clockwise),
988
989            (Top, Clockwise),
990            (Top, Clockwise),
991            (Back, Clockwise),
992        ];
993
994        for (side, direction) in moves {
995            grid.move_face(side, direction);
996        }
997
998        assert!(assert_solved_cube(&grid))
999    }
1000}