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 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 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 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 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), GridFace::new(Orange), GridFace::new(Green), GridFace::new(Red), GridFace::new(Blue), GridFace::new(Yellow), ],
562 }
563 }
564
565 fn create_mixed_grid() -> Grid {
566 Grid {
567 faces: [
568 new_custom_face([
570 [Red, White, Green],
571 [Green, White, Blue],
572 [White, Blue, Blue],
573 ]),
574 new_custom_face([
576 [Blue, Orange, Red],
577 [Yellow, Orange, Yellow],
578 [Green, Green, Orange],
579 ]),
580 new_custom_face([
582 [Blue, Red, Orange],
583 [Green, Green, Orange],
584 [Yellow, Yellow, Green],
585 ]),
586 new_custom_face([
588 [White, Orange, Orange],
589 [Yellow, Red, Orange],
590 [Red, Red, Green],
591 ]),
592 new_custom_face([
594 [Yellow, Green, Yellow],
595 [White, Blue, Red],
596 [White, White, White],
597 ]),
598 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}