Python入门习题(88)——OpenJudge百练习题:情报破译

OpenJudge百练第4112号习题:情报破译

题目描述

来源
OpenJudge网站 —— 百练习题集-第4112号习题

要求
总时间限制: 3000ms 单个测试点时间限制: 1000ms 内存限制: 65536kB

描述

A国和B国正在进行一场战争。A国通过间谍知道B国的情报加密规则为:

  1. 仅对字母加密,其他符号保留(如空格,逗号等)

  2. 对第i个单词(i从1开始)的加密方法是把第i个单词反转(如abc变成cba),然后对单词内的每个字母采用经典的Caesar加密法,循环后移i个字母。例如:第5个单词的加密表如下所示:

密码字母:A B C D E F G H I J K L M N O P Q R S T U VW X Y Z

原文字母:V W X Y Z A B C D E F G H I J K L M N O P QR S T U

  1.   单词的定义是:任何一串极大的连续字母串。
    

比如,样例输出第三行,第二个单词为ba,反转后为ab,a后移2个单词变成c,b后移两个单词变成d,故该单词加密后为cd(见样例输入第三行)。

现在A国又截获了一些B国的情报密文。请你帮A国破译出情报的内容。

输入
一共有不超过int范围行,每行为一个字符串(int范围)。注意,每行是可以以空格开头的。
输出
情报破译后得到的内容。每条情报对应输出一行。
样例输入
fiU umncv oolz ioex jhfqu, zg uh zqI nlaxO ockl yz kmpzgE.
fX gxcj , ghlsxffr cxmG K.
ab3cd
样例输出
The talks will take place, at an Air Force base on Sunday.
We have , occupied City F.
az3ba

解题思路

  1. 问题是求一行密文对应的明文。下面的代码中,crack函数封装了破译密文的逻辑。
  2. 做法是,从左到右地,对每一个单词进行破译(crack_word函数),而非字母无需改变,输出破译得到的明文。
  3. 如何得出一个个单词?做法是,从左到右扫描,遇到一个字母,则找出该位置打头的连续的字母,直至遇到非字母或者字符串结束。下面的代码中,find_word函数封装了找单词的逻辑。
  4. 已知一个作为密文的单词cword,凯撒秘钥是key, 如何得到其明文pword?做法是,cword逆序得到rev_cword,接着对于rev_cword内的每一个字母s,得到其加密前的字母r。这些字母r连在一起,就是明文单词word。
  5. 已知密文字母s,凯撒秘钥是key,如何求出其对应的明文字母r?做法是,先判别s字母的大小写,接着转换为明文字母。无论是大写字母还是小写字母,做法类似。如果是大写,则用字母s的编码值减去key,如果减出来的结果小于’A’的编码值,则加上26,求出来的结果作为编码转换为字母,该字母即为明文字母。

参考答案

import sys

#得到密文miwen对应的明文
def crack(miwen):
    mingwen = ''
    index = 0
    word_count = 0
    while index < len(miwen):
        if miwen[index].isalpha():
            cword = find_word(miwen, index)
            word_count += 1
            pword = crack_word(cword, word_count)
            mingwen += pword
            index += len(cword)
        else:
            mingwen += miwen[index]
            index += 1

    return mingwen

#在line字符串内,找到从index索引位置开始的单词。
#line[index]是字母
def find_word(line, index):
    word = ''
    while index < len(line) and line[index].isalpha():
        word += line[index]
        index += 1

    return word


#对单词进行解密,凯撒秘钥是key
def crack_word(cword, key):
    rev_cword = cword[::-1]
    pword = ''
    for s in rev_cword:
        pword += casear_crack(s, key)
    return pword


#对字母进行凯撒解密,秘钥是key
def casear_crack(s, key):
    if s.isupper():
        base_letter = 'A'
    else:
        base_letter = 'a'
    dif = ord(s) - ord(base_letter) - key
    if dif < 0:
        dif += 26
    p = chr(dif + ord(base_letter))
    return p

for line in sys.stdin:  #读入行数不定的文本
    print(crack(line), end='')  #键盘输入时,按Ctrl + Z或Ctrl + D来表明结束输入

测试用例

  1. 题目给出的测试用例覆盖了以下情形:(1)输入多行文本。(2)key=1, 2, 3, 4乃至更大。(3)包含大小写字母。(4)包含非字母字符。(5)单词之间用数字分隔。差不多够用了。
  2. 输入一行文本。
    样例输入
    cba
    样例输出
    zab

小结

  1. 自顶向下逐步细化。细化的步骤有复杂度的话,用函数封装实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值