Python解决Cipher Map问题

题目

声明:题目来源为Checkio
Help Sofia write a decrypter for the passwords that Nikola will encrypt through the cipher map. A cipher grille is a 4×4 square of paper with four windows cut out. Placing the grille on a paper sheet of the same size, the encoder writes down the first four symbols of his password inside the windows (see fig. below). After that, the encoder turns the grille 90 degrees clockwise. The symbols written earlier become hidden under the grille and clean paper appears inside the windows. The encoder then writes down the next four symbols of the password in the windows and turns the grille 90 degrees again. Then, they write down the following four symbols and turns the grille once more. Lastly, they write down the final four symbols of the password. Without the same cipher grille, it is difficult to discern the password from the resulting square comprised of 16 symbols. Thus, the encoder can be confident that no hooligan will easily gain access to the locked door.
problem

题意理解

Cipher Map问题的大意是:给定一个解码器和一个加密后的密码,解码器和密码都是4*4的(如上图所示),其中解码器中包含四个“窗口”,将解码器和密码重叠,四个窗口中的内容按从左到右,从上到下的顺序组合起来就是密码的一部分,然后将解码器顺时针旋转90°,重复上述操作直至解码器旋转270°为止,四部分组合起来就是密码。

输入

解码器元组和密码元组都是数据类型为字符串的元组,解码器元组和密码元组都分别包含4个串长为4的字符串,解码器元组中的字符串使用’X’代表窗口所在的位置,输入样例如下:

#解码器
('X...',
 '..X.',
 'X..X',
 '....')
 #密码
('itdf',
'gdce',
'aton',
'qrdi')

输出

输出结果为解密后的字符串,例如上述样例的输出结果为:

'icantforgetiddqd'

解题思路

根据题意,只需要对解码器与密码重叠,找到加密后的4*4密码中’X‘所对应的元素提取出来,重复如此,直至解码器旋转满270°,其中解码器每顺时针旋转90°就要重叠提取一次,那么问题的关键就变成了如何将解码器旋转90°。其实,实现解码器旋转90°也很简单,按逆序(从最后一个字符串开始到第一个字符串为止)依次提取对应位置的第一个字符作为第一行,接着按同样的顺序提取四个字符串的第二个字符作为第二行,依次类推直至取完4个字符,这样就可以的得到原4*4数组旋转90°后的新4*4数组。

代码

def recall_password(cipher_grille, ciphered_password):
    ciphers = []
    ciphers.append(cipher_grille)
    for i in range(3):
        cipher_grille = [[cipher_grille[i][j] for i in reversed(range(4))] for j in range(4)]
        ciphers.append(cipher_grille)
    
    out = ''
    for cipher in ciphers:
        for i,item in enumerate(cipher):
            for j,ch in enumerate(item):
                if ch == 'X':
                    out += ciphered_password[i][j]

    return out


if __name__ == '__main__':
    assert recall_password(
        ('X...',
         '..X.',
         'X..X',
         '....'),
        ('itdf',
         'gdce',
         'aton',
         'qrdi')) == 'icantforgetiddqd', 'First example'

    assert recall_password(
        ('....',
         'X..X',
         '.X..',
         '...X'),
        ('xhwc',
         'rsqx',
         'xqzz',
         'fyzr')) == 'rxqrwsfzxqxzhczy', 'Second example'
原创文章 27 获赞 90 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42103091/article/details/105087671