19960: 恩尼格玛
http://cs101.openjudge.cn/practice/19960/
Frank老师在计算概论的第一堂课上让同学们观看了“模仿游戏”这部电影。看完以后,Hitler同学对其中的恩尼格玛加密机产生了浓厚的兴趣。在网上查阅资料以后,他决定从简单的情况入手(输入文本只包含abcdef六个字母),用电脑实现一个恩尼格玛加密机。 加密机的原理如下(参照示意图):

三个转子上都有线路,彼此相连;反射器将六个槽位两两相连;输入某一字母后经过左中右三个转子到达反射器,再返回,依次通过右中左三个转子,最后得到加密字母(全小写)。(如图中,输入b得到d)
注意:每输入一个字母,左边的转子都会向下转一位,左边的转子转了一圈以后中间的转子向下转一位,中间的转子转一圈以后最右边的转子向下转一位
输入
前18行,每行2个数字,以空格隔开,表示转子进出的初始线路连接(1-6行是左转子,7-12行是中间转子,13-18行是右转子) 第19-21行,每行2个数字,以空格隔开,表示反射器中两两连接的情况 最后一行是待加密的字符串(只含有abcdef六个字母,全小写)
输出
加密后的字符串(全小写)
样例输入
1 6
2 3
3 5
4 4
5 2
6 1
1 3
2 1
3 4
4 2
5 6
6 5
1 5
2 1
3 4
4 6
5 3
6 2
1 6
2 3
4 5
abcdefabcdefabcdef样例输出
caecaeccbffefdabbc
解释:处理完第一个字符'a'以后,左转子变为(2 1;3 4;4 6;5 5;6 3;1 2),
中间转子、右转子不变来源
cs101-2019 张昊骞
相当于左转子向下转一次后,行标号均加一 (1 6 -> 2 7(2 1)); (2 3 -> 3 4)
字母a,始终找左转子的第一行,但是经过之前左转子向下转一位,第一行会被原来的第六行替代,此时左转子第一行线路是(1 2)。它由第六行的 6 1 -> 1 2而来。如果能明白输入ab,输出ca应该能明白了。
python
def rotate(a):
return (a % 6) + 1 # 返回加1后的结果,自动回绕到1
def update_rotation(dic):
return {rotate(k): rotate(v) for k, v in dic.items()} # 一次性更新字典
# 初始化字典
rotL, rotM, rotR = {}, {}, {}
rerotL, rerotM, rerotR = {}, {}, {}
ref, alpha = {}, {}
# 读取输入并初始化旋转字典
for i in range(6):
come, go = map(int, input().split())
rotL[come] = go
rerotL[go] = come
for i in range(6):
come, go = map(int, input().split())
rotM[come] = go
rerotM[go] = come
for i in range(6):
come, go = map(int, input().split())
rotR[come] = go
rerotR[go] = come
# 读取参考交换字典
for i in range(3):
come, go = map(int, input().split())
ref[come] = go
ref[go] = come
# 字母到数字的映射和反向映射
for i in ['a', 'b', 'c', 'd', 'e', 'f']:
alpha[i] = ord(i) - 96
alpha[ord(i) - 96] = i
# 处理输入字符串
string = list(input())
output = []
time = 0
for i in string:
code = alpha[i]
# 执行多次旋转操作并存入输出列表
output.append(alpha[rerotL[rerotM[rerotR[ref[rotR[rotM[rotL[code]]]]]]]])
# 更新字典
rotL = update_rotation(rotL)
rerotL = update_rotation(rerotL)
time += 1
# 每6次旋转更新 rotM, rerotM
if time % 6 == 0:
rotM = update_rotation(rotM)
rerotM = update_rotation(rerotM)
# 每36次旋转更新 rotR, rerotR
if time % 36 == 0:
rotR = update_rotation(rotR)
rerotR = update_rotation(rerotR)
# 输出最终加密后的字符串
print(''.join(output))python
def rotate(a):
return (a % 6) + 1 # 返回加1后的结果,自动回绕到1
def update_rotation(dic):
return {rotate(k): rotate(v) for k, v in dic.items()} # 一次性更新字典
# 初始化字典
rotL, rotM, rotR = {}, {}, {}
rerotL, rerotM, rerotR = {}, {}, {}
ref, alpha = {}, {}
# 读取输入并初始化旋转字典
for i in range(6):
come, go = map(int, input().split())
rotL[come] = go
rerotL[go] = come
for i in range(6):
come, go = map(int, input().split())
rotM[come] = go
rerotM[go] = come
for i in range(6):
come, go = map(int, input().split())
rotR[come] = go
rerotR[go] = come
# 读取参考交换字典
for i in range(3):
come, go = map(int, input().split())
ref[come] = go
ref[go] = come
# 字母到数字的映射和反向映射
for i in ['a', 'b', 'c', 'd', 'e', 'f']:
alpha[i] = ord(i) - 96
alpha[ord(i) - 96] = i
# 处理输入字符串
string = list(input())
output = []
time = 0
for i in string:
code = alpha[i]
# 执行多次旋转操作并存入输出列表
output.append(alpha[rerotL[rerotM[rerotR[ref[rotR[rotM[rotL[code]]]]]]]])
# 更新字典
rotL = update_rotation(rotL)
rerotL = update_rotation(rerotL)
time += 1
# 每6次旋转更新 rotM, rerotM
if time % 6 == 0:
rotM = update_rotation(rotM)
rerotM = update_rotation(rerotM)
# 每36次旋转更新 rotR, rerotR
if time % 36 == 0:
rotR = update_rotation(rotR)
rerotR = update_rotation(rerotR)
# 输出最终加密后的字符串
print(''.join(output))