5.1 统计英文文件中的单词数***
思路:
先创建个路径,文件读取之后,在用str.replace把符号替代成空格。最后用str.split切分成字符串,返回字符串长度就是这个文件中的单词数字了。重点在于要先读取路径。
知识:
open(filename)
函数可以打开诸如txt
,csv
等格式的文件。
例如:
with open('a.txt', 'r', encoding='utf-8') as text: # 打开文件a.txt,创建文件对象
txt = text.read() # 读文件为字符串
print(txt) # 输出字符串
但是首先要先构建个路径,然后带入+上你的名称
path = '/data/bigfiles/'
with open(path+file, 'r', encoding='utf-8') as f:
基础知识:
字符串方法
为了方便编程,Python
为我们提供了许多方法这里我们将学习其中的两个字符串方法。
替换
str.replace(oldvalue, newvalue, count)
方法是在字符串str中,用另一个newvalue字符串替换oldvalue字符串count次。
参数值:
序号 | 参数 | 描述 |
---|---|---|
1 | oldvalue | 必需。要检索的字符串。 |
2 | newvalue | 必需。替换旧值的字符串。 |
3 | count | 可选。数字,指定要替换的旧值出现次数。默认为替换所有出现的检索字符串。 |
示例如下:
txt = "I like bananas. She likes bananas too. "
x1 = txt.replace("bananas", "apples") # 替换所有
print(x1) # I like apples. She likes apples too.
x2 = txt.replace("bananas", "apples", 1) # 只替换一次
print(x2) # I like apples. She likes bananas too.
切分
str.split(sep=None, maxsplit=- 1)
将字符串拆分成一个列表,其中每个单词都是一个列表项。可以指定分隔符,默认分隔符是空白字符(包括空格、制表\t、换行\n、回车\r、进纸\f和纵向制表符\v)。
参数值:
序号 | 参数 | 描述 |
---|---|---|
1 | sep | 可选。规定分割字符串时要使用的分隔符。默认值为空白字符。 |
2 | maxsplit | 可选。规定要执行的拆分数。默认值为 -1,即“所有出现次数”。 |
示例如下:
txt = "yearly a.每年的 ad.一年一度"
x1 = txt.split() # 遇空白字符就切分,返回3个元素的列表
print(x1) # ['yearly', 'a.每年的', 'ad.一年一度']
x2 = txt.split(maxsplit=1) # 只切分一次,返回2个元素的列表
print(x2) # ['yearly', 'a.每年的 ad.一年一度']
输入格式
输入为一行,是一个文本文件名,例如example1.txt
。
输出格式
输出为一行,是打开并读取输入的文件名,对文件内容进行单词数目统计后的结果, 输出共有m个单词
,具体格式见示例。 a.txt b.txt mySunshine.txt
代码:
# 补充你的代码
file = input()
path = '/data/bigfiles/'
with open(path+file,'r',encoding = 'utf-8') as text:
txt =text.read()
for i in """ ,.!\' """:
txt = txt.replace(i,' ')
fin = txt.split()
print(f'共有{len(fin)}个单词')
5.2 凯撒密码
第一关:凯撒密码-加密***
思路:
首先分为三部分,字母大写,字母小写和数字(其中数字要特别注意,是digit)。然后后移三位,要分为[:3] + [3:]才可实现凯撒密码。其中涉及到两个函数,maketrans相当于转换表,translate需要转换表才可以翻译。
知识:
为了完成本关任务,你需要掌握:1.string库,2.maketrans() 函数,3.translate()函数。
下面介绍几个string
的内置属性:
string.ascii_uppercase
所有大写字母string.ascii_lowercase
所有小写字母string.ascii_letters
所有字母string.digits
所有数字
示例如下:
import string
lower = string.ascii_lowercase
upper = string.ascii_uppercase
digit = string.digits
before = string.ascii_letters
输出:
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
由于两个函数要结合使用,所以就一起介绍了。
maketrans()
方法用于创建字符映射的转换表,对于接受两个参数的最简单的调用方式,第一个参数是字符串,表示需要转换的字符,第二个参数也是字符串表示转换的目标。
注:两个字符串的长度必须相同,为一 一对应的关系。
maketrans()
方法语法: str.maketrans(intab, outtab)
参数
intab
-- 字符串中要替代的字符组成的字符串。outtab
-- 相应的映射字符的字符串。
返回值 返回字符串转换后生成的新字符串。
translate()
方法根据参数table
给出的表(包含 256
个字符)转换字符串的字符, 要过滤掉的字符放到 del
参数中。
translate()
方法语法: str.translate(table[, deletechars])
参数
table
-- 翻译表,翻译表是通过maketrans方法转换而来。deletechars
-- 字符串中要过滤的字符列表。
返回值 返回翻译后的字符串。
示例如下: 示例一:
intab = "aeiou" # 原字符
outtab = "12345" # 用于替换的字符
# 想要加密的字符串的明文
txt = "this is string example....wow!!!"
# 创建映射转换表
# 将明文中字符"a、e、i、o、u"分别替换为"1、2、3、4、5",其他字符不变
trantab = ''.maketrans(intab, outtab)
# 输出加密后的结果
print(txt.translate(trantab))
输出: th3s 3s str3ng 2x1mpl2....w4w!!!
示例二:
intab = "abcdefghijklmnopqrstuvwxyz" # 原字符
outtab = "defghijklmnopqrstuvwxyzabc" # 用于替换的字符
# 想要加密的字符串的明文
txt = "this is string example....wow!!!"
# 创建映射转换表,用后面第3个字符替换
trantab = ''.maketrans(intab, outtab)
# 输出加密后的结果
print(txt.translate(trantab))
输出: wklv lv vwulqj hadpsoh....zrz!!!
输入输出:
测试输入:Open Box PassWord:2021
预期输出:Rshq Era SdvvZrug:5354
代码:
import string
def caesar_cipher(text):
"""接收一个字符串为参数,采用字母表和数字中后面第3个字符代替当前字符的方法
对字符串中的字母和数字进行替换,实现加密效果,返回值为加密的字符串。
例如:2019 abc 替换为5342 def """
# 补充你的代码
x1 = string.ascii_lowercase
x2 = string.ascii_uppercase
x3 = string.digits
begin = x1 + x2 + x3
after = x1[3:] + x1[:3] +x2[3:] + x2[:3] +x3[3:] + x3[:3]
fin = ''.maketrans(begin,after)
return text.translate(fin)
if __name__ == '__main__':
plaintext = input()
print(caesar_cipher(plaintext))
第二关:凯撒密码-解密****
思路:
首先要把begin和after调换过来,然后才能继续用。
推测偏移量
def find_offset(key_text, ciphertext):
"""接收一个单词和一个加密字符串为参数,尝试用[0,25]之间的数为偏移量进行解密。
如果key_text 在解密后的明文里,则说明解密成功。
找出偏移量数值并返回这个整数偏移量。"""
for i in range(26):
plain_text = caesar_decrypt(ciphertext, i) # 使用i作为偏移量,尝试解密得到明文
if key_text in plain_text: # 如果key_text在明文里,说明偏移值为i时能成功解密
return i
maketrans
maketrans()
方法用于创建字符映射的转换表,对于接受两个参数的最简单的调用方式,第一个参数是字符串,表示需要转换的字符,第二个参数也是字符串表示转换的目标。
语法
str.maketrans(intab, outtab)
参数说明
- intab - - 字符串中要替代的字符组成的字符串。
- outtab - - 相应的映射字符的字符串。
编程要求
在右侧编辑器中代码。具体要求如下: 某国截获一份情报如下:Y
t gj, tw sty yt gj, ymfy nx f vzjxynts.
。 根据潜伏的特工传回的消息,知道这份情报的明文中有一个单词是 question
,且采用的是恺撒加密的方法,偏移量未知。 请编程计算偏移量,并用得到的偏移量解密读到的密文。
测试说明
平台会对你编写的代码进行测试:
测试输入: Fyyfhp ts Ujfwq Mfwgtw ts Ijhjrgjw 2, 6496
预期输出: 密钥是5
Attack on Pearl Harbor on December 7, 1941
代码:
import string
def caesar_decrypt(text, offset):
"""接收一个加密的字符串text和一个整数offset为参数,采用字母表和数字中前面第offset个字符
代替当前字符的方法对字符串中的字母和数字进行替换,实现解密效果,返回值为解密的字符串。"""
# 补充你的代码
x1 = string.ascii_lowercase
x2 = string.ascii_uppercase
x3 = string.digits
begin = x1 + x2 + x3
after = x1[offset:] + x1[:offset] +x2[offset:] + x2[:offset] +x3[offset:] + x3[:offset]
fin = ''.maketrans(after,begin)
return text.translate(fin)
def find_offset(key_text, ciphertext):
"""接收一个单词和一个加密字符串为参数,尝试用[0,25]之间的数为偏移量进行解密。
如果key_text 在解密后的明文里,则说明解密成功。
找出偏移量数值并返回这个整数偏移量。"""
# 补充你的代码
for i in range(26):
plain_text = caesar_decrypt(ciphertext, i) #使用i作为偏移量,尝试解密得到明文
if key_text in plain_text : # 如果key_text在明文里,说明偏移值为i时能成功解密
return i
if __name__ == '__main__':
key_message = 'question' #密文中的已知单词
cipher_text = 'Yt gj,tw sty yt gj,ymfy nx f vzjxynts.' #截获的密文
secret_key = find_offset(key_message, cipher_text) #破解密码,得到密匙
print(f'密钥是{secret_key}')
target_text = input() #读入新密文,进行解密
#'Fyyfhp ts Ujfwq Mfwgtw ts Ijhjrgjw 2, 6496' #新密文,需要解密
print(caesar_decrypt(target_text, secret_key)) #解密,打印明文
5.3 使用凯撒密码加密和解密英文文件*****
open()
open()
函数用于打开一个文件,创建一个file对象,相关的方法才可以调用它进行读写。
语法
open(name[, mode[, buffering]])
参数说明
-
name: 一个包含了你要访问的文件名称的字符串值。
-
mode: mode决定了打开文件的模式:只读,写入,追加等。所有可取值见如下的完全列表。这个参数是非强制的,默认文件访问模式为只读(r)。
-
buffering: 如果buffering的值被设为0,就不会有寄存。如果buffering的值取1,访问文件时会寄存行。如果将buffering的值设为大于1的整数,表明了这就是的寄存区的缓冲大小。如果取负值,寄存区的缓冲大小则为系统默认。
def read_txt(file):
"""接收文件名为参数,读取文件中的内容为一个字符串,返回这个字符串。"""
with open(file, 'r') as temp:
return temp.read()
Python String 模块内置属性
string.ascii_lowercase
小写字母string.ascii_uppercase
大写字母string.digits
数字0 - 9
def caesar_decrypt(text, offset):
"""接收一个加密的字符串text和一个整数offset为参数,采用字母表和数字中前面第offset个字符
代替当前字符的方法对字符串中的字母和数字进行替换,实现解密效果,返回值为解密的字符串。"""
lower = string.ascii_lowercase # 小写字母
upper = string.ascii_uppercase # 大写字母
before = lower[offset:] + lower[:offset] + upper[offset:] + upper[:offset] + string.digits[offset:] + string.digits[:offset]
after = string.ascii_letters + string.digits
Python 常用函数
做题思路:
主要在看如何解码和加密两个方式,然后在解码的过程中,注意好两个函数的应用!!!
range
range()
函数返回的是一个可迭代对象(类型是对象),而不是列表类型, 所以打印的时候不会打印列表。
语法
range(stop)
range(start, stop[, step])
参数说明
-
start: 计数从start开始。默认是从0开始。例如range(3)等价于range(0, 3);
-
stop: 计数到stop结束,但不包括stop。例如:range(0, 3)是[0, 1, 2],没有3
-
step:步长,默认为1。例如:range(0, 3)等价于range(0, 3, 1)
def find_offset(key_text, ciphertext):
"""接收一个明文单词和一个加密字符串为参数,尝试用[0,8]之间的数为偏移量进行解密。
若解密结果中包含这个明文单词,说明当前正在尝试的偏移量就是加密时所用偏移量,返回
这个整数偏移量。
"""
offset = 0
for i in range(0, 9):
if key_text in caesar_decrypt(ciphertext, i):
offset = i
return offset
maketrans
maketrans()
方法用于创建字符映射的转换表,对于接受两个参数的最简单的调用方式,第一个参数是字符串,表示需要转换的字符,第二个参数也是字符串表示转换的目标。
语法
str.maketrans(intab, outtab)
参数说明
- intab - - 字符串中要替代的字符组成的字符串。
- outtab - - 相应的映射字符的字符串。
def caesar_cipher(text, offset):
"""接收一个字符串为参数,采用字母表和数字中后面第offset个字符代替当前字符的方法
对字符串中的字母和数字进行替换,实现加密效果,返回值为加密的字符串。
例如:2019 abc 替换为5342 def """
lower = string.ascii_lowercase # 小写字母
upper = string.ascii_uppercase # 大写字母
before = string.ascii_letters + string.digits
after = lower[offset:] + lower[:offset] + upper[offset:] + upper[:offset] + string.digits[offset:] + string.digits[
:offset]
table = ''.maketrans(before, after) # 创建映射表
return text.translate(table)
编程要求
本项目文件下载: text0.txt tests.txt jap.txt testjm.txt 在右侧编辑器中补充代码,完成文件分析与加密。具体要求如下:
1.接收一个字符串为参数,如果参数值为加密
, 要求用户输入一个要加密的文件名
,再输入一个单词做为密钥发生器
,用于计算偏移量,对文件中的内容进行加密并输出;
2.如果参数值为解密
, 要求用户输入一个要解密的文件名
,再输入一个单词做为匹配词
,用于破解偏移量,输出解密后的文本
;
3.若为其他输入,输出输入错误
。
4.为了提高加密强度,本题不使用固定偏移量,而是约定用一个英文单词做为密钥,读入一个英文单词,计算这个单词的每个字母的ASCII
值的和,再对9
取模,结果作为偏移量offset
。将大写字母、小写字母和数字均用其后的第offset
个字符代替,获得加密的文本。例如:当偏移量为3
的时候,所有的字母A将被替换成D
,B
替换成E
,以此类推。
5.解密处理进行相反的操作,不同的是,凯撒加密的强度不高,若知道明文中的一个单词,便可以直接根据这个单词进行暴力破解。
测试说明
平台会对你编写的代码进行测试:
测试输入1: 加密
/step1/testks.txt
February
预期输出1: Fieyxmjyp mw fixxiv xler ykpc.Ibtpmgmx mw fixxiv xler mqtpmgmx.
测试输入2: 解密
/step1/testjm.txt
than
预期输出2: Beautiful is better than ugly.Explicit is better thanimplicit.
代码:
import string
def judge(txt):
"""接收一个字符串为参数,如果参数值为“加密”,要求用户输入一个要加密的文件名,
再输入一个单词做为密钥发生器,用于计算偏移量,对文件中的内容进行加密并输出。
如果参数值为“解密”,要求用户输入一个要解密的文件名,再输入一个单词做为匹配词,
用于破解偏移量,输出解密后的文本。若为其他输入,输出'输入错误'。"""
# 补充你的代码
if txt == '加密':
file = input()
key_word = input()
print(caesar_cipher (read_txt(file), cal_offset(key_word)) )
elif txt == '解密':
file = input()
key_text = input()
print(caesar_decrypt(read_txt(file), find_offset(key_text, read_txt(file))))
else :
print('输入错误')
def read_txt(file):
"""接收文件名为参数,读取文件中的内容为一个字符串,返回这个字符串。"""
with open(file, 'r') as temp:
return temp.read()
def caesar_cipher(text, offset):
"""接收一个字符串为参数,采用字母表和数字中后面第offset个字符代替当前字符的方法
对字符串中的字母和数字进行替换,实现加密效果,返回值为加密的字符串。
例如:2019 abc 替换为5342 def """
# 补充你的代码
x1 = string.ascii_lowercase
x2 = string.ascii_uppercase
x3 = string.digits
begin = x1 + x2 + x3
after = x1[offset:] + x1[:offset] + x2[offset:] + x2[:offset] + x3[offset:] + x3[:offset]
fin = ''.maketrans(begin,after)
return text.translate(fin)
def caesar_decrypt(text, offset):
"""接收一个加密的字符串text和一个整数offset为参数,采用字母表和数字中前面第offset个字符
代替当前字符的方法对字符串中的字母和数字进行替换,实现解密效果,返回值为解密的字符串。"""
# 补充你的代码
x1 = string.ascii_lowercase
x2 = string.ascii_uppercase
x3 = string.digits
begin = x1 + x2 + x3
after = x1[offset:] + x1[:offset] + x2[offset:] + x2[:offset] + x3[offset:] + x3[:offset]
fin = ''.maketrans(after,begin)
return text.translate(fin)
def cal_offset(key_word):
"""接收一个单词为参数,计算这个单词的每个字母的ASCII值的和,
再对9取模,结果作为偏移量offset,返回这个偏移量。"""
# 补充你的代码
offset = 0
for i in key_word:
offset += ord(i)
offset = offset % 9
return offset
def find_offset(key_text, ciphertext):
"""接收一个明文单词和一个加密字符串为参数,尝试用[0,8]之间的数为偏移量进行解密。
若解密结果中包含这个明文单词,说明当前正在尝试的偏移量就是加密时所用偏移量,返回
这个整数偏移量。
"""
# 补充你的代码
offset = 0
for i in range(0,9):
if key_text in caesar_decrypt(ciphertext, i):
offset = i
return offset
if __name__ == '__main__':
task = input()
judge(task)
5.4文本分析和加密
第一关:统计字符数量***
思路以及重点知识:
读取文件的两行代码还要好好学习,然后五个字符串函数要好好熟悉很基础!!
任务描述
本关任务:读取附件中的文件,统计文件中大写字母、小写字母、数字、空白字符和其他字符的数量。
输出格式
文件中大写字母、小写字母、数字、空白字符和其他字符的数量;
相关知识
Python 读取文件
读取文件中的内容为字符串可以用以下函数实现:
# 读文件,返回字符串
def read_file(file):
with open(file, 'r', encoding='utf-8') as f:
return f.read()
Python 常用字符串内建函数
-
string.capitalize(
) 把字符串的第一个字符大写; -
string.count(str, beg=0, end=len(string))
返回str
在string
里面出现的次数,如果beg
或者end
指定则返回指定范围内 str 出现的次数; -
string.decode(encoding='UTF-8', errors='strict')
用于将bytes
类型的二进制数据转换为str
类型,这个过程也称为“解码”; -
string.encode(encoding='UTF-8', errors='strict')
用于将str
类型的数据转换为byte
二进制数据,这个过程也称为“编码”; -
string.find(str, beg=0, end=len(string))
检测str
是否包含在string
中,如果beg
和end
指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,否则返回-1
; -
string.format()
格式化字符串; -
string.isalnum()
如果string
至少有一个字符并且所有字符都是字母或数字则返回True
,否则返回False
; -
string.isalpha()
如果string
至少有一个字符并且所有字符都是字母则返回True
, 否则返回False
; -
string.isdecimal()
如果string
只包含十进制数字则返回True
否则返回False
; -
string.isdigit()
如果string
只包含数字则返回True
否则返回False
; -
string.islower()
如果string
中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回True
,否则返回False
; -
string.isnumeric()
如果string
中只包含数字字符,则返回True
,否则返回False
; -
string.isspace()
如果string
中只包含空格,则返回True
,否则返回False
; -
string.isupper()
如果string
中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是大写,则返回True
,否则返回False
; -
string.join(seq)
以string
作为分隔符,将seq
中所有的元素(的字符串表示)合并为一个新的字符串; -
string.ljust(width)
返回一个原字符串左对齐,并使用空格填充至长度width
的新字符串; -
string.lower()
转换string
中所有大写字符为小写; -
string.lstrip()
截掉string
左边的空格; -
max(str)
返回字符串str
中最大的字母; -
min(str)
返回字符串str
中最小的字母; -
string.replace(str1, str2, num=string.count(str1))
把string
中的str1
替换成str2
,如果num
指定,则替换不超过num
次; -
string.rstrip()
删除string
字符串末尾的空格; -
string.split(str="", num=string.count(str))
以str
为分隔符切片string
,如果num
有指定值,则仅分隔num+1
个子字符串; -
string.startswith(obj, beg=0,end=len(string))
检查字符串是否是以obj
开头,是则返回True
,否则返回False
。如果beg
和end
指定值,则在指定范围内检查; -
string.swapcase()
翻转string
中的大小写; -
string.upper()
转换string
中的小写字母为大写。
# 统计大写字母、小写字母、数字、空格和其他字符的数量
def classify_char(txt):
upper, lower, digit, space, other = 0, 0, 0, 0, 0
for ch in txt:
if ch.islower():
lower = lower + 1
elif ch.isupper():
upper = upper + 1
elif ch.isnumeric():
digit = digit + 1
elif ch.isspace():
space = space + 1
else:
other = other + 1
return upper, lower, digit, space, other
编程要求
本项目文件下载: mayun.txt 在右侧编辑器补充代码,具体要求如下:
-
读取本地的
mayun.txt
文件,返回字符串,文件存放路径为mayun.txt
; -
分类统计文件中大写字母、小写字母、数字、空白字符(包括空格、
\n
、\t
等,可用isspace()
方法判断)和其他字符的数量
测试说明
平台会对你编写的代码进行测试:
预期输出: 16 306 11 84 17
代码:
import string
# 读文件,返回字符串
def read_file(file):
# 补充你的代码
with open (file,'r') as temp:
return temp.read()
# 返回大写字母、小写字母、数字、空格和其他字符的数量
def classify_char(txt):
# 补充你的代码
upper, lower, digit, space, other = 0, 0, 0, 0, 0
for ch in txt:
if ch.islower():
lower = lower + 1;
elif ch.isupper():
upper = upper + 1;
elif ch.isnumeric():
digit = digit + 1;
elif ch.isspace():
space = space + 1;
else:
other = other + 1;
return upper,lower,digit,space,other
if __name__ == '__main__':
filename = 'mayun.txt' # 读取的文件名
text = read_file(filename) # text为字符串
print(*classify_char(text))
第二关:统计单词数量**
相关知识:
word_list稍微注意一下就可以了
任务描述
本关任务:读取附件中的文件,输出文件中单词的数量。
输出格式
输出: 文件中单词的数量;
相关知识
字符串替换
# 用空格替换所有符号,切分为列表
def word_list(txt):
for ch in '!"#$%&()*+,-.:;<=>?@[\\]^_’‘{|}~/':
txt = txt.replace(ch, " ") # 所有符号替换为空格
# print(txt)
return txt.split() # 切分为列表,返回列表
编程要求
在右侧编辑器中的 Begin-End 区间补充代码,统计单词数量。具体要求如下:
输出文件中单词的数量(将其中所有标点符号替换为空格,再根据空格对字符串进行切分可以得到元素为单词的列表。数字按单词统计,如 1994
计算一个单词)。
测试说明
平台会对你编写的代码进行测试:
预期输出:
共有86单词
代码:
import string
# 读文件,返回字符串
def read_file(file):
with open(file, 'r', encoding='utf-8') as f:
return f.read()
def word_list(txt):
"""用空格替换所有符号,切分为列表"""
for ch in '!"#$%&()*+,-.:;<=>?@[\\]^_’‘{|}~/':
# 补充你的代码
txt = txt.replace(ch,' ')
return txt.split()
def number_of_words(ls):
"""返回单词数量"""
# 补充你的代码
num = 0
for ch in ls:
if ch == ' ':
num += 1
return len(ls)
if __name__ == '__main__':
filename = 'mayun.txt' # 读取的文件名
text = read_file(filename) # text为字符串
words_list = word_list(text) # 单词的列表
words_counts = number_of_words(words_list)
print(f'共有{words_counts}单词')
第三关:计算偏移量**
思路:
学会ord函数就可以了
任务描述
本关任务:读取附件中的文件,完成文本分析与加密。
输入格式
一个代表星期几的单词,Monday
, Tuesday
, Wednesday
, Thursday
, Friday
, Saturday
, Sunday
中的一个
输出格式
输出: 输入单词的偏移量。
相关知识
偏移量
用字符串中字符ASCII值的和对26取模为偏移量
# 用字符串中字符ASCII值的和对26取模为偏移量
def offset_cal(day):
sum_of_ch = 0
for c in day:
sum_of_ch = sum_of_ch + ord(c)
offset = sum_of_ch % 26
return offset
编程要求
在右侧编辑器中的 Begin-End 区间补充代码,输出偏移量。具
测试说明
平台会对你编写的代码进行测试:
测试输入1:Tuesday
;
预期输出1: 7
测试输入2:Wednesday
;
预期输出2: 22
代码:
import string
#
def offset_cal(day):
"""用字符串中字符ASCII值的和对26取模为偏移量"""
# 补充你的代码
a = 0
for i in day:
a += ord(i)
offset = a % 26
return offset
if __name__ == '__main__':
secret_word = input()
offset_number = offset_cal(secret_word)
print(offset_number)
第四关:凯撒密码加密*
任务描述
本关任务:读取附件中的文件,完成文件加密。
输入格式
一个代表星期几的单词,Monday
, Tuesday
, Wednesday
, Thursday
, Friday
, Saturday
, Sunday
中的一个
输出格式
输出:
用恺撒加密方法对上述文件内容进行加密的结果。
相关知识
凯撒密码
在密码学中,凯撒密码是一种最简单且最广为人知的加密技术。恺撒密码
据传是古罗马恺撒大帝用来保护重要军情的加密系统。它是一种替换加密的技术,明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。例,当偏移量是 3
的时候,所有的字母 A
将被替换成 D
,B
变成 E
,以此类推,小写字母也一样处理,其他字符忽略,不作任何改变。
def kaisa(txt, number):
lower = string.ascii_lowercase # 小写字母
upper = string.ascii_uppercase # 大写字母
before = string.ascii_letters
after = lower[number:] + lower[:number] + upper[number:] + upper[:number]
table = ''.maketrans(before, after) # 创建映射表
return txt.translate(table)
编程要求
在右侧编辑器中的 Begin-End 区间补充代码,完成文件分析与加密。具体要求如下:
用恺撒加密方法对上述文件内容进行加密,为提高加密强度,约定输入一个秘密单词来产生偏移量;
测试说明
平台会对你编写的代码进行测试:
测试输入:Tuesday
;
预期输出:
Ayplk 3 aptlz mvy bupclyzpaf. Hss mhpslk. P hwwsplk mvy Ohychyk mvy 10 aptlz. Hss mhpslk, aolf kvu’a lclu dhua av zll tl. Mvy aol shza aptl, P dlua av aol alhjolyz’ jvsslnl dopjo dhz jvuzpklylk aol aopyk vy mvbyao jshzz vm tf jpaf. P hwwsplk qviz mvy 30 aptlz. Nva ylqljalk. Pa dhz zv kpmmpjbsa ha aoha aptl, P dhz zv mybzayhalk. Iljhbzl P ahbnoa pu aol bupclyzpaf. Tf whf dhz $10 h tvuao. Iljhbzl P jvbsk uva mpuk h nvvk qvi pu 1994.
代码:
import string
# 读文件,返回字符串
def read_file(file):
with open(file, 'r', encoding='utf-8') as f:
return f.read()
#
def offset_cal(day):
"""用字符串中字符ASCII值的和对26取模为偏移量 """
sum_of_ch = 0
for c in day:
sum_of_ch = sum_of_ch + ord(c)
offset = sum_of_ch % 26
return offset
def kaisa(txt, number):
# 补充你的代码
x1 = string.ascii_lowercase
x2 = string.ascii_uppercase
begin = x1 + x2
after = x1[number:] + x1[:number]+ x2[number:] + x2[:number]
fin = ''.maketrans(begin,after)
return txt.translate(fin)
if __name__ == '__main__':
filename = 'mayun.txt' # 读取的文件名
text = read_file(filename) # text为字符串
secret_word = input()
offset_number = offset_cal(secret_word)
print(kaisa(text, offset_number))
5.5日期分析处理
第一关:判断闰年****
笔记:
学会if里面判断的方法
任务描述
本关任务:一个8
位表示的年月日,如20200220
,前4
位表示年份,5-6
位表示月份,7-8
位表示日期。编写程序对日期数据进行处理和分析。
相关知识
为了完成本关任务,你需要掌握: 1.字符串索引 2.字符串切片 3.判定闰年
字符串索引
索引是指通过序列数据的序号返回其对应的字符或元素的操作。
可以按正向序号进行索引或按逆向序号进行索引,通过序号获取对应的元素。
- 字符串中第一个元素的索引为 0
- 字符串中最后一个元素的索引为 -1
示例:
s = 'Hello Python!' # 字符串,13个字符,空格算字符
print(s[0]) # 按序号正向索引,返回序号为0的字符 'H'
print(s[-13]) # 按逆向序号索引,返回序号为-13的字符 'H'
print(s[6]) # 按序号正向索引,返回序号为6的字符 'P'
print(s[-7]) # 按逆向序号索引,返回序号为-7的字符字符 'P'
注意:空格也是一个字符,所以str[5]
输出的是空格
字符串切片
切片是从一个序列中获取一个子序列,切片结果的数据类型与原序列相同。
s = 'Hello World!'
print(s[6:12]) # 根据序号[6:12]切片,输出不包括序号12的字符串'World!'
print(s[:-7]) # 从序号-12向后到-7切片,输出'Hello'
print(s[6:-1]) # 混用正负索引,输出'World'
print(s[6:]) # World!,未切取到最后字符 “!”
判定闰年
闰年(Leap Year)是为了弥补因人为历法规定造成的年度天数与地球实际公转周期的时间差而设立的。平年有365天,闰年有366天(2月中多一天)。公历年份是400的倍数为闰年,或年份是4的倍数且不是100的倍数的为闰年。
year = int(input())
if year % 400 == 0 or year % 4 == 0 and year % 100 != 0:
print(f'{year}是闰年')
else:
print(f'{year}是平年')
输入输出格式
输入格式
- 输入一个
8
位长度的表示日期的数字字符串(题目确保输入的字符串只包含0-9
的数字,且长度为8
位)
输出格式
- 根据输入数据中表示年份的数字判断是否为闰年。
编程要求
根据提示,在右侧编辑器补充代码。
测试说明
平台会对你编写的代码进行测试:
测试输入:
20200229
预期输出:
2020年是闰年
代码
def leap(current_date):
"""接收一个用8个字符表示日期的字符串为参数,判断这个日期中的年份是否为闰年
返回值为布尔型。
闰年的判定方法是:能被400整除或能被4整除且同时不能被100整除的是闰年。
"""
# 补充你的代码
flag = True
year = current_date[:4]
year = eval(year)
if year % 4 == 0 and (year % 100 != 0 or year % 400 == 0):
flag = True
else :
flag = False
return flag
if __name__ == '__main__':
date = input() # 输入一个表示年份的8位数字字符串
if leap(date[:4]): # 如果输入的年份是闰年
print(f'{date[:4]}年是闰年')
else:
print(f'{date[:4]}年不是闰年')
第二关:输出当前月有多少天***
笔记:
eval不能用在list里面,得要用int
任务描述
本关任务:一个8
位表示的年月日,如20200220
,前4
位表示年份,5-6
位表示月份,7-8
位表示日期。编写程序对日期数据进行处理和分析。
输入输出格式
输入格式
- 输入一个
8
位长度的表示日期的数字字符串(题目确保输入的字符串只包含0-9
的数字,且长度为8
位)
输出格式
- 输出当前月份共有多少天?
编程要求
根据提示,在右侧编辑器补充代码。
测试说明
平台会对你编写的代码进行测试:
测试输入:
20200229
预期输出:
2020年2月有29天
代码:
def days_of_month(current_date):
"""接收一个用8个字符表示日期的字符串为参数,计算这个日期中的月份有多少天?返回值为整型,
表示当前月份天数。
@参数 current_date:表示日期,字符串类型
"""
# 补充你的代码
list1 =[31,28,31,30,31,30,31,31,30,31,30,31]
list2 =[31,29,31,30,31,30,31,31,30,31,30,31]
month = current_date[4:6]
#print(month)
ask = int(month)
if leap(current_date) == True:
return list2[ask - 1]
else :
return list1[ask - 1]
def leap(current_date):
"""接收一个用8个字符表示日期的字符串为参数,判断这个日期中的年份是否为闰年
返回值为布尔型。
闰年的判定方法是:能被400整除或能被4整除且同时不能被100整除的是闰年。
"""
# 补充你的代码
year = current_date[:4]
year = eval(year)
if year % 400 == 0 or year % 4 == 0 and year %100 != 0:
return True
else :
return False
if __name__ == '__main__':
CurrentDate = input()
days = days_of_month(CurrentDate)
print(f'{CurrentDate[:4]}年{int(CurrentDate[4:6])}月有{days}天')
第三关:日期转换格式****
笔记:
学会字符串相加和切片~
任务描述
本关任务:一个8
位表示的年月日,如20200220
,前4
位表示年份,5-6
位表示月份,7-8
位表示日期。编写程序对日期数据进行处理和分析。
相关知识
为了完成本关任务,你需要掌握: 1.字符串切片
索引
在了解切片之前我们先要了解字符串索引,什么是索引呢?我们先来看张图:
如图所示,数字就是字符串的索引,有正向的也有反向的。字符串是字符的有序集合,可以通过其位置来获得具体的元素,而索引就是字符串的位置标记。索引从 0 开始。Python 可以取负值,表示从末尾提取,最后一个为 -1,倒数第二个为 -2,即程序认为可以从结束处反向计数。
- 字符串中第一个元素的索引为 0
- 字符串中最后一个元素的索引为 -1
str[0]
获取第一个元素str[-2]
获取倒数第二个元素
示例:
str = "hello world"
print(str[0])
print(str[1])
print(str[5])
print(str[6])
print(str[-2])
输出:
h
e
w
l
注意:空格也是一个字符,所以
str[5]
输出的是空格
切片
切片其实就是把字符串使用指定规则按照索引分割。 通常上边界不包括在提取字符串内(包头不包尾)。 如果没有指定值,则分片的边界默认为0
和序列的长度。
str[1:3 ]
获取从索引为1
的字符一直到索引为3
的字符串,不包括索引为3
的字符串str[1:]
获取从索引为1
的字符一直到字符串的最后一个字符(包括最后一个字符)str[:3]
获取从索引为0
的字符一直到索引为3
的字符串,不包括索引为3
的字符串str[:-1]
获取从索引为0
的字符一直到最后一个字符(不包括最后一个字符串)str[:]
获取字符串从开始到结尾的所有元素str[-3:-1]
获取索引为-3
到索引为-1
的字符,不包括索引为-1
的字符str[-1:-3]
和str[2:0]
获取的为空字符,系统不提示错误- 分片的时候还可以增加一个步长,如
str[::2]
示例:
str = "hello world"
print(str[1:3])
print(str[1:])
print(str[:3])
print(str[:-1])
print(str[-3:-1])
print(str[-1:-3])
print(str[::2])
输出:
el
ello world
hel
hello worl
rl
hlowrd
输入输出格式
输入格式
- 输入一个
8
位长度的表示日期的数字字符串(题目确保输入的字符串只包含0-9
的数字,且长度为8
位) - 第二行输入一个分割符号
sign
输出格式
- 输出用
sign
符号分隔的日期输出,例如输入/
,输出2020/09/09
。
编程要求
根据提示,在右侧编辑器补充代码。
测试说明
平台会对你编写的代码进行测试:
测试输入:
20200229
/
预期输出:
2020/02/29
代码:
def separate_date(current_date, symbol):
"""接收一个用8个字符表示日期的字符串和一个符号为参数,返回用该符号分隔的日期,字符串类型。
@参数 current_date:表示日期,字符串类型
@参数 symbol:分隔符号,字符串类型
例如传入'20201031'和"/",返回字符串'2020/09/09'
"""
# 补充你的代码
year = current_date[:4]
month = current_date[4:6]
date = current_date[6:]
a = year + symbol + month + symbol + date
return a
if __name__ == '__main__':
CurrentDate = input() # 输入8位数字表示的日期
sign = input() # 输入分隔符
print(separate_date(CurrentDate, sign)) # 输出用分隔符分隔的日期
第四关:判断日期合法性*
任务描述
本关任务:一个8位表示的年月日,如20200220,前4位表示年份,5-6位表示月份,7-8位表示日期。编写程序对日期数据进行处理和分析。
输入输出格式
输入格式
输入一个8位长度的表示日期的数字字符串(题目确保输入的字符串只包含0-9的数字,且长度为8位)
输出格式
只考虑月份和日期的合法性,判断输入的数字是否为一个合法的日期。
编程要求
根据提示,在右侧编辑器补充代码。
测试说明
平台会对你编写的代码进行测试:
测试输入:
20200229
预期输出:
20200229是合法日期
代码:
def legal_judge(current_date):
"""接收一个用8个字符表示日期的字符串为参数,判定日期的合法性,返回值为布尔型。
1,3,5,7,8,10,12月各31天,4,6,9,11各30天,闰年2月29天,平年2月28天。
@参数 current_date:表示日期,字符串类型
"""
# 补充你的代码
list1 =[31,28,31,30,31,30,31,31,30,31,30,31]
list2 =[31,29,31,30,31,30,31,31,30,31,30,31]
month = current_date[4:6]
month = int(month)
date = current_date[6:]
date = int(date)
if leap(current_date) == True:
if month >0 and month <13:
if date <= list2[month - 1]:
return True
else:
return False
else :
return False
else :
if month >0 and month <13:
if date <= list1[month - 1]:
return True
else:
return False
else :
return False
def leap(current_date):
"""接收一个用8个字符表示日期的字符串为参数,判断这个日期中的年份是否为闰年
返回值为布尔型。
闰年的判定方法是:能被400整除或能被4整除且同时不能被100整除的是闰年。
"""
# 补充你的代码
year = current_date[:4]
year = eval(year)
if year % 400 == 0 or year % 4 == 0 and year % 100 != 0:
return True
else :
return False
if __name__ == '__main__':
CurrentDate = input()
if legal_judge(CurrentDate):
print(f'{CurrentDate}是合法日期')
else:
print(f'{CurrentDate}是非法日期')
第五关:月份的英文名称*
任务描述
本关任务:一个8位表示的年月日,如20200220,前4位表示年份,5-6位表示月份,7-8位表示日期。编写程序对日期数据进行处理和分析。
输入输出格式
输入格式
输入一个8位长度的表示日期的数字字符串(题目确保输入的字符串只包含0-9的数字,且长度为8位)
输出格式
输出当前月份的单词和缩写形式
编程要求
根据提示,在右侧编辑器补充代码。
测试说明
平台会对你编写的代码进行测试:
测试输入:
20200229
预期输出:
2月英文是February,缩写为Feb.
代码:
def name_of_month(current_date):
"""接收一个用8个字符表示日期的字符串为参数,返回这个月份对应的英文单词及其缩写形式。
@参数 current_date:表示日期,字符串类型
例如:current_date为20201031,返回值为'October','Oct.'
日期的英文全称:['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October','November', 'December']
日期的英文缩写:September为前四位字母加点,其余月份均为前三位字母加点,如:'Sept.','Jan.'
"""
# 补充你的代码
list1 =['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October','November', 'December']
list2 = ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May.', 'Jun.', 'Jul.', 'Aug.', 'Sept.', 'Oct.','Nov.', 'Dec.']
month = current_date[4:6]
month = int(month)
upper = list1[month - 1]
lower = list2[month - 1]
return upper ,lower
if __name__ == '__main__':
CurrentDate = input()
monthName, monthAbbr = name_of_month(CurrentDate) # 获得月份名称和缩写
print(f'{int(CurrentDate[4:6])}月英文是{monthName},缩写为{monthAbbr}')
5.6单词猎手游戏**************
第一关:字符串、列表随机*****
笔记:
学会替代文本成空格,然后学会random函数如random.choice().
任务描述
本关任务:编写一个能处理本地文件的小程序。
相关知识
为了完成本关任务,你需要掌握: 1.字符串的处理 2.random
函数 3.列表的处理。
字符串常见的处理
- 去除空格
str.strip()
:删除字符串两边的指定字符,括号的写入指定字符,默认为空格。str.lstrip()
:删除字符串左边的指定字符,括号的写入指定字符,默认空格。str.rstrip()
:删除字符串右边的指定字符,括号的写入指定字符,默认空格。>>> a=' hello '
>>> b=a.strip()
>>> print(b)
hello
>>> a=' hello '
>>> b=a.lstrip()
>>> print(b)
hello #右边空格可能看的不是很明显
>>> a=' hello '
>>> b=a.rstrip()
>>> b
' hello'
- 替换
str.replace()
:方法把字符串中的old
(旧字符串) 替换成new
(新字符串),如果指定第三个参数max
,则替换不超过max
次。>>> s= "Hallo World!"
>>> ret= s.replace("!"," ")
>>> print(ret)
Hallo World
- 按输入字符切割
str.split()
:通过指定分隔符对字符串进行切片,如果第二个参数num
有指定值,则分割为num+1
个子字符串。>>> str = "this is string example....wow!!!"
>>> print(str.split( )) # 以空格为分隔符
['this', 'is', 'string', 'example....wow!!!']
>>> print(str.split('i',1)) # 以 i 为分隔符
['th', 's is string example....wow!!!']
>>> print(str.split('w')) # 以 w 为分隔符
['this is string example....', 'o', '!!!']
列表随机取值
random.choice()
方法返回一个列表,元组或字符串的随机项。
import random
>>> ls = [1, 2, 3, 5, 9]
>>> print(random.choice(ls))
2
>>> print(random.choice(ls))
9
我们调用 random.random()
生成随机数时,每一次生成的数都是随机的。但是,当我们预先使用 random.seed(x)
设定好种子之后,其中的 x
可以是任意数字,如 10
,这个时候,先调用它的情况下,使用 random()
生成的随机数将会是同一个。
import random
>>> ls = [1, 2, 3, 5, 9]
>>> random.seed( 10 )
>>> print(random.choice(ls))
9
>>> random.seed( 10 )
>>> print(random.choice(ls))
9
编程要求
根据提示,在右侧编辑器补充代码。 本项目文件下载:gone with the wind.txt 输入一个整数,作为随机数种子 实现 read_file(file)
函数,参数为要读取的文件名,功能是读取文件内容为字符串,用空格替换掉字符串中全部标点、符号,再根据空格切分为一个列表,返回这个列表。 实现secret_word(ls)
函数,参数为从文件中读取的单词列表,返回值为随机得到的一个单词。
测试说明
平台会对你编写的代码进行测试:
测试输入1:
2021
预期输出1:
正在从文件加载单词列表...
成功加载424122个单词
trash
测试输入2:
9999
预期输出2:
正在从文件加载单词列表...
成功加载424122个单词
know
代码:
import random
def read_file(file):
"""接收一个文件名为参数,读取文件中的内容为字符串类型,
替换字符串中的标点和符号为空格,根据空格将字符串切分为单词为元素的列表,
返回这个列表。
@参数 file:文件名,字符串类型
读取文件前先输出'正在从文件加载单词列表...'
转为列表后输出输出'成功加载了多少个单词' """
print('正在从文件加载单词列表...')
with open(file, 'r', encoding='utf-8') as novel:
txt = novel.read()
symbols = '!"#$%&()*+,-.:;[\'][\"]<=>?@[\\]^_‘{|}~/' #标点、符号 字符串
# 补充你的代码,将所有符号替换为空格
for i in symbols:
if i in txt:
txt = txt.replace(i,' ')
print(f'成功加载{len(txt.split())}个单词')
return txt.split() # 切分为列表,返回列表
def secret_word(ls):
"""参数为从文件中读取的单词列表,返回值为随机得到的一个单词。
@参数 ls:单词列表,列表类型
在测试程序时,可以先预设一个有少数单词的列表,例如随机数种子为19730516时:
# >>> ls = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
# >>> secret_word(ls)
# 'Monday'
"""
# 补充你的代码
return random.choice(ls)
if __name__ == '__main__':
test_seed = int(input())
random.seed(test_seed)
filename = 'data/gone with the wind.txt' # 文件名
wordlist = read_file(filename)
secretword = secret_word(wordlist)
print(secretword)
第二关:猜测目标单词*****
笔记:
这一节有好多东西要学
任务描述
本关任务:编写一个能根据输入的字母推测目标单词的小程序。
相关知识
为了完成本关任务,你需要掌握: 1.如何获取字符串的长度。 2.如何遍历字符串。 3.字符串的切片。 4.字符串的拼接。
字符串的处理
-
字符串长度
>>> a = 'abc'
>>> print(len(a))
3
-
遍历字符串
data = 'abc'
>>> for i in range(len(data)):
>>> print(data[i])
a
b
c
-
连接字符串
>>> a='hello '
>>> b='world'
>>> print(a+b)
hello world
-
字符串切片 字符串
[开始索引:结束索引:步长]
切取字符串为开始索引到结束索引-1
内的字符串 步长不指定时步长为1
字符串[开始索引:结束索引]
>>> a = 'abce'
>>> b = a[:3]+'d'+a[3]
>>> print(b)
abcde
编程要求
根据提示,在右侧编辑器补充代码,实现 get_guessed_word
函数,它接受三个参数: cover_word
, secretWord
和 letter
。每次猜测后产生一个由猜中字母和下划线与空格组成的字符串,该字符串基于猜出的字母在 secret_word
中的位置。
测试说明
平台会对你编写的代码进行测试:
测试输入1:
felling
预期输出1:
单词长度为7
_ _ _ _ _ _ _
当前是第1次猜测,你还有13次机会
请输入你猜测的字母:a
当前猜测结果为:_ _ _ _ _ _ _
当前是第2次猜测,你还有12次机会
请输入你猜测的字母:e
当前猜测结果为:_ e _ _ _ _ _
当前是第3次猜测,你还有11次机会
请输入你猜测的字母:l
当前猜测结果为:_ e l l _ _ _
当前是第4次猜测,你还有10次机会
请输入你猜测的字母:g
当前猜测结果为:_ e l l _ _ g
当前是第5次猜测,你还有9次机会
请输入你猜测的字母:i
当前猜测结果为:_ e l l i _ g
当前是第6次猜测,你还有8次机会
请输入你猜测的字母:n
当前猜测结果为:_ e l l i n g
当前是第7次猜测,你还有7次机会
请输入你猜测的字母:f
当前猜测结果为:f e l l i n g
你太厉害了,居然只用了7次就猜中了单词
秘密单词是:felling
测试输入2:
abc
预期输出2:
单词长度为3
_ _ _
当前是第1次猜测,你还有5次机会
请输入你猜测的字母:c
当前猜测结果为:_ _ c
当前是第2次猜测,你还有4次机会
请输入你猜测的字母:b
当前猜测结果为:_ b c
当前是第3次猜测,你还有3次机会
请输入你猜测的字母:d
当前猜测结果为:_ b c
当前是第4次猜测,你还有2次机会
请输入你猜测的字母:a
当前猜测结果为:a b c
你太厉害了,居然只用了4次就猜中了单词
秘密单词是:abc
代码:
def get_guessed_word(cover_word, word, letter):
"""接受三个字符串为参数:分别表示正在猜测的遮盖了字母的单词、随机抽取的单词和正在猜测的字母。
每次猜测后产生一个由猜中字母和下划线与空格组成的字符串,猜中的字母显示出来,未知字母用"_"
表示,字母间留一个空格。返回每次猜测后由字母和下划线组成的字符串。
@参数 cover_word:遮盖了字母的单词,字符串类型
@参数 word:随机抽取的单词,字符串类型
@参数 letter:正在猜测的字母,字符串类型
"""
# 补充你的代码
for i in range(len(word)):
if letter == word[i]:
cover_word = cover_word[:2*i] + letter + " " + cover_word[2*(i+1):]
print(f'当前猜测结果为:{cover_word}')
return cover_word
if __name__ == '__main__':
word = input()
print(f'单词长度为{len(word)}') # 先提示用户单词长度
cover_word = '_ ' * len(word) # 产生一个由下划线与空格构成的字符串,每组下划线与空格代表一个字母
print(cover_word)
for i in range(1, 2 * len(word) + 1): # 最多猜测2倍字母数次
print(f'当前是第{i}次猜测,你还有{2 * len(word) - i}次机会')
letter = input('请输入你猜测的字母:') # 输入猜测的字母
cover_word = get_guessed_word(cover_word, word, letter)
guess_word = cover_word.replace(' ', '')
if guess_word == word: # 替换字符串中的空格,查看是否猜中
print(f'你太厉害了,居然只用了{i}次就猜中了单词')
print(f'秘密单词是:{guess_word}') # 猜中后输出时去掉单词中的空格
break
第三关:单词猎手游戏(re0)
任务描述
本关任务:编写一个程序,从一篇文章里随机取出一个单词,要求用户在有限次数内逐个字母猜测,直到猜到单词中的全部字母或超出次数限制结束游戏。
相关知识
为了完成本关任务,你需要掌握:
- 读取文件中的内容为字符串类型
- 如何操作字符串
单词猎手
-
计算机必须从文本文件中随机选择一个单词并命名为
secretWord
(本题要求用choice()
方法实现),单词可能包含大写和小写字母,为降低猜测难度,你需要将单词转为全部小写字母。 -
在开始游戏时,用户会得到单词长度为几个字符的提示和有多少次猜测机会的提示。产生一个由下划线与空格构成的字符串
cover_word
,每组下划线与空格代表一个字母。 -
游戏是交互式的,用户在每次输入猜测的字母
letter
时,要先给出提示性的信息再接受输入(input('请输入你猜测的字母:\n')
)。计算机也会给出相应的响应,如果字母在单词中存在,则在单词的相应位置显示猜中的字母,否则更新猜测次数。 -
当用户猜到了单词中全部字母,或用完所有次数还没猜测出来,游戏结束。
编程要求
根据提示,在右侧编辑器补充代码
-
输入一个“选词”、“模板”、“开始填词”三个字符串之一,根据字符串完成函数调用和输出。输入其他字符串时,无论输入的随机数种子是什么,都先输出加载单词信息再输出“输入错误 ”。
-
输入一个整数,作为随机数种子
-
实现
read_file(file)
函数,参数为要读取的文件名,功能是读取文件内容为字符串,用空格替换掉字符串中全部标点、符号,再根据空格切分为一个列表,返回这个列表。 -
实现
secret_word(ls)
函数,参数为从文件中读取的单词列表,返回值为随机得到的一个单词。 -
实现
get_guessed_word
函数,它接受三个参数:cover_word
,word
和letter
。每次猜测后产生一个由猜中字母和下划线与空格组成的字符串,该字符串基于猜出的字母在secret_word
中的位置,返回每次猜测后由字母和下划线组成的字符串。 -
实现
word_guess
函数,它接受一个参数:secret_word
。此函数返回删除了空格的猜测结果字符串。函数中限定允许猜测的次数为单词长度的2倍。若在限定次数内猜中所有字母,输出“你太厉害了,居然只用了i次就猜中了单词“,其中i为实际使用的次数。否则输出“太遗憾了,你未能在n次内猜出单词”,其中n为限定的次数。函数最后输出“秘密单词是:猜中的单词 ”,返回这个猜中的单词。
测试说明
平台会对你编写的代码进行测试:
测试输入:
选词
2021
预期输出:
正在从文件加载单词列表...
成功加载424122个单词
trash
测试输入:
模板
2021
预期输出:
正在从文件加载单词列表...
成功加载424122个单词
_ _ _ _ _
测试输入:
开始填词
2021
a
s
t
h
r
预期输出:
正在从文件加载单词列表...
成功加载424122个单词
单词长度为5
_ _ _ _ _
当前是第1次猜测,你还有9次机会
请输入你猜测的字母:a
当前猜测结果为:_ _ a _ _
当前是第2次猜测,你还有8次机会
请输入你猜测的字母:s
当前猜测结果为:_ _ a s _
当前是第3次猜测,你还有7次机会
请输入你猜测的字母:t
当前猜测结果为:t _ a s _
当前是第4次猜测,你还有6次机会
请输入你猜测的字母:h
当前猜测结果为:t _ a s h
当前是第5次猜测,你还有5次机会
请输入你猜测的字母:r
当前猜测结果为:t r a s h
你太厉害了,居然只用了5次就猜中了单词
秘密单词是:trash
代码:
import random
def read_file(file):
"""接收一个文件名为参数,读取文件中的内容为字符串类型,
替换字符串中的标点和符号为空格,根据空格将字符串切分为单词为元素的列表,
返回这个列表。
@参数 file:文件名,字符串类型
读取文件前先输出'正在从文件加载单词列表...'
转为列表后输出输出'成功加载了多少个单词' """
print('正在从文件加载单词列表...')
with open(file, 'r', encoding='utf-8') as novel:
txt = novel.read()
symbols = '!"#$%&()*+,-.:;[\'][\"]<=>?@[\\]^_‘{|}~/'
for ch in symbols:
txt = txt.replace(ch, " ") # 所有符号替换为空格
print(f'成功加载{len(txt.split())}个单词')
# print(txt.split())
return txt.split() # 切分为列表,返回列表
def secret_word(ls):
"""参数为从文件中读取的单词列表,返回值为随机得到的一个单词。
@参数 ls:单词列表,列表类型
在测试程序时,可以先预设一个有少数单词的列表,例如随机数种子为19730516时:
# >>> ls = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
# >>> secret_word(ls)
# 'Monday'
"""
#####################Begin#####################################
# 此处去掉注释符号“#”并补充你的代码
word = random.choice(ls)
return word
#####################End#####################################
def get_guessed_word(cover_word, word, letter):
"""接受三个字符串为参数:分别表示正在猜测的遮盖了字母的单词、随机抽取的单词和正在猜测的字母。
每次猜测后产生一个由猜中字母和下划线与空格组成的字符串,猜中的字母显示出来,未知字母用"_"
表示,字母间留一个空格。返回每次猜测后由字母和下划线组成的字符串。
@参数 cover_word:遮盖了字母的单词,字符串类型
@参数 word:随机抽取的单词,字符串类型
@参数 letter:正在猜测的字母,字符串类型
"""
#####################Begin#####################################
# 此处去掉注释符号“#”并补充你的代码
for i in range(len(word)):
if letter == word[i]:
cover_word = cover_word[:2*i] + letter + " " + cover_word[2*(i+1):]
#####################End#####################################
print(f'当前猜测结果为:{cover_word}')
return cover_word
def word_guess(word):
"""以随机抽取的秘密单词为参数,参数类型为字符串。
@参数 word:随机抽取的秘密单词,字符串类型
先输出一个单词长度的提示信息,产生一个由下划线与空格构成的字符串,每组下划线与空格代表一个字母
限制用户最多猜测次数为单词长度的2倍
每次猜测并输入一个字母,调用get_guessed_word()函数对猜测进行处理。
然后回车换行,并按题目要求进行输出。
若去除处理后的单词中的空格后得到的单词与传入参数相同,表示已经猜中了秘密单词。
例如秘密单词为'Tuesday',且用户在6次猜测时猜中了单词中的全部字母,此时输出:
你太厉害了,居然只用了6次就猜中了单词
秘密单词是:Tuesday
'"""
#####################Begin#####################################
# 此处去掉注释符号“#”并补充你的代码
print(f'单词长度为{len(word)}') # 先提示用户单词长度
cover_word = '_ ' * len(word) # 产生一个由下划线与空格构成的字符串,每组下划线与空格代表一个字母
print(cover_word)
for i in range(1, 2 * len(word) + 1): # 最多猜测2倍字母数次
print(f'当前是第{i}次猜测,你还有{2 * len(word) - i}次机会')
letter = input('请输入你猜测的字母:') # 输入猜测的字母
cover_word = get_guessed_word(cover_word, word, letter)
guess_word = cover_word.replace(' ', '')
if guess_word == word: # 替换字符串中的空格,查看是否猜中
print(f'你太厉害了,居然只用了{i}次就猜中了单词')
print(f'秘密单词是:{guess_word}') # 猜中后输出时去掉单词中的空格
return guess_word
else:
print(f'太遗憾了,你未能在{2 * len(word)}次内猜出单词')
return cover_word
#####################End#####################################
def judge(txt):
"""接收一个字符串为参数,根据参数值调用不同函数完成任务"""
test_seed = int(input())
random.seed(test_seed)
filename = 'data/gone with the wind.txt' # 文件名
wordlist = read_file(filename)
secretword = secret_word(wordlist)
if txt == '选词': # 输出抽中的单词
#####################Begin#####################################
# 此处去掉注释符号“#”并补充你的代码
print(secretword)
#####################End#####################################
elif txt == '模板': # 输出猜词模板,形如:_ _ _ _ _ _
#####################Begin#####################################
# 此处去掉注释符号“#”并补充你的代码
print('_ ' * len(secretword))
#####################End#####################################
elif txt == '开始填词':
word_guess(secretword)
else:
print('输入错误')
if __name__ == '__main__':
text = input()
judge(text)
5.7维吉尼亚密码(re0)
第一关:维吉尼亚密码——解密
代码:
import string
def vigenere_decrypt(text, key):
"""接收密文字符串和密钥字符串为参数,返回解密后的字符串.
解密时字母和数字以外的其他字符原样输出。"""
lower_tab = string.ascii_lowercase # 小写字母
upper_tab = string.ascii_uppercase # 大写字母
digit_tab = string.digits
# 补充你的代码
plain_text = ''
key_index = 0
for char in text:
if char.isupper():
offset = ord(key[key_index % len(key)].upper()) - ord('A')
plain_text += upper_tab[(upper_tab.index(char) - offset) % 26]
key_index += 1
elif char.islower():
offset = ord(key[key_index % len(key)].lower()) - ord('a')
plain_text += lower_tab[(lower_tab.index(char) - offset) % 26]
key_index += 1
elif char.isdigit():
offset = ord(key[key_index % len(key)].upper()) - ord('A')
plain_text += digit_tab[(digit_tab.index(char) - offset) % 10]
key_index += 1
else:
plain_text += char
return plain_text
if __name__ == '__main__':
secret_key = input()
cipher_text = input()
plain_text = vigenere_decrypt(cipher_text, secret_key)
print(f'解密后得到的明文是{plain_text}')
第二关:维吉尼亚密码——加密
代码:
import string
def vigenere_encryption(text, key):
"""接收明文字符串和密钥字符串为参数,返回加密后的字符串.
加密时字母和数字以外的其他字符原样输出。
数字加密时,根据对应的密钥字符在字母表中的偏移量对10取模得到数字的偏移量。
例如当前数字为1,对应的密钥字母是R,R的偏移量是17,对10取模为7,1 2 3 4 5 6 7 8 9 0 中序号为7的数字是8,加密结果即为8"""
lower_tab = string.ascii_lowercase # 小写字母
upper_tab = string.ascii_uppercase # 大写字母
digit_tab = string.digits
# 补充你的代码
cipher_text = ''
key_index = 0
for char in text:
if char.isupper():
offset = ord(key[key_index % len(key)].upper()) - ord('A')
cipher_text += upper_tab[(upper_tab.index(char) + offset) % 26]
key_index += 1
elif char.islower():
offset = ord(key[key_index % len(key)].lower()) - ord('a')
cipher_text += lower_tab[(lower_tab.index(char) + offset) % 26]
key_index += 1
elif char.isdigit():
offset = ord(key[key_index % len(key)].upper()) - ord('A')
cipher_text += digit_tab[(digit_tab.index(char) + offset) % 10]
key_index += 1
else:
cipher_text += char
return cipher_text
if __name__ == '__main__':
secret_key = input()
plain_text = input()
plain_to_cipher_text = vigenere_encryption(plain_text, secret_key)
print(f'加密后得到的密文是{plain_to_cipher_text}')
5.8WIFI密码
第一关:计算整数幂*****
笔记:
要学会如何以科学计数法输出,或不已科学计数法输出;
任务描述
小明在武汉理工大学读书,学校的wifi密码是楼栋号的房间号次幂的前16位的16进制表示,且其中字母均为大写。本项目就带你一步一步的破解这个密码。
本关任务:编写一个能计算整数的整数次幂的小程序。
相关知识
为了完成本关任务,你需要掌握: 1.幂运算函数
幂运算函数
内置函数pow(base, exp[, mod]) 返回 base 的 exp 次幂;如果 mod 存在,则返回 base 的 exp 次幂对 mod 取余(比 pow(base, exp) % mod 更高效)。 两参数形式 pow(base, exp) 等价于乘方运算符: base**exp。
print(pow(2,10))
输出: 1024
编程要求
根据提示,在右侧编辑器补充代码,输入楼栋号和房间号,计算并输出楼栋号的房间号次幂。
测试说明
平台会对你编写的代码进行测试:
测试输入: 4 # 4号楼
102 # 102号房间
预期输出: 25711008708143844408671393477458601640355247900524685364822016
代码:
a = int(input())
b = int(input())
print(pow(a,b))
第二关:输出幂运算的前n位数*
任务描述
小明在武汉理工大学读书,学校的wifi密码是楼栋号的房间号次幂的前16位的16进制表示,且其中字母均为大写。本项目就带你一步一步的破解这个密码。
本关任务:编写一个能输出一个整数的整数次幂的前n位数的小程序。
相关知识
为了完成本关任务,你需要掌握: 1.整数转字符串 2.字符串切片
整数转字符串
str(number)可以将整数num转为字符串类型,后续可用字符串方法进行操作。
print(str(5070602400912917605986812821504))
输出: '5070602400912917605986812821504'
字符串切片
s[m: n] 可以返回字符串s中序号从m开始(包括m)到n结束(包括n)的子字符串。m省略时从第一个字符开始,n省略时到最后一个字符结束(包括最后一个字符)
print('5070602400912917605986812821504'[:12])
输出: 507060240091
编程要求
根据提示,在右侧编辑器补充代码,在输入楼栋号和房间号,计算并输出楼栋号的房间号次幂的前16位数字。
测试说明
平台会对你编写的代码进行测试:
测试输入: 4 # 4号楼
102 # 102号房间
预期输出: 2571100870814384
代码:
a = int(input())
b = int(input())
print(f'{pow(a,b)}'[:16])
第三关:转为十六进制数***
笔记:
学会hex()函数,转为十六进制,里面要为int
任务描述
小明在武汉理工大学读书,学校的wifi密码是楼栋号的房间号次幂的前16位的16进制表示,且其中字母均为大写。本项目就带你一步一步的破解这个密码。
本关任务:编写一个能输出一个整数的整数次幂的前n位数转为十六进制数的小程序。
相关知识
为了完成本关任务,你需要掌握: 1.整数字符串转整数 2.整数转十六进制
整数字符串转整数
int(str)可以将整数字符串str转为整数类型,后续可用整数方法或函数进行运算。
print(int('507060240091'))
输出: 507060240091
整数转十六进制
内置函数hex(x)可以将整数转换为以“0x”为前缀的小写十六进制字符串。
print(hex(507060240091))
输出: 0x760f253edb
编程要求
根据提示,在右侧编辑器补充代码,在输入楼栋号和房间号,计算并输出楼栋号的房间号次幂的前16位数字的十六进制表示。
测试说明
平台会对你编写的代码进行测试:
测试输入: 4 # 4号楼
102 # 102号房间
预期输出: 0x9226712162ab0
代码:
a = int(input())
b = int(input())
print(hex(int(f'{pow(a,b)}'[:16])))
第四关:字母转大写***
笔记:
学会upper()
任务描述
小明在武汉理工大学读书,学校的wifi密码是楼栋号的房间号次幂的前16位的16进制表示,且其中字母均为大写。本项目就带你一步一步的破解这个密码。
本关任务:编写一个能输出一个整数的整数次幂的前n位数转为十六进制数的且使出现的字母都是大写表示的小程序。
相关知识
为了完成本关任务,你需要掌握: 1.字母转大写
整数字符串转整数
str.upper()返回原字符串str的副本,其中所有区分大小写的字符均转换为大写。 注意,括号中无参数,这个方法作用在点前面的字符串上,将前面字符串中的小写字母转为大写,其他字符不变。
print('0x9226712162ab0'.upper())
输出: 0X9226712162AB0
编程要求
根据提示,在右侧编辑器补充代码,在输入楼栋号和房间号,计算并输出楼栋号的房间号次幂的前16位数字的十六进制的大写表示。
测试说明
平台会对你编写的代码进行测试:
测试输入: 4 # 4号楼
102 # 102号房间
预期输出: 0X9226712162AB0
代码:
a = int(input())
b = int(input())
print(f"{hex(int(f'{pow(a,b)}'[:16]))}".upper())
第五关:计算wifi密码*****
代码:
a = int(input())
b = int(input())
c = int(input())
print(f"{hex(int(f'{pow(a,b)}'[:c]))}"[2:].upper())