题目说明:
YYYYRRRRWWWWOOOOGGGGBBBB UUL'
第一行为输入为对应F, R, B, L, U, D
面的元素颜色
第二行输入为翻转的标识符
标识符有:F、F'、R、R'、B、B'、L、L'、U、U'、D、D'
。分别为对应明的顺时针翻转和逆时针翻转。带'
则为逆时针,不带则为顺时针
输入示意图:
输出说明:
BWBYOORRYGWGORORWGYGWBYB
-
示例图【无需输出,仅理解】:
输出翻转后最终对应位置F, R, B, L, U, D
的颜色序列
题解:
-
-
要理解题目中,每个转动的模拟情况,每个面的转动会影响那些面
-
旋转面的影响方框【元素】依次是什么,
-
这里以以U移动举例:
-
U移动会带动L、F、R、B【顺序可以改,但必须保证前后对应的面相等,因为带动顺序也很关键】
-
每个面划分为2*2的矩阵,那么,L会影响的元素方位是(0,0) (0,1)。F会影响的也是(0,0) (0,1)
-
分别模拟出每个面依次对照的影响元素的位置
-
-
-
获取每个影响元素的方位
-
就可以编码了,难点在于如何理解每一个面的转动以及他所带动的面的元素是什么,每一个面的带动情况是不一样的
-
难度:
复杂度高,找到移动影响序列比较繁琐,编码难度中等
编码
-
构建常量以及每一个面的两个序列【面移动序列,面中受影响所移动的位置序列】:
Sn, Ni = 0, 1 #常量Sn代表顺时针,Ni代表逆时针 F, R, B, L, U, D = 0,1,2,3,4,5 #随意,我只是根据题目来而已 two_d_matrix = [[0,0,0,0] for i in range(6)] #批量初始化6个面。每一个面有2*2就是4个元素,这个使用一维数组代替是因为如果使用二级数组会很麻烦 Fr = [U, R, D, L] #Xr代表的是 X个面中,移动的4个面序列 Fm = [(2,3), (0, 2), (1, 0), (3, 1)] #Xm代表的是每个面依次对照的影响元素的位置默认全为顺时针方向【本来应该是(0,0)~(1,1)二进制化就好了】 Lr = [U, F, D, B] Lm = [(0,2), (0, 2), (0, 2), (3, 1)] Dr = [F, R, B, L] Dm = [(2,3), (2, 3), (2, 3), (2, 3)] Rr = [D, F, U, B] Rm = [(3,1), (3, 1), (3, 1), (0, 2)] Ur = [F, L, B, R] Um = [(1,0), (1, 0), (1, 0), (1, 0)] Br = [R, U, L, D] Bm = [(3,1), (1, 0), (0, 2), (2, 3)] #输入的转动映射 char_to_turn = {'U':(U,Sn), "U'":(U, Ni), "F":(F,Sn),"F'":(F,Ni) , "L":(L,Sn),"L'":(L,Ni), "D":(D,Sn) ,"D'":(D,Ni) , "R":(R,Sn), "R'":(R,Ni), "B":(B, Sn), "B'":(B, Ni)} #全部面的关联面序列以及影响移动框序列,上面的二层抽象,方便后续操作 X_r = {F:Fr, R:Rr, B:Br, L:Lr, U:Ur, D:Dr} X_m = {F:Fm, R:Rm, B:Bm, L:Lm, U:Um, D:Dm}
-
将X面翻转(仅单面模拟,不对其他4个移动面进行模拟)以及获取对应值的方法
1 def trun_X_round(round_name:int, S_or_N:int): 2 """ 3 将X面进行翻转 4 :param round_name: 输入翻转的面常量 5 :param S_or_N: 输入顺时针或者是逆时针 6 """ 7 x_round = two_d_matrix[round_name] 8 new_round = copy.deepcopy(x_round)#一定要深拷贝,不然好像是会直接修改,因为浅复制是映射到同一个指针 9 if S_or_N == Sn: #根据转向去翻转,顺序无所谓,逻辑要一致,这里使用了两个数组来简化,0-3类比为二进制(x,y)就像x={0,1} y={0,1} 10 new_round[1] = x_round[0] 11 new_round[3] = x_round[1] 12 new_round[2] = x_round[3] 13 new_round[0] = x_round[2] 14 else: 15 new_round[1] = x_round[0] 16 new_round[3] = x_round[1] 17 new_round[2] = x_round[3] 18 new_round[0] = x_round[2] 19 # print(new_round) #输出测试 20 two_d_matrix[round_name] = new_round 21 22 def get_value(X_round:int, idx:tuple):#获取某个索引的值,返回的以面为单位,如["G","G"] 23 return [ 24 two_d_matrix[X_round][idx[0]], two_d_matrix[X_round][idx[1]] 25 ]
-
翻转其他部分:
1 def trun_other_round_Sn(X_round:int): 2 """ 3 翻转X影响的其他部分【受X干扰的面】 4 :param X_round:输入面常量 5 """ 6 Xr = X_r[X_round] #获取所选面X的关联面序列,下为影响移动框序列 7 Xm_ori = X_m[X_round] 8 temp_value = [get_value(Xr[i], Xm_ori[i]) for i in range(4)] #批量保存原移动框的值,方便后续覆盖 9 #因为顺时针,所以第一个索引[0]移动后实际上变为最后一个[3]可以理解为循环链表,因为第一个比较特殊,拎出来做一次,理解了这个循环其实就是剩下3个idx[1,2,3]的移动 10 two_d_matrix[Xr[0]][Xm_ori[0][0]], two_d_matrix[Xr[0]][Xm_ori[0][1]] = temp_value[3][0], temp_value[3][1] 11 for idx, Xm in enumerate(Xm_ori): 12 if idx > 0: 13 #每次顺时针旋转,当前面的两个元素变为前一个面的两个元素,因为一个面有两个影响元素,temp_value以列表存储,每个存储两个元素列表,不理解调试一下就好了 14 two_d_matrix[Xr[idx]][Xm[0]] , two_d_matrix[Xr[idx]][Xm[1]] = temp_value[idx-1][0], temp_value[idx-1][1] 15 # print(two_d_matrix) 16 17 return 18 def trun_other_round_Ni(X_round:int): 19 #就是翻转了一下,就ok了,其他不影响,因为怎么转,点之间都是对应的 20 Xr = list(reversed(X_r[X_round])) 21 Xm_ori = list(reversed(X_m[X_round])) 22 temp_value = [get_value(Xr[i], Xm_ori[i]) for i in range(4)] 23 24 two_d_matrix[Xr[0]][Xm_ori[0][0]], two_d_matrix[Xr[0]][Xm_ori[0][1]] = temp_value[3][0], temp_value[3][1] 25 for idx, Xm in enumerate(Xm_ori): 26 if idx > 0: 27 two_d_matrix[Xr[idx]][Xm[0]] , two_d_matrix[Xr[idx]][Xm[1]] = temp_value[idx-1][0], temp_value[idx-1][1] 28 # print(two_d_matrix)
-
main函数:
1 if __name__ == '__main__': 2 3 input_list = input() 4 5 count_input = 0 6 for i in range(6): 7 for k in range(4):#根据输入构造二维矩阵(数组),k和前面设置的常量一一对应 8 two_d_matrix[i][k] = input_list[count_input] 9 count_input += 1 10 11 turn_list = [] 12 turn_input = input() 13 for idx, turn_one in enumerate(turn_input): 14 if idx != len(turn_input)-1: 15 if turn_input[idx+1] == "'":#当下一个为翻转的字符时加上并存入 16 add_char = turn_one + turn_input[idx+1] 17 turn_list.append(char_to_turn[add_char])#映射完存的实际上是(X_round,Sn_or_Ni) 18 else: 19 turn_list.append(char_to_turn[turn_one])#没有就直接存 20 elif turn_one != "'": 21 turn_list.append(char_to_turn[turn_one])#末尾不是翻转符那就存入翻转序列 22 for X, angle in turn_list:#遍历翻转数列 23 trun_X_round(X, angle)#先对X本面进行翻转【for内顺序无所谓】 24 if angle == Sn: 25 trun_other_round_Sn(X_round=X)#如果是顺时针就调用顺时针,否则就调用逆时针 26 elif angle == Ni: 27 trun_other_round_Ni(X_round=X) 28 29 for i in two_d_matrix:#构造输出 30 for k in i: 31 print(k,end="")
-
all code:
1 # 输入示例:带可视化显示 2 # YYYYRRRRWWWWOOOOGGGGBBBB 3 # UUL' 4 import copy 5 Sn, Ni = 0, 1 #常量Sn代表顺时针,Ni代表逆时针 6 F, R, B, L, U, D = 0,1,2,3,4,5 #随意,我只是根据题目来而已 7 two_d_matrix = [[0,0,0,0] for i in range(6)] #批量初始化6个面。每一个面有2*2就是4个元素,这个使用一维数组代替是因为如果使用二级数组会很麻烦 8 9 Fr = [U, R, D, L] #Xr代表的是 X个面中,移动的4个面序列 10 Fm = [(2,3), (0, 2), (1, 0), (3, 1)] #Xm代表的是每个面依次对照的影响元素的位置默认全为顺时针方向【本来应该是(0,0)~(1,1)二进制化就好了】 11 Lr = [U, F, D, B] 12 Lm = [(0,2), (0, 2), (0, 2), (3, 1)] 13 Dr = [F, R, B, L] 14 Dm = [(2,3), (2, 3), (2, 3), (2, 3)] 15 Rr = [D, F, U, B] 16 Rm = [(3,1), (3, 1), (3, 1), (0, 2)] 17 Ur = [F, L, B, R] 18 Um = [(1,0), (1, 0), (1, 0), (1, 0)] 19 Br = [R, U, L, D] 20 Bm = [(3,1), (1, 0), (0, 2), (2, 3)] 21 #输入的转动映射 22 char_to_turn = {'U':(U,Sn), "U'":(U, Ni), "F":(F,Sn),"F'":(F,Ni) , "L":(L,Sn),"L'":(L,Ni), 23 "D":(D,Sn) ,"D'":(D,Ni) , "R":(R,Sn), "R'":(R,Ni), "B":(B, Sn), "B'":(B, Ni)} 24 #全部面的关联面序列以及影响移动框序列,上面的二层抽象,方便后续操作 25 X_r = {F:Fr, R:Rr, B:Br, L:Lr, U:Ur, D:Dr} 26 X_m = {F:Fm, R:Rm, B:Bm, L:Lm, U:Um, D:Dm} 27 28 def trun_X_round(round_name:int, S_or_N:int): 29 """ 30 将X面进行翻转 31 :param round_name: 输入翻转的面常量 32 :param S_or_N: 输入顺时针或者是逆时针 33 """ 34 x_round = two_d_matrix[round_name] 35 new_round = copy.deepcopy(x_round)#一定要深拷贝,不然好像是会直接修改,因为浅复制是映射到同一个指针 36 if S_or_N == Sn: #根据转向去翻转,顺序无所谓,逻辑要一致,这里使用了两个数组来简化,0-3类比为二进制(x,y)就像x={0,1} y={0,1} 37 new_round[1] = x_round[0] 38 new_round[3] = x_round[1] 39 new_round[2] = x_round[3] 40 new_round[0] = x_round[2] 41 else: 42 new_round[1] = x_round[0] 43 new_round[3] = x_round[1] 44 new_round[2] = x_round[3] 45 new_round[0] = x_round[2] 46 # print(new_round) #输出测试 47 two_d_matrix[round_name] = new_round 48 49 def get_value(X_round:int, idx:tuple):#获取某个索引的值,返回的以面为单位,如["G","G"] 50 return [ 51 two_d_matrix[X_round][idx[0]], two_d_matrix[X_round][idx[1]] 52 ] 53 54 def trun_other_round_Sn(X_round:int): 55 """ 56 翻转X影响的其他部分【受X干扰的面】 57 :param X_round:输入面常量 58 """ 59 Xr = X_r[X_round] #获取所选面X的关联面序列,下为影响移动框序列 60 Xm_ori = X_m[X_round] 61 temp_value = [get_value(Xr[i], Xm_ori[i]) for i in range(4)] #批量保存原移动框的值,方便后续覆盖 62 #因为顺时针,所以第一个索引[0]移动后实际上变为最后一个[3]可以理解为循环链表,因为第一个比较特殊,拎出来做一次,理解了这个循环其实就是剩下3个idx[1,2,3]的移动 63 two_d_matrix[Xr[0]][Xm_ori[0][0]], two_d_matrix[Xr[0]][Xm_ori[0][1]] = temp_value[3][0], temp_value[3][1] 64 for idx, Xm in enumerate(Xm_ori): 65 if idx > 0: 66 #每次顺时针旋转,当前面的两个元素变为前一个面的两个元素,因为一个面有两个影响元素,temp_value以列表存储,每个存储两个元素列表,不理解调试一下就好了 67 two_d_matrix[Xr[idx]][Xm[0]] , two_d_matrix[Xr[idx]][Xm[1]] = temp_value[idx-1][0], temp_value[idx-1][1] 68 # print(two_d_matrix) 69 70 return 71 def trun_other_round_Ni(X_round:int): 72 #就是翻转了一下,就ok了,其他不影响,因为怎么转,点之间都是对应的 73 Xr = list(reversed(X_r[X_round])) 74 Xm_ori = list(reversed(X_m[X_round])) 75 temp_value = [get_value(Xr[i], Xm_ori[i]) for i in range(4)] 76 77 two_d_matrix[Xr[0]][Xm_ori[0][0]], two_d_matrix[Xr[0]][Xm_ori[0][1]] = temp_value[3][0], temp_value[3][1] 78 for idx, Xm in enumerate(Xm_ori): 79 if idx > 0: 80 two_d_matrix[Xr[idx]][Xm[0]] , two_d_matrix[Xr[idx]][Xm[1]] = temp_value[idx-1][0], temp_value[idx-1][1] 81 # print(two_d_matrix) 82 83 if __name__ == '__main__': 84 85 input_list = input() 86 87 count_input = 0 88 for i in range(6): 89 for k in range(4):#根据输入构造二维矩阵(数组),k和前面设置的常量一一对应 90 two_d_matrix[i][k] = input_list[count_input] 91 count_input += 1 92 93 turn_list = [] 94 turn_input = input() 95 for idx, turn_one in enumerate(turn_input): 96 if idx != len(turn_input)-1: 97 if turn_input[idx+1] == "'":#当下一个为翻转的字符时加上并存入 98 add_char = turn_one + turn_input[idx+1] 99 turn_list.append(char_to_turn[add_char])#映射完存的实际上是(X_round,Sn_or_Ni) 100 else: 101 turn_list.append(char_to_turn[turn_one])#没有就直接存 102 elif turn_one != "'": 103 turn_list.append(char_to_turn[turn_one])#末尾不是翻转符那就存入翻转序列 104 for X, angle in turn_list:#遍历翻转数列 105 trun_X_round(X, angle)#先对X本面进行翻转【for内顺序无所谓】 106 if angle == Sn: 107 trun_other_round_Sn(X_round=X)#如果是顺时针就调用顺时针,否则就调用逆时针 108 elif angle == Ni: 109 trun_other_round_Ni(X_round=X) 110 111 for i in two_d_matrix:#构造输出 112 for k in i: 113 print(k,end="") 114
自己编码的过程:
在我自己编码的途中,纯大脑模拟3维魔方并编码,而且输出如此抽象,实际上是非常困难的,因此我自己编码的时候借助了大模型生成的帮忙的可视化接口(虽然你笔试的时候肯定不能用,我当时也不够时间写出来,找到影响元素的位置序列真tm繁琐)【我命名为draw_cube.py。这个根据自己喜欢来】记得把import 改一下就好,最好复制那个输出就能显示图片了,有图片辅助更好理解
code:
1 # 输入示例:带可视化显示 2 # YYYYRRRRWWWWOOOOGGGGBBBB 3 # UUL' 4 import copy 5 import draw_cube#这个是可视化的代码 6 Sn, Ni = 0, 1 #常量Sn代表顺时针,Ni代表逆时针 7 F, R, B, L, U, D = 0,1,2,3,4,5 #随意,我只是根据题目来而已 8 two_d_matrix = [[0,0,0,0] for i in range(6)] #批量初始化6个面。每一个面有2*2就是4个元素,这个使用一维数组代替是因为如果使用二级数组会很麻烦 9 10 Fr = [U, R, D, L] #Xr代表的是 X个面中,移动的4个面序列 11 Fm = [(2,3), (0, 2), (1, 0), (3, 1)] #Xm代表的是每个面依次对照的影响元素的位置默认全为顺时针方向【本来应该是(0,0)~(1,1)二进制化就好了】 12 Lr = [U, F, D, B] 13 Lm = [(0,2), (0, 2), (0, 2), (3, 1)] 14 Dr = [F, R, B, L] 15 Dm = [(2,3), (2, 3), (2, 3), (2, 3)] 16 Rr = [D, F, U, B] 17 Rm = [(3,1), (3, 1), (3, 1), (0, 2)] 18 Ur = [F, L, B, R] 19 Um = [(1,0), (1, 0), (1, 0), (1, 0)] 20 Br = [R, U, L, D] 21 Bm = [(3,1), (1, 0), (0, 2), (2, 3)] 22 #输入的转动映射 23 char_to_turn = {'U':(U,Sn), "U'":(U, Ni), "F":(F,Sn),"F'":(F,Ni) , "L":(L,Sn),"L'":(L,Ni), 24 "D":(D,Sn) ,"D'":(D,Ni) , "R":(R,Sn), "R'":(R,Ni), "B":(B, Sn), "B'":(B, Ni)} 25 #全部面的关联面序列以及影响移动框序列,上面的二层抽象,方便后续操作 26 X_r = {F:Fr, R:Rr, B:Br, L:Lr, U:Ur, D:Dr} 27 X_m = {F:Fm, R:Rm, B:Bm, L:Lm, U:Um, D:Dm} 28 29 def trun_X_round(round_name:int, S_or_N:int): 30 """ 31 将X面进行翻转 32 :param round_name: 输入翻转的面常量 33 :param S_or_N: 输入顺时针或者是逆时针 34 """ 35 x_round = two_d_matrix[round_name] 36 new_round = copy.deepcopy(x_round)#一定要深拷贝,不然好像是会直接修改,因为浅复制是映射到同一个指针 37 if S_or_N == Sn: #根据转向去翻转,顺序无所谓,逻辑要一致,这里使用了两个数组来简化,0-3类比为二进制(x,y)就像x={0,1} y={0,1} 38 new_round[1] = x_round[0] 39 new_round[3] = x_round[1] 40 new_round[2] = x_round[3] 41 new_round[0] = x_round[2] 42 else: 43 new_round[1] = x_round[0] 44 new_round[3] = x_round[1] 45 new_round[2] = x_round[3] 46 new_round[0] = x_round[2] 47 # print(new_round) #输出测试 48 two_d_matrix[round_name] = new_round 49 50 def get_value(X_round:int, idx:tuple):#获取某个索引的值,返回的以面为单位,如["G","G"] 51 return [ 52 two_d_matrix[X_round][idx[0]], two_d_matrix[X_round][idx[1]] 53 ] 54 55 def trun_other_round_Sn(X_round:int): 56 """ 57 翻转X影响的其他部分【受X干扰的面】 58 :param X_round:输入面常量 59 """ 60 Xr = X_r[X_round] #获取所选面X的关联面序列,下为影响移动框序列 61 Xm_ori = X_m[X_round] 62 temp_value = [get_value(Xr[i], Xm_ori[i]) for i in range(4)] #批量保存原移动框的值,方便后续覆盖 63 #因为顺时针,所以第一个索引[0]移动后实际上变为最后一个[3]可以理解为循环链表,因为第一个比较特殊,拎出来做一次,理解了这个循环其实就是剩下3个idx[1,2,3]的移动 64 two_d_matrix[Xr[0]][Xm_ori[0][0]], two_d_matrix[Xr[0]][Xm_ori[0][1]] = temp_value[3][0], temp_value[3][1] 65 for idx, Xm in enumerate(Xm_ori): 66 if idx > 0: 67 #每次顺时针旋转,当前面的两个元素变为前一个面的两个元素,因为一个面有两个影响元素,temp_value以列表存储,每个存储两个元素列表,不理解调试一下就好了 68 two_d_matrix[Xr[idx]][Xm[0]] , two_d_matrix[Xr[idx]][Xm[1]] = temp_value[idx-1][0], temp_value[idx-1][1] 69 # print(two_d_matrix) 70 71 return 72 def trun_other_round_Ni(X_round:int): 73 #就是翻转了一下,就ok了,其他不影响,因为怎么转,点之间都是对应的 74 Xr = list(reversed(X_r[X_round])) 75 Xm_ori = list(reversed(X_m[X_round])) 76 temp_value = [get_value(Xr[i], Xm_ori[i]) for i in range(4)] 77 78 two_d_matrix[Xr[0]][Xm_ori[0][0]], two_d_matrix[Xr[0]][Xm_ori[0][1]] = temp_value[3][0], temp_value[3][1] 79 for idx, Xm in enumerate(Xm_ori): 80 if idx > 0: 81 two_d_matrix[Xr[idx]][Xm[0]] , two_d_matrix[Xr[idx]][Xm[1]] = temp_value[idx-1][0], temp_value[idx-1][1] 82 # print(two_d_matrix) 83 84 if __name__ == '__main__': 85 86 input_list = input() 87 draw_cube.show_cube_list(input_list)#可视化输入的二阶魔法平面图 88 count_input = 0 89 for i in range(6): 90 for k in range(4):#根据输入构造二维矩阵(数组),k和前面设置的常量一一对应 91 two_d_matrix[i][k] = input_list[count_input] 92 count_input += 1 93 94 turn_list = [] 95 turn_input = input() 96 for idx, turn_one in enumerate(turn_input): 97 if idx != len(turn_input)-1: 98 if turn_input[idx+1] == "'":#当下一个为翻转的字符时加上并存入 99 add_char = turn_one + turn_input[idx+1] 100 turn_list.append(char_to_turn[add_char])#映射完存的实际上是(X_round,Sn_or_Ni) 101 else: 102 turn_list.append(char_to_turn[turn_one])#没有就直接存 103 elif turn_one != "'": 104 turn_list.append(char_to_turn[turn_one])#末尾不是翻转符那就存入翻转序列 105 for X, angle in turn_list:#遍历翻转数列 106 trun_X_round(X, angle)#先对X本面进行翻转【for内顺序无所谓】 107 if angle == Sn: 108 trun_other_round_Sn(X_round=X)#如果是顺时针就调用顺时针,否则就调用逆时针 109 elif angle == Ni: 110 trun_other_round_Ni(X_round=X) 111 112 for i in two_d_matrix:#构造输出 113 for k in i: 114 print(k,end="") 115 draw_cube.show_cube() 116 117 #YYYYRRRRWWWWOOOOGGGGBBBB 119 #OBRBWOWRYOYRGYGYWGBRBOWG 120
鸣谢: