ETJava Beta | Java    注册   登录
  • 搜索:
  • 笔试真题——机器人拧魔方模拟

    发表于      阅读(1)     博客类别:Crawler     转自:https://www.cnblogs.com/io-T-T/p/18519050
    如有侵权 请联系我们删除  (页面底部联系我们)  
    说明:根据遗留的记忆写出来了此篇文章,可能与原文解释有部分出入,但总体思路一致。

    题目说明:

    YYYYRRRRWWWWOOOOGGGGBBBB UUL'

    第一行为输入为对应F, R, B, L, U, D面的元素颜色

    第二行输入为翻转的标识符

    标识符有:F、F'、R、R'、B、B'、L、L'、U、U'、D、D' 。分别为对应明的顺时针翻转和逆时针翻转。带'则为逆时针,不带则为顺时针

    输入示意图:

    image-20241031221017240

    输出说明:

    BWBYOORRYGWGORORWGYGWBYB

    • 示例图【无需输出,仅理解】:

    image-20241031222035048

    输出翻转后最终对应位置F, R, B, L, U, D的颜色序列

    题解:

      • 要理解题目中,每个转动的模拟情况,每个面的转动会影响那些面

      • 旋转面的影响方框【元素】依次是什么,

        • 这里以以U移动举例:

          1. U移动会带动L、F、R、B【顺序可以改,但必须保证前后对应的面相等,因为带动顺序也很关键】

          1. 每个面划分为2*2的矩阵,那么,L会影响的元素方位是(0,0) (0,1)。F会影响的也是(0,0) (0,1)

          2. 分别模拟出每个面依次对照的影响元素的位置

      • 获取每个影响元素的方位

      • 就可以编码了,难点在于如何理解每一个面的转动以及他所带动的面的元素是什么,每一个面的带动情况是不一样的

     

    难度:

    复杂度高,找到移动影响序列比较繁琐,编码难度中等

    编码

    • 构建常量以及每一个面的两个序列【面移动序列,面中受影响所移动的位置序列】:

      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

    鸣谢:

    魔方模拟