【2021华为云AI实战营】Python编程知识经典题型解析(下)
Python基础语法、数据结构、正则表达式、多任务和魔法方法的使用
理论学习视频:《AI基础课程--Python编程知识》
一、凯撒密码
题目描述
世界上最简单、最著名的加密方法是凯撒密码,也叫移位密码。在移位密码中,明文中的字母通过按照一个固定数目进行偏移后被替换成新的字母。
ROT13 是一个被广泛使用的编码技术,明文中的所有字母都被移动 13 位。因此,'A' ↔ 'N', 'B' ↔ 'O' 等等。
请编写一个函数,用于解码一个被 ROT13 编码的字符串,然后返回解码后的结果。
所有解码后的字母都必须为字母大写。请不要解码非字母的字符(例如,空格、标点符号),但你需要在结果中保留它们。
代码实现
tmp=input("请输入rot13密文字符串:")
def rot13(s):
s = s.upper()
a=''
for n in s:
if not n.isupper():
a += n
break
if n<='M':
a+=chr(ord(n)+13)
else:
a+=chr(ord(n)-13)
print("解码后明文: ", a)
rot13(tmp)
二、HZF的魔法棒
题目描述
HZF有一个魔法棒,魔法棒有很多功能,其中最简单的是对字母的改变:可以将大写字母变成小写字母(A->a,B->b,C->c…Z->z),将小写字母变成大写字母(a->A…z->Z),魔法对数字不生效。HZF让你告诉他改变之后的字符串是什么样的。
输入 输入一个字符串(只包含大小写字母和数字)。每个字符串字符数(0 < n <= 1000)。
输出 输出改变后的字符串。
样例 输入样例 1
abC02 输出样例 1
ABc02
输入样例 2
aceACE 输出样例 2
ACEace 提示样例 2
代码实现
a = input("输入任意一个字符串(可含大小写字母和数字):")
b = []
for n in a :
if "a"<= n <= "z":
b.append(n.upper())
elif"A" <= n <= "Z" :
b.append(n.lower())
else:
b.append(n)
print("".join(b))
简化一下:
a = input("输入任意一个字符串(可含大小写字母和数字):")
''.join(map(chr,map(lambda x:ord(x)^32,a)))
三、电话号码验证器
题目描述
如果传入的字符串是一个有效的中国电话号码格式,则返回true。 例如: 134-4562-5655 13469587456 1314 122 9899
代码实现
import re
string = input("请输入11位手机号码:")
phone=string.replace(' ','').replace('-','')
pattern = re.compile(r'^(13[0-9]|14[0|5|6|7|9]|15[0|1|2|3|5|6|7|8|9]|'
r'16[2|5|6|7]|17[0|1|2|3|5|6|7|8]|18[0-9]|'
r'19[1|3|5|6|7|8|9])\d{8}$')
if pattern.search(phone):
print("True")
else:
print("手机号码非法!")
加上一个号码段的判断吧:
其中:
中国联通的号码段: 130,131,132,155,156,185,186,145,176
中国移动的号码段: 134, 135 , 136, 137, 138, 139, 147, 150, 151,152, 157, 158, 159, 178, 182, 183, 184, 187, 188
中国电信的号码段:133,153,189
import re
def phone():
n = input("请输入一个手机号:")
n=n.replace(' ','').replace('-','')
if re.match(r'1[3,4,5,7,8]\d{9}',n):
print("您输入的的手机号码是:",n)
if re.match(r'13[0,1,2]\d{8}',n) or \
re.match(r"15[5,6]\d{8}",n) or \
re.match(r"18[5,6]",n) or \
re.match(r"145\d{8}",n) or \
re.match(r"176\d{8}",n):
print("该号码属于——中国联通")
elif re.match(r"13[4,5,6,7,8,9]\d{8}",n) or \
re.match(r"147\d{8}|178\d{8}",n) or \
re.match(r"15[0,1,2,7,8,9]\d{8}",n) or \
re.match(r"18[2,3,4,7,8]\d{8}",n):
print("该号码属于——中国移动")
else:
print("该号码属于——中国电信")
else:
print("请输入正确的手机号")
if __name__ == '__main__':
phone()
四、生日提取
题目描述
提取所有人的生日
需要匹配的 -- 需要提取的
-
刘伟 1996.8.24 - - 8 24
-
李伟 1993年1月2日 - - 1 2
-
聂芳 1997-7-24 - - 7 24
-
陈伟 1996.3.21 - - 3 21
-
杜英 1991.12.1 - - 12 1
-
段秀 1994-7-5 - - 7 5
-
路娜 1993年1月6日 - - 1 6
编写一个正则表达式,使得以上所有的生日都能被正确提取
代码实现
import re # 导入正则表达式模块
s = input() # 输入上述任一需要提取的生日格式,如: 刘伟1996.8.24
result = re.findall('[\.年-](\d+)[\.月-](\d+)', s) # 在单引号内输入正则表达式
print(result) # 输出正确结果 如: 8 24
五、扫雷
题目描述
大家都玩过扫雷游戏吧,给定一个矩形方正区域,里面有若干个地雷,用鼠标点击,点击后如果出现一块区域,那么说明这个点周围8个方向没有地雷,如果出现数字,数字是几,那么就表示这个区域周围8个方向有几颗地雷,如果是地雷,那你很不幸就输掉了。 现在告诉你这个图里地雷的分布,你来给出每个点上面的数字应该是多少?
输入 数据的第一行有2个整数n, m(1 <= n, m <= 50),表示一个n * m的区域,n行m列,接下来n行每行有一个长度为m的字符串,字符串只包含2种字母,”.”和”X”,其中”.”表示这个地方不是地雷,”X”表示这个地方是地雷。
输出 请输出n行内容,每一行是一个长度为m的字符串,由数字和符号”X”组成,如果这个点不是地雷,那么就表示这个点周围有几颗地雷,否则这个点存放符号”X”,表示这个点是地雷。
样例 输入样例 1
3 5 ..... ..XX. ..... 输出样例 1
01221 01XX1 01221
代码实现
def myList(m): #输入列表:获取输入的符号
ls=[]
print('请依次输入每行的地图:')
for j in range(m):
s=input()
ll=[]
for i in s:
ll.append(i)
ls.append(ll)
return ls
def result(ls): #初始状态应该对应输入列表,除了对应的位置值为X ,其它的位置初始值均为0
rs=ls
for i in range(len(ls)):
for j in range(len(ls[i])):
if ls[i][j]=='X': rs[i][j]='X'
else: rs[i][j]=0
return (rs)
def check(m,n,ls): #通过检查输入列表中[i][j]点是否为雷,即X,来决定相邻的八个点的值是不是要加1(我是顺时针判断)
for i in range(m):
for j in range(n):
if ls[i][j]=='X':
if i-1>=0 and rs[i-1][j]!='X': # 判断上面是否有雷
rs[i-1][j]+=1
if i-1>=0 and j+1<n and rs[i-1][j+1]!='X': # 判断右上角是否有雷
rs[i-1][j+1]+=1
if j+1<n and rs[i][j+1]!='X': # 判断右边是否有雷
rs[i][j+1]+=1
if i+1<m and j+1<n and rs[i+1][j+1]!='X': # 判断右下角是否有雷
rs[i+1][j+1]+=1
if i+1<m and rs[i+1][j]!='X': # 判断下面是否有雷
rs[i+1][j]+=1
if i+1<m and j-1>=0 and rs[i+1][j-1]!='X': # 判断左下角是否有雷
rs[i+1][j-1]+=1
if j-1>=0 and rs[i][j-1]!='X': # 判断左边是否有雷
rs[i][j-1]+=1
if i-1>=0 and j-1>=0 and rs[i-1][j-1]!='X': # 判断左上角是否有雷
rs[i-1][j-1]+=1
else:
continue
return rs
def out(rs): #将数字列表输出为二维列表
for s in rs :
for ss in s:
print(ss,end='')
print()
m,n=map(int,(input('请输入行和列:').split()))
while True:
if m==0 and n==0:
break
else:
ls=myList(m)
rs=result(ls)
rr=check(m,n,ls)
print('结果为:')
out(rs)
print()
break
六、被选召的孩子
题目描述
小华和他的小伙伴们想要参加一个游戏,但是参加的人很多需要筛选。主办方的选择孩子的标准如下:
n个孩子从左到右站成一排,每个孩子都有一个分数(该分数为正整数),要求所选出的孩子们必须是连续的一段,而且所选出的孩子的分数的平均值必须大于等于预先给定的一个常数b。但是这样选择的方法可能并不唯一,请问有几种选法呢?
输入
第一行:输入候选孩子的个数n(1<=n<=20000)和给定的常数b(1<=b<=500)
接下来n行:输入n个孩子的分数Xi(i=1,2,…)且1<=Xi<=500。
输出
输出选择的种数。
输入样例
5 9 32 4 9 21 10
输出样例
13
提示
merge sort
a[i]表示第i个孩子的分数,s[i]表示从第一个孩子到第i个孩子(包括第i个)的分数之和,则第j个到第i个的分数的平均值为(s[j]-s[i-1])/(j-i+1),即直角坐标系上的(i-1,s[i-1]).(j,s[j])两点连线的斜率。所以平均值大于或等于b,就是斜率大于或等于b。那么判断从第i个人开始选有几种选法,过(i-1,s[i-1])做一条斜率为b的直线(与y轴交点为y[i-1]),有几个点是在它的上方。根据直线的性质,将这条直线平移到所判断的点(j,s[j]),与y轴的交点为y[j],如果y[j]<y[i-1],则不能选,否则就可以选。因而就可以通过判断y[](y[0]=0)这一组数据里,y[i]>=y[j]的对数。也可以用总的(n+1)*n/2减去逆序对(不包括相等的情况)。
代码实现
别看题目很长,其实逻辑很简单~
n,b = map(int, input('请输入候选孩子的个数n(1<=n<=20000)和给定的常数b(1<=b<=500):').split())
score = input('输入n个孩子的分数Xi(i=1,2,…)且1<=Xi<=500:')
data_list = score.strip().split()
data_list = [int(x) for x in data_list]
print(data_list)
k = 0
for i in range(1, n+1):
for j in range(n-i+1):
if sum(data_list[j:i+j]) / i >= b:
k += 1
print("共有:%d种选法" %k)
七、弟弟的作业
题目描述
你的弟弟刚做完了“100以内数的加减法”这部分的作业,请你帮他检查一下。每道题目(包括弟弟的答案)的格式为a+b=c或者a-b=c,其中a和b是作业中给出的,均为不超过100的非负整数;c是弟弟算出的答案,可能是不超过200的非负整数,也可能是单个字符”?”,表示他不会算。
输入 输入文件的第一行只有一个数字T(1 <= T <= 1000),表示下面有T个算术运算,接下来有T行,每行包含一道题目,格式有以下4种情况: a+b=c a-b=c a+b=? a-b=? 其中0 <= b <= a <= 100,0 <= c <= 200,且不包含任何空白字符。输入的所有整数均不含前导0。
输出 输出仅一行一个数字,表示”a+b=c”和”a-b=c”中计算正确的个数。
样例 输入样例 4 1+2=3 3-1=5 6+7=? 99-0=99 输出样例 2
代码实现
import re
num=int(input('请输入题数:'))
topic = []
for i in range(num):
topic.append(input('请输入您的作业:'))
k=0
for i in range(num):
work=topic[i]
result=re.match('(\d{1,2})([\+|\-])(\d{1,2})=(\d{1,3}|\?)',work)
if result:
a=result.group(1)
op=result.group(2)
b=result.group(3)
c=result.group(4)
if c!='?':
if op=='+' and int(a)+int(b)==int(c):
k+=1
elif op=='-' and int(a)-int(b)==int(c):
k+=1
print('恭喜你您答对了:%d题'%k)
- 点赞
- 收藏
- 关注作者
评论(0)