Browse Source

Adding check for cross pieces, and tuple mapping function.

Charles Reid 1 year ago
parent
commit
742a5e8d37
1 changed files with 551 additions and 0 deletions
  1. 551
    0
      rubikscubennnsolver/__init__.py

+ 551
- 0
rubikscubennnsolver/__init__.py View File

@@ -577,6 +577,557 @@ class RubiksCube(object):
577 577
                 return False
578 578
         return True
579 579
 
580
+
581
+    def rotation_map(self, action):
582
+        """
583
+        This returns a set of tuples
584
+        that correspond to the movements
585
+        of each piece on the cube
586
+        for the move "action".
587
+        """
588
+        results = []
589
+
590
+        if action[-1] in ("'", "`"):
591
+            reverse = True
592
+            action = action[0:-1]
593
+        else:
594
+            reverse = False
595
+
596
+        # 2Uw, Uw and 2U all mean rotate the top 2 U rows
597
+        # 3Uw and 3U mean rotate the top 3 U rows
598
+        if len(action) >= 2 and action[0].isdigit() and action[1].isdigit():
599
+            rows_to_rotate = int(action[0:2])
600
+            action = action[2:]
601
+        elif action[0].isdigit():
602
+            rows_to_rotate = int(action[0])
603
+            action = action[1:]
604
+        else:
605
+            # Uw also means rotate the top 2 U rows
606
+            if 'w' in action:
607
+                rows_to_rotate = 2
608
+            else:
609
+                rows_to_rotate = 1
610
+
611
+        # We've accounted for this so remove it
612
+        if 'w' in action:
613
+            action = action.replace('w', '')
614
+
615
+        # The digit at the end indicates how many quarter turns to do
616
+        if action[-1].isdigit():
617
+            quarter_turns = int(action[-1])
618
+            action = action[0:-1]
619
+        else:
620
+            quarter_turns = 1
621
+
622
+        side_name = action
623
+
624
+        # Skip moves x, y, z
625
+
626
+        side = self.sides[side_name]
627
+        min_pos = side.min_pos
628
+        max_pos = side.max_pos
629
+
630
+        # Rotation of the squares of the face itself
631
+        for turn in range(quarter_turns):
632
+
633
+            # Number the squares of the faces
634
+            # in a 2D array, then re-use all the
635
+            # existing transforms
636
+            oldface = []
637
+            counter = min_pos
638
+            for ii in range(self.size):
639
+                facerow = []
640
+                for jj in range(self.size):
641
+                    facerow.append(counter)
642
+                    counter += 1
643
+                oldface.append(facerow)
644
+
645
+            # This is not what we want, because it returns
646
+            # the face colors, not the face index numbers:
647
+            #oldface = side.get_face_as_2d_list()
648
+
649
+            if reverse:
650
+                newface = rotate_counter_clockwise(oldface)
651
+            else:
652
+                newface = rotate_clockwise(oldface)
653
+
654
+            oldface = compress_2d_list(oldface)
655
+            newface = compress_2d_list(newface)
656
+
657
+            for (j,k) in zip(oldface,newface):
658
+                results.append((j,k))
659
+
660
+
661
+
662
+        # Again skip rotation of entire cube with x, y, z
663
+
664
+
665
+        if side_name == "U":
666
+
667
+            for turn in range(quarter_turns):
668
+
669
+                # rotate the connecting row(s) of the surrounding sides
670
+                for row in range(rows_to_rotate):
671
+                    left_first_square = self.squares_per_side + 1 + (row * self.size)
672
+                    left_last_square = left_first_square + self.size - 1
673
+
674
+                    front_first_square = (self.squares_per_side * 2) + 1 + (row * self.size)
675
+                    front_last_square = front_first_square + self.size - 1
676
+
677
+                    right_first_square = (self.squares_per_side * 3) + 1 + (row * self.size)
678
+                    right_last_square = right_first_square + self.size - 1
679
+
680
+                    back_first_square = (self.squares_per_side * 4) + 1 + (row * self.size)
681
+                    back_last_square = back_first_square + self.size - 1
682
+
683
+                    if reverse:
684
+                        for square_index in range(left_first_square, left_last_square + 1):
685
+                            old_index = square_index
686
+                            new_index = square_index + (3 * self.squares_per_side)
687
+                            results.append((old_index,new_index))
688
+
689
+                        for square_index in range(front_first_square, front_last_square + 1):
690
+                            old_index = square_index
691
+                            new_index = square_index - self.squares_per_side
692
+                            results.append((old_index,new_index))
693
+
694
+                        for square_index in range(right_first_square, right_last_square + 1):
695
+                            old_index = square_index
696
+                            new_index = square_index - self.squares_per_side
697
+                            results.append((old_index,new_index))
698
+
699
+                        for square_index in range(back_first_square, back_last_square + 1):
700
+                            old_index = square_index
701
+                            new_index = square_index - self.squares_per_side
702
+                            results.append((old_index,new_index))
703
+
704
+                    else:
705
+                        for square_index in range(left_first_square, left_last_square + 1):
706
+                            old_index = square_index
707
+                            new_index = square_index + self.squares_per_side
708
+                            results.append((old_index,new_index))
709
+
710
+                        for square_index in range(front_first_square, front_last_square + 1):
711
+                            old_index = square_index
712
+                            new_index = square_index + self.squares_per_side
713
+                            results.append((old_index,new_index))
714
+
715
+                        for square_index in range(right_first_square, right_last_square + 1):
716
+                            old_index = square_index
717
+                            new_index = square_index + self.squares_per_side
718
+                            results.append((old_index,new_index))
719
+
720
+                        for square_index in range(back_first_square, back_last_square + 1):
721
+                            old_index = square_index
722
+                            new_index = square_index - (3 * self.squares_per_side)
723
+                            results.append((old_index,new_index))
724
+
725
+        elif side_name == "L":
726
+
727
+            for turn in range(quarter_turns):
728
+
729
+                # rotate the connecting row(s) of the surrounding sides
730
+                for row in range(rows_to_rotate):
731
+
732
+                    top_first_square = 1 + row
733
+                    top_last_square = top_first_square + ((self.size - 1) * self.size)
734
+
735
+                    front_first_square = (self.squares_per_side * 2) + 1 + row
736
+                    front_last_square = front_first_square + ((self.size - 1) * self.size)
737
+
738
+                    down_first_square = (self.squares_per_side * 5) + 1 + row
739
+                    down_last_square = down_first_square + ((self.size - 1) * self.size)
740
+
741
+                    back_first_square = (self.squares_per_side * 4) + self.size - row
742
+                    back_last_square = back_first_square + ((self.size - 1) * self.size)
743
+
744
+                    top_squares = []
745
+                    for square_index in range(top_first_square, top_last_square + 1, self.size):
746
+                        top_squares.append(square_index)
747
+
748
+                    front_squares = []
749
+                    for square_index in range(front_first_square, front_last_square + 1, self.size):
750
+                        front_squares.append(square_index)
751
+
752
+                    down_squares = []
753
+                    for square_index in range(down_first_square, down_last_square + 1, self.size):
754
+                        down_squares.append(square_index)
755
+
756
+                    back_squares = []
757
+                    for square_index in range(back_first_square, back_last_square + 1, self.size):
758
+                        back_squares.append(square_index)
759
+
760
+                    if reverse:
761
+                        for (index, square_index) in enumerate(range(top_first_square, top_last_square + 1, self.size)):
762
+                            old_index = square_index
763
+                            new_index = front_squares[index]
764
+                            results.append((old_index,new_index))
765
+
766
+                        for (index, square_index) in enumerate(range(front_first_square, front_last_square + 1, self.size)):
767
+                            old_index = square_index
768
+                            new_index = down_squares[index]
769
+                            results.append((old_index,new_index))
770
+
771
+                        back_squares = list(reversed(back_squares))
772
+                        for (index, square_index) in enumerate(range(down_first_square, down_last_square + 1, self.size)):
773
+                            old_index = square_index
774
+                            new_index = back_squares[index]
775
+                            results.append((old_index,new_index))
776
+
777
+                        top_squares = list(reversed(top_squares))
778
+                        for (index, square_index) in enumerate(range(back_first_square, back_last_square + 1, self.size)):
779
+                            old_index = square_index
780
+                            new_index = top_squares[index]
781
+                            results.append((old_index,new_index))
782
+
783
+                    else:
784
+                        back_squares = list(reversed(back_squares))
785
+                        for (index, square_index) in enumerate(range(top_first_square, top_last_square + 1, self.size)):
786
+                            old_index = square_index
787
+                            new_index = back_squares[index]
788
+                            results.append((old_index,new_index))
789
+
790
+                        for (index, square_index) in enumerate(range(front_first_square, front_last_square + 1, self.size)):
791
+                            old_index = square_index
792
+                            new_index = top_squares[index]
793
+                            results.append((old_index,new_index))
794
+
795
+                        for (index, square_index) in enumerate(range(down_first_square, down_last_square + 1, self.size)):
796
+                            old_index = square_index
797
+                            new_index = front_squares[index]
798
+                            results.append((old_index,new_index))
799
+
800
+                        down_squares = list(reversed(down_squares))
801
+                        for (index, square_index) in enumerate(range(back_first_square, back_last_square + 1, self.size)):
802
+                            old_index = square_index
803
+                            new_index = down_squares[index]
804
+                            results.append((old_index,new_index))
805
+
806
+        elif side_name == "F":
807
+
808
+            for turn in range(quarter_turns):
809
+
810
+                # rotate the connecting row(s) of the surrounding sides
811
+                for row in range(rows_to_rotate):
812
+                    top_first_square = (self.squares_per_side - self.size) + 1 - (row * self.size)
813
+                    top_last_square = top_first_square + self.size - 1
814
+
815
+                    left_first_square = self.squares_per_side + self.size - row
816
+                    left_last_square = left_first_square + ((self.size - 1) * self.size)
817
+
818
+                    down_first_square = (self.squares_per_side * 5) + 1 + (row * self.size)
819
+                    down_last_square = down_first_square + self.size - 1
820
+
821
+                    right_first_square = (self.squares_per_side * 3) + 1 + row
822
+                    right_last_square = right_first_square + ((self.size - 1) * self.size)
823
+
824
+                    #log.info("top first %d, last %d" % (top_first_square, top_last_square))
825
+                    #log.info("left first %d, last %d" % (left_first_square, left_last_square))
826
+                    #log.info("down first %d, last %d" % (down_first_square, down_last_square))
827
+                    #log.info("right first %d, last %d" % (right_first_square, right_last_square))
828
+
829
+                    top_squares = []
830
+                    for square_index in range(top_first_square, top_last_square + 1):
831
+                        top_squares.append(square_index)
832
+
833
+                    left_squares = []
834
+                    for square_index in range(left_first_square, left_last_square + 1, self.size):
835
+                        left_squares.append(square_index)
836
+
837
+                    down_squares = []
838
+                    for square_index in range(down_first_square, down_last_square + 1):
839
+                        down_squares.append(square_index)
840
+
841
+                    right_squares = []
842
+                    for square_index in range(right_first_square, right_last_square + 1, self.size):
843
+                        right_squares.append(square_index)
844
+
845
+                    if reverse:
846
+                        for (index, square_index) in enumerate(range(top_first_square, top_last_square + 1)):
847
+                            old_index = square_index
848
+                            new_index = right_squares[index]
849
+                            results.append((old_index,new_index))
850
+
851
+                        top_squares = list(reversed(top_squares))
852
+                        for (index, square_index) in enumerate(range(left_first_square, left_last_square + 1, self.size)):
853
+                            old_index = square_index
854
+                            new_index = top_squares[index]
855
+                            results.append((old_index,new_index))
856
+
857
+                        for (index, square_index) in enumerate(range(down_first_square, down_last_square + 1)):
858
+                            old_index = square_index
859
+                            new_index = left_squares[index]
860
+                            results.append((old_index,new_index))
861
+
862
+                        down_squares = list(reversed(down_squares))
863
+                        for (index, square_index) in enumerate(range(right_first_square, right_last_square + 1, self.size)):
864
+                            old_index = square_index
865
+                            new_index = down_squares[index]
866
+                            results.append((old_index,new_index))
867
+
868
+                    else:
869
+                        left_squares = list(reversed(left_squares))
870
+                        for (index, square_index) in enumerate(range(top_first_square, top_last_square + 1)):
871
+                            old_index = square_index
872
+                            new_index = left_squares[index]
873
+                            results.append((old_index,new_index))
874
+
875
+                        for (index, square_index) in enumerate(range(left_first_square, left_last_square + 1, self.size)):
876
+                            old_index = square_index
877
+                            new_index = down_squares[index]
878
+                            results.append((old_index,new_index))
879
+
880
+                        right_squares = list(reversed(right_squares))
881
+                        for (index, square_index) in enumerate(range(down_first_square, down_last_square + 1)):
882
+                            old_index = square_index
883
+                            new_index = right_squares[index]
884
+                            results.append((old_index,new_index))
885
+
886
+                        for (index, square_index) in enumerate(range(right_first_square, right_last_square + 1, self.size)):
887
+                            old_index = square_index
888
+                            new_index = top_squares[index]
889
+                            results.append((old_index,new_index))
890
+
891
+        elif side_name == "R":
892
+
893
+            for turn in range(quarter_turns):
894
+
895
+                # rotate the connecting row(s) of the surrounding sides
896
+                for row in range(rows_to_rotate):
897
+
898
+                    top_first_square = self.size - row
899
+                    top_last_square = self.squares_per_side
900
+
901
+                    front_first_square = (self.squares_per_side * 2) + self.size - row
902
+                    front_last_square = front_first_square + ((self.size - 1) * self.size)
903
+
904
+                    down_first_square = (self.squares_per_side * 5) + self.size - row
905
+                    down_last_square = down_first_square + ((self.size - 1) * self.size)
906
+
907
+                    back_first_square = (self.squares_per_side * 4) + 1 + row
908
+                    back_last_square = back_first_square + ((self.size - 1) * self.size)
909
+
910
+                    #log.info("top first %d, last %d" % (top_first_square, top_last_square))
911
+                    #log.info("front first %d, last %d" % (front_first_square, front_last_square))
912
+                    #log.info("down first %d, last %d" % (down_first_square, down_last_square))
913
+                    #log.info("back first %d, last %d" % (back_first_square, back_last_square))
914
+
915
+                    top_squares = []
916
+                    for square_index in range(top_first_square, top_last_square + 1, self.size):
917
+                        top_squares.append(square_index)
918
+
919
+                    front_squares = []
920
+                    for square_index in range(front_first_square, front_last_square + 1, self.size):
921
+                        front_squares.append(square_index)
922
+
923
+                    down_squares = []
924
+                    for square_index in range(down_first_square, down_last_square + 1, self.size):
925
+                        down_squares.append(square_index)
926
+
927
+                    back_squares = []
928
+                    for square_index in range(back_first_square, back_last_square + 1, self.size):
929
+                        back_squares.append(square_index)
930
+
931
+                    if reverse:
932
+                        back_squares = list(reversed(back_squares))
933
+                        for (index, square_index) in enumerate(range(top_first_square, top_last_square + 1, self.size)):
934
+                            old_index = square_index
935
+                            new_index = back_squares[index]
936
+                            results.append((old_index,new_index))
937
+
938
+                        for (index, square_index) in enumerate(range(front_first_square, front_last_square + 1, self.size)):
939
+                            old_index = square_index
940
+                            new_index = top_squares[index]
941
+                            results.append((old_index,new_index))
942
+
943
+                        for (index, square_index) in enumerate(range(down_first_square, down_last_square + 1, self.size)):
944
+                            old_index = square_index
945
+                            new_index = front_squares[index]
946
+                            results.append((old_index,new_index))
947
+
948
+                        down_squares = list(reversed(down_squares))
949
+                        for (index, square_index) in enumerate(range(back_first_square, back_last_square + 1, self.size)):
950
+                            old_index = square_index
951
+                            new_index = down_squares[index]
952
+                            results.append((old_index,new_index))
953
+
954
+                    else:
955
+                        for (index, square_index) in enumerate(range(top_first_square, top_last_square + 1, self.size)):
956
+                            old_index = square_index
957
+                            new_index = front_squares[index]
958
+                            results.append((old_index,new_index))
959
+
960
+                        for (index, square_index) in enumerate(range(front_first_square, front_last_square + 1, self.size)):
961
+                            old_index = square_index
962
+                            new_index = down_squares[index]
963
+                            results.append((old_index,new_index))
964
+
965
+                        back_squares = list(reversed(back_squares))
966
+                        for (index, square_index) in enumerate(range(down_first_square, down_last_square + 1, self.size)):
967
+                            old_index = square_index
968
+                            new_index = back_squares[index]
969
+                            results.append((old_index,new_index))
970
+
971
+                        top_squares = list(reversed(top_squares))
972
+                        for (index, square_index) in enumerate(range(back_first_square, back_last_square + 1, self.size)):
973
+                            old_index = square_index
974
+                            new_index = top_squares[index]
975
+                            results.append((old_index,new_index))
976
+
977
+        elif side_name == "B":
978
+
979
+            for turn in range(quarter_turns):
980
+
981
+                # rotate the connecting row(s) of the surrounding sides
982
+                for row in range(rows_to_rotate):
983
+                    top_first_square = 1 + (row * self.size)
984
+                    top_last_square = top_first_square + self.size - 1
985
+
986
+                    left_first_square = self.squares_per_side + 1 + row
987
+                    left_last_square = left_first_square + ((self.size - 1) * self.size)
988
+
989
+                    down_first_square = (self.squares_per_side * 6)  - self.size + 1 - (row * self.size)
990
+                    down_last_square = down_first_square + self.size - 1
991
+
992
+                    right_first_square = (self.squares_per_side * 3) + self.size - row
993
+                    right_last_square = right_first_square + ((self.size - 1) * self.size)
994
+
995
+                    #log.info("top first %d, last %d" % (top_first_square, top_last_square))
996
+                    #log.info("left first %d, last %d" % (left_first_square, left_last_square))
997
+                    #log.info("down first %d, last %d" % (down_first_square, down_last_square))
998
+                    #log.info("right first %d, last %d" % (right_first_square, right_last_square))
999
+
1000
+                    top_squares = []
1001
+                    for square_index in range(top_first_square, top_last_square + 1):
1002
+                        top_squares.append(square_index)
1003
+
1004
+                    left_squares = []
1005
+                    for square_index in range(left_first_square, left_last_square + 1, self.size):
1006
+                        left_squares.append(square_index)
1007
+
1008
+                    down_squares = []
1009
+                    for square_index in range(down_first_square, down_last_square + 1):
1010
+                        down_squares.append(square_index)
1011
+
1012
+                    right_squares = []
1013
+                    for square_index in range(right_first_square, right_last_square + 1, self.size):
1014
+                        right_squares.append(square_index)
1015
+
1016
+                    if reverse:
1017
+                        left_squares = list(reversed(left_squares))
1018
+                        for (index, square_index) in enumerate(range(top_first_square, top_last_square + 1)):
1019
+                            old_index = square_index
1020
+                            new_index = left_squares[index]
1021
+                            results.append((old_index,new_index))
1022
+
1023
+                        for (index, square_index) in enumerate(range(left_first_square, left_last_square + 1, self.size)):
1024
+                            old_index = square_index
1025
+                            new_index = down_squares[index]
1026
+                            results.append((old_index,new_index))
1027
+
1028
+                        right_squares = list(reversed(right_squares))
1029
+                        for (index, square_index) in enumerate(range(down_first_square, down_last_square + 1)):
1030
+                            old_index = square_index
1031
+                            new_index = right_squares[index]
1032
+                            results.append((old_index,new_index))
1033
+
1034
+                        for (index, square_index) in enumerate(range(right_first_square, right_last_square + 1, self.size)):
1035
+                            old_index = square_index
1036
+                            new_index = top_squares[index]
1037
+                            results.append((old_index,new_index))
1038
+
1039
+                    else:
1040
+                        for (index, square_index) in enumerate(range(top_first_square, top_last_square + 1)):
1041
+                            old_index = square_index
1042
+                            new_index = right_squares[index]
1043
+                            results.append((old_index,new_index))
1044
+
1045
+                        top_squares = list(reversed(top_squares))
1046
+                        for (index, square_index) in enumerate(range(left_first_square, left_last_square + 1, self.size)):
1047
+                            old_index = square_index
1048
+                            new_index = top_squares[index]
1049
+                            results.append((old_index,new_index))
1050
+
1051
+                        for (index, square_index) in enumerate(range(down_first_square, down_last_square + 1)):
1052
+                            old_index = square_index
1053
+                            new_index = left_squares[index]
1054
+                            results.append((old_index,new_index))
1055
+
1056
+                        down_squares = list(reversed(down_squares))
1057
+                        for (index, square_index) in enumerate(range(right_first_square, right_last_square + 1, self.size)):
1058
+                            old_index = square_index
1059
+                            new_index = down_squares[index]
1060
+                            results.append((old_index,new_index))
1061
+
1062
+        elif side_name == "D":
1063
+
1064
+            for turn in range(quarter_turns):
1065
+
1066
+                # rotate the connecting row(s) of the surrounding sides
1067
+                for row in range(rows_to_rotate):
1068
+                    left_first_square = (self.squares_per_side * 2) - self.size + 1 - (row * self.size)
1069
+                    left_last_square = left_first_square + self.size - 1
1070
+
1071
+                    front_first_square = (self.squares_per_side * 3) - self.size + 1 - (row * self.size)
1072
+                    front_last_square = front_first_square + self.size - 1
1073
+
1074
+                    right_first_square = (self.squares_per_side * 4) - self.size + 1 - (row * self.size)
1075
+                    right_last_square = right_first_square + self.size - 1
1076
+
1077
+                    back_first_square = (self.squares_per_side * 5) - self.size + 1 - (row * self.size)
1078
+                    back_last_square = back_first_square + self.size - 1
1079
+
1080
+                    #log.info("left first %d, last %d" % (left_first_square, left_last_square))
1081
+                    #log.info("front first %d, last %d" % (front_first_square, front_last_square))
1082
+                    #log.info("right first %d, last %d" % (right_first_square, right_last_square))
1083
+                    #log.info("back first %d, last %d" % (back_first_square, back_last_square))
1084
+
1085
+                    if reverse:
1086
+                        for square_index in range(left_first_square, left_last_square + 1):
1087
+                            old_index = square_index
1088
+                            new_index = square_index + self.squares_per_side
1089
+                            results.append((old_index,new_index))
1090
+
1091
+                        for square_index in range(front_first_square, front_last_square + 1):
1092
+                            old_index = square_index
1093
+                            new_index = square_index + self.squares_per_side
1094
+                            results.append((old_index,new_index))
1095
+
1096
+                        for square_index in range(right_first_square, right_last_square + 1):
1097
+                            old_index = square_index
1098
+                            new_index = square_index + self.squares_per_side
1099
+                            results.append((old_index,new_index))
1100
+
1101
+                        for square_index in range(back_first_square, back_last_square + 1):
1102
+                            old_index = square_index
1103
+                            new_index = square_index - (3 * self.squares_per_side)
1104
+                            results.append((old_index,new_index))
1105
+
1106
+                    else:
1107
+                        for square_index in range(left_first_square, left_last_square + 1):
1108
+                            old_index = square_index
1109
+                            new_index = square_index + (3 * self.squares_per_side)
1110
+                            results.append((old_index,new_index))
1111
+
1112
+                        for square_index in range(front_first_square, front_last_square + 1):
1113
+                            old_index = square_index
1114
+                            new_index = square_index - self.squares_per_side
1115
+                            results.append((old_index,new_index))
1116
+
1117
+                        for square_index in range(right_first_square, right_last_square + 1):
1118
+                            old_index = square_index
1119
+                            new_index = square_index - self.squares_per_side
1120
+                            results.append((old_index,new_index))
1121
+
1122
+                        for square_index in range(back_first_square, back_last_square + 1):
1123
+                            old_index = square_index
1124
+                            new_index = square_index - self.squares_per_side
1125
+                            results.append((old_index,new_index))
1126
+
1127
+        return results
1128
+
1129
+
1130
+
580 1131
     def rotate(self, action):
581 1132
         """
582 1133
         self.state is a dictionary where the key is the square_index and the