期末考试来临,WPS在线模板助你临阵磨枪
1166
2022-05-29
文章目录
1 选择题(每题2分,共20分)
2 简答题(每题3分,共30分)
3 应用题(每题5分,共50分)
3.1 庞大的牛群
3.2 古堡之门
3.3 二维列表转置
3.4 用print函数画圆
3.5 约瑟夫环
3.6 扑克牌中的顺子
3.7 青蛙上台阶
3.8 24点游戏
3.9 背包问题
3.10 空间直线相交问题
参-
1 选择题
2 简答题
3 应用题
3.1 庞大的牛群
3.2 古堡之门
3.3 二维列表转置
3.4 用print函数画圆
3.5 约瑟夫环
3.6 扑克牌中的顺子
3.7 青蛙上台阶
3.8 24点游戏
3.9 背包问题
3.10 空间直线相交问题
不要当真,这只是一套模仿英语四六考试的Python编程能力自测题,完全基于Python基础语法和标准模块,仅最后一题,用到了NumPy模块。参-附于文末,读者可自行核对。如果得分超过60分,相当于英语四级水平;得分超过80分,相当于英语六级水平。
1 选择题(每题2分,共20分)
A C是其中最早古老的
B C#是其中最年轻的
C C++比Java的历史更久
D Java比Python的历史更久
A 詹姆斯·高斯林(James Gosling)
B 林纳斯·托瓦兹(Linus Torvalds)
C 吉多·范罗苏姆(Guido van Rossum)
D 廖雪峰
A [1,2,3]
B [4,5]
C [5,3,1]
D 显示异常信息
A [1,2,9,9,5]
B [1,2,9,5]
C [1,2,[9],5]
D 显示异常信息
A d[‘name’]
B d.name
C d.get(‘name’)
D d.get(‘age’)
A a[0] = b[1]
B a[0] == b[1]
C a+b
D (*a, *b)
A list(s)
B set(s)
C tuple(s)
D dict(s)
A [i if i%2 else i*2 for i in range(5)]
B [i if i%2 for i in range(5)]
C [i for i in range(5) if i%2]
D x = 3 if 3*7==21 else 4
[True, 5, 0, False, None, '0', '', 'False'].count(False)
1
A 1
B 2
C 3
D 4
''.join(map(lambda s:s*2, 'abc'))
1
A ‘abcabc’
B [‘aa’, ‘bb’, ‘cc’]
C [‘abc’, ‘abc’]
D ‘aabbcc’
2 简答题(每题3分,共30分)
3 and 4 * 5 or 6
1
z = zip('xyz', (1,2,3)) for i in range(2): for k, v in z: print('%s=%d'%(k,v))
1
2
3
4
import threading import time def func(): for i in range(5): print(i) time.sleep(1) threading.Thread(target=func).start() time.sleep(3) print('程序结束')
1
2
3
4
5
6
7
8
9
10
11
3 应用题(每题5分,共50分)
3.1 庞大的牛群
假定你现在养了一头母牛,它每年元旦都生一头小母牛。每头小母牛从四周岁开始,每年元旦也生一头小母牛。不考虑牛的寿命和生育年限,过了n个元旦之后,你总共拥有多少头牛?
3.2 古堡之门
福尔摩斯到某古堡探险,看到门上写着一个奇怪的算式:
ABCDE × G = EDCBA
1
他对华生说:“ABCDE应该代表不同的数字,G也代表某个数字!”
华生:“我猜也是!”
于是,两人沉默了好久,还是没有算出合适的结果来。
请利用计算机的优势,找到破解的答案。
3.3 二维列表转置
严格讲,Python的列表并没有维度的概念。这里说的二维列表是指类似下面这样的列表。
[ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]
1
2
3
请实现二维列表的转置(行列互换,首行变首列,尾行变尾列,如下所示)。
[ [1, 4, 7], [2, 5, 8], [3, 6, 9] ]
1
2
3
3.4 用print函数画圆
使用print()函数打印星号,形成一个近似的圆。考虑到在文本显示模式下字符的宽高不相等,以及字符水平间距和行间距不相等等因素,可以在水平方向重复字符以保持合适的看高比例。
3.5 约瑟夫环
从1开始的n个连续整数顺时针组成n个元素的环形队列,从元素1开始沿顺时针方向计数,将第m个元素剔除队列,紧接着从下一个元素重新开始计数,将第m个元素剔除队列……直至队列剩余一个元素,并返回该元素的值。
3.6 扑克牌中的顺子
从扑克牌中随机抽5张牌,判断是不是顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,大小王用0表示,可代表任意数字。
3.7 青蛙上台阶
青蛙每次至少可以跳上一层台阶,最多可以跳上两个台阶,计算青蛙跳上N层台阶总共有多少种方式。
3.8 24点游戏
几乎每个人都玩过24点游戏,规则也很简单:任意给出4个数字(视难度不同,一般是10以内或13以内的数字,允许重复),每个数字只能且必须使用1次,利用加减乘除四则运算,使得计算结果为24。例如,4个数字分别为5,5,5,1,则有(5-1/5)*5 = 24。请用代码解决24点问题,若有解,则打印解,若无解,则打印无解。
3.9 背包问题
在一款英雄对战游戏中,玩家拥有m件装备和n位英雄,他可以给每一位英雄分配0件或多件装备,而不同的英雄拥有不同数目的装备时将获得不同的攻击力。玩家如何分配这m件装备,可以使得n个英雄获得的攻击力的和最大?以玩家拥有5件装备和3位英雄为例,列表p共有3行6列,对应着3位英雄分别拥有从0到5件装备时的攻击力。
3.10 空间直线相交问题
ABCD是欧氏空间中不重合的四个点,判断过点AB的直线和过点CD的直线是否相交。
参-
1 选择题
DCCBBADBBD
2 简答题
参-1
>>> 0xab + 0b1100 183
1
2
参-2
>>> int('0xab', base=16) + int('0b1100', base=2) 183
1
2
参-
>>> ''.join([chr(ord('A')+i) for i in range(26)]) 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
1
2
参-
>>> cmd = input('请变量名和变量值(以等号分隔):') 请变量名和变量值(以等号分隔):x=5 >>> exec(cmd) >>> x 5
1
2
3
4
5
参-
>>> s = 'erwerflkfjsfldkfberwefrasdafsasfdadfasd' >>> max(set(s), key=s.count) 'f'
1
2
3
参-
def is_isomo(n): return str(n*n)[-len(str(n)):] == str(n) >>> is_isomo(5) True
1
2
3
4
5
这段代码中两次使用str(n),效率一定会打折,追求完美的同学肯定无法接受。下面的代码使用了海象符号(Py3.8及更高版本支持),可以完美地解决这个问题。
def is_isomo(n): return str(n*n)[-len((s:=str(n))):] == s >>> is_isomo(6) True
1
2
3
4
5
参-
写成下面这样,看起来没有问题,但若存在重复元素,则可能导致结果错误。
>>> def find_lucky(arr): return list(filter(lambda x:x==arr.index(x), arr)) >>> find_lucky([1, 1, 2, 5]) [2]
1
2
3
4
5
这样写才是正确的。
>>> def find_lucky(arr): return [item[1] for item in filter(lambda x:x[0]==x[1], enumerate(arr))] >>> find_lucky([1, 1, 2, 5]) [1, 2]
1
2
3
4
5
参-
2的整数次幂,写成二进制一定是高位为1其余为0。利用这个特征,很容易判断一个数是否是2的整数次幂。
>>> def check_pow(num): return num > 0 and num & num-1 == 0 >>> check_pow(256) True
1
2
3
4
5
3 and 4 * 5 or 6
1
参-
20
1
z = zip('xyz', (1,2,3)) for i in range(2): for k, v in z: print('%s=%d'%(k,v))
1
2
3
4
参-
x=1 y=2 z=3
1
2
3
import threading import time def func(): for i in range(5): print(i) time.sleep(1) threading.Thread(target=func).start() time.sleep(3) print('程序结束')
1
2
3
4
5
6
7
8
9
10
11
参-
4
1
3 应用题
3.1 庞大的牛群
假定你现在养了一头母牛,它每年元旦都生一头小母牛。每头小母牛从四周岁开始,每年元旦也生一头小母牛。不考虑牛的寿命和生育年限,过了n个元旦之后,你总共拥有多少头牛?
参-1(5分)
从第5个元旦开始,每年新增的小牛数量是4年前的母牛总数,因此过了n个元旦之后牛的数量,等于4年前的牛的数量,加上上一个年的牛的数量。
>>> def cows(n): if n < 4: return n+1 return cows(n-1) + cows(n-4) >>> cows(5) 7 >>> cows(10) 36 >>> cows(20) 907
1
2
3
4
5
6
7
8
9
10
11
参-2(5分)
递归虽然简洁,但未必是最佳选择。本题的四级参-是一个非线性递归,复杂度为递归深度的平方,效率很低。其实,同样的思路,不用递归实现的话,速度就会快很多,只是代码没有递归那么优雅。
>>> def cows(n): if n < 4: return n+1 result = [1,2,3,4] for i in range(4, n+1): result.append(result[0]+result[-1]) result = result[1:] return result[-1] >>> cows(5) 7 >>> cows(10) 36 >>> cows(20) 907
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
3.2 古堡之门
福尔摩斯到某古堡探险,看到门上写着一个奇怪的算式:
ABCDE × G = EDCBA
1
他对华生说:“ABCDE应该代表不同的数字,G也代表某个数字!”
华生:“我猜也是!”
于是,两人沉默了好久,还是没有算出合适的结果来。
请利用计算机的优势,找到破解的答案。
参-1(3分)
中规中矩的写法,代码结构存在改进空间。
>>> def cbble(): for i in range(10000, 100000): a, quotient = divmod(i, 10000) b, quotient = divmod(quotient, 1000) c, quotient = divmod(quotient, 100) d, e = divmod(quotient, 10) parts =set([a,b,c,d,e]) if len(parts) == 5: for j in range(1, 10): k = 10000*e + 1000*d + 100*c + 10*b +a if j not in parts and i*j == k: print('%d x %d = %d'%(i, j, k)) break >>> cbble() 21978 x 4 = 87912
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
参-2(5分)
追求结构的优美甚于追求更高的效率,尽管不是最佳选择,但对于此问题却是合适的。
>>> def cbble(): for i in range(10000, 100000): a,b,c,d,e = map(int, str(i)) parts =set([a,b,c,d,e]) if len(parts) == 5: k = 10000*e + 1000*d + 100*c + 10*b +a for j in range(1, 10): if j not in parts and i*j == k: return('%d x %d = %d'%(i, j, k)) return '此题无解!' >>> cbble() '21978 x 4 = 87912'
1
2
3
4
5
6
7
8
9
10
11
12
13
3.3 二维列表转置
严格讲,Python的列表并没有维度的概念。这里说的二维列表是指类似下面这样的列表。
[ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]
1
2
3
请实现二维列表的转置(行列互换,首行变首列,尾行变尾列,如下所示)。
[ [1, 4, 7], [2, 5, 8], [3, 6, 9] ]
1
2
3
参-1(3分)
不考虑检查列表是否满足转置的条件(列表每个元素都是长度相等的列表),初级程序员根据第一直觉写出来的代码几乎都是这样的。
>>> def transpose(arr): result = list() for j in range(len(arr[0])): result.append(list()) for i in range(len(arr)): result[j].append(arr[i][j]) return result >>> transpose([[1,2,3], [4,5,6], [7,8,9]]) [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
1
2
3
4
5
6
7
8
9
10
参-2(5分)
作为中高级程序员必然掌握使用一颗星(*)和两颗星(**)的魔法,内置函数用起来更是得心应手。
>>> def transpose(arr): return list(zip(*arr)) >>> transpose([[1,2,3], [4,5,6], [7,8,9]]) [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
1
2
3
4
5
3.4 用print函数画圆
使用print()函数打印星号,形成一个近似的圆。考虑到在文本显示模式下字符的宽高不相等,以及字符水平间距和行间距不相等等因素,可以在水平方向重复字符以保持合适的看高比例。
参-(5分)
优秀的程序员数学至少要及格才行。画圆,得先计算出圆上个点的位置。通常要借助于参数方程,比如,令角度变量theta从0°变到360°,对应每个theta,圆上点坐标为:
x = R * cos(theta) y = R * sin(theta)
1
2
理解了这个思路,下面的代码就很容易看懂了。三角函数来自Python的标准模块math,该模块还包括度和弧度互转等很多数学函数。代码中的
>>> import math >>> def print_circle(r, k): # r为半径,k为宽高比矫正系数 theta = range(0,360,5) x = [round(r*math.cos(math.radians(i))+r) for i in theta] y = [round(r*math.sin(math.radians(i))+r) for i in theta] dots = set(zip(x,y)) for i in range(2*r+1): for j in range(2*r+1): if (i,j) in dots: print('*'*k, sep='', end='') else: print(' '*k, sep='', end='') print() >>> print_circle(5, 3) *************** ****** ****** *** *** *** ****** *** *** *** *** *** *** *** *** *** *** ****** ****** ***************
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
3.5 约瑟夫环
从1开始的n个连续整数顺时针组成n个元素的环形队列,从元素1开始沿顺时针方向计数,将第m个元素剔除队列,紧接着从下一个元素重新开始计数,将第m个元素剔除队列……直至队列剩余一个元素,并返回该元素的值。
参-(5分)
>>> def joseph(n, m): queue, start = list(range(1, n+1)), 0 while len(queue) > 1: start = (m+start-1)%len(queue) queue.pop(start) return queue[0]
1
2
3
4
5
6
3.6 扑克牌中的顺子
从扑克牌中随机抽5张牌,判断是不是顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,大小王用0表示,可代表任意数字。
参-(5分)
本题有两个环节:
从扑克牌中随机抽5张牌
随机取牌,可以使用Python的内置模块random中的sample()方法,该方法可以随机地从指定列表中提取出多个不同的元素。
判断是不是顺子
将5张牌换成对应数字,剔除0后排序。若是顺子的话,前后元素之差均为1。若不是1,同时超过1的总和大于0的个数,则不是顺子,否则为顺子。
>>> import random >>> import numpy as np >>> def get_five(): poker = list(range(1,14))*4 + [0,0] # 生成54张扑克牌 return random.sample(poker, 5) >>> def is_straight(five): no_zero = list(filter(lambda x:x>0, five)) # 剔除0 if len(no_zero) > len(set(no_zero)): # 如有重复 return False # 则不是顺子 no_zero.sort() # 非零元素排序 no_zero = np.array(no_zero) # 转为numpy数组 diff = np.diff(no_zero) # diff为相邻元素的差组成的数组 if np.sum(diff - 1) > 5-no_zero.size: # 若diff各元素减1后的和大于0的个数 return False # 则不是顺子 else: return True >>> def test(n): # 测试函数 for i in range(n): five = get_five() if is_straight(five): print(five) >>> test(100) # 测试100次 [12, 10, 11, 0, 8] [5, 1, 0, 3, 2] [10, 6, 0, 7, 9]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
3.7 青蛙上台阶
青蛙每次至少可以跳上一层台阶,最多可以跳上两个台阶,计算青蛙跳上N层台阶总共有多少种方式。
参-1(5分)
跳一层只有一种方法,跳两层则有两种方法。要跳到K层,可以先跳到K-1层后再跳一次迈上一层,也可以先跳到K-2层后再一步跳上两层。显然,跳到K层的方法数量等于跳到K-1层的方法数量加上跳到K-2层的方法数量。基于这个推理,很容易写出递归代码。
>>> def climb(n): if n == 1: return 1 elif n == 2: return 2 else: return climb(n-1) + climb(n-2) >>> climb(10) 89
1
2
3
4
5
6
7
8
9
10
11
参-2(5分)
递归方法虽然简洁,但会受递归深度限制,无法计算超过递归深度的数值。其实,不使用递归,代码写起来也很简答。
>>> def climb(n): if n == 1: return 1 elif n == 2: return 2 c1, c2 = 1, 2 for i in range(2,n): c1, c2 = c2, c1+c2 return c2 >>> climb(10) 89
1
2
3
4
5
6
7
8
9
10
11
12
3.8 24点游戏
几乎每个人都玩过24点游戏,规则也很简单:任意给出4个数字(视难度不同,一般是10以内或13以内的数字,允许重复),每个数字只能且必须使用1次,利用加减乘除四则运算,使得计算结果为24。例如,4个数字分别为5,5,5,1,则有(5-1/5)*5 = 24。请用代码解决24点问题,若有解,则打印解,若无解,则打印无解。
参-(5分)
不考虑计算顺序的话,4个数字使用4种运算符连接的话,共有443424=1536种组合。若考虑使用括号改变计算顺序,则前述每一种组合又可分为11种情况。遍历全部153611=16896种组合,即可解决问题。另外,书写代码时如果使用内置的排列函数(permutations)和笛卡尔积函数(product),会使代码更简练。
>>> from itertools import permutations, product >>> def game24(n1,n2,n3,n4): for a,b,c,d in permutations((n1,n2,n3,n4),4): for o1,o2,o3 in product(['+','-','*','/'], repeat=3): # 笛卡尔积的另一种写法 cases = list() cases.append('%d%s%d%s%d%s%d'%(a,o1,b,o2,c,o3,d)) cases.append('(%d%s%d)%s%d%s%d'%(a,o1,b,o2,c,o3,d)) cases.append('%d%s%d%s(%d%s%d)'%(a,o1,b,o2,c,o3,d)) cases.append('%d%s(%d%s%d)%s%d'%(a,o1,b,o2,c,o3,d)) cases.append('(%d%s%d)%s(%d%s%d)'%(a,o1,b,o2,c,o3,d)) cases.append('(%d%s%d%s%d)%s%d'%(a,o1,b,o2,c,o3,d)) cases.append('((%d%s%d)%s%d)%s%d'%(a,o1,b,o2,c,o3,d)) cases.append('(%d%s(%d%s%d))%s%d'%(a,o1,b,o2,c,o3,d)) cases.append('%d%s(%d%s%d%s%d)'%(a,o1,b,o2,c,o3,d)) cases.append('%d%s((%d%s%d)%s%d)'%(a,o1,b,o2,c,o3,d)) cases.append('%d%s(%d%s(%d%s%d))'%(a,o1,b,o2,c,o3,d)) for expression in cases: try: # 捕获表达式中分母为0的异常 if eval(expression) == 24: print('答案:%s = 24'%expression) return except: pass print('无解!') >>> game24(5,5,5,1) 答案:5*(5-1/5) = 24 >>> game24(1,3,4,6) 答案:6/(1-3/4) = 24 >>> game24(10,10,4,4) 答案:(10*10-4)/4 = 24 >>> game24(7,7,3,3) 答案:7*(3/7+3) = 24 >>> game24(1,5,7,10) 答案:(1+7/5)*10 = 24 >>> game24(15,25,37,80) 无解!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
3.9 背包问题
在一款英雄对战游戏中,玩家拥有m件装备和n位英雄,他可以给每一位英雄分配0件或多件装备,而不同的英雄拥有不同数目的装备时将获得不同的攻击力。玩家如何分配这m件装备,可以使得n个英雄获得的攻击力的和最大?以玩家拥有5件装备和3位英雄为例,列表p共有3行6列,对应着3位英雄分别拥有从0到5件装备时的攻击力。
p = [ [0, 1, 3, 5, 7, 9], [0, 1, 1, 3, 3, 7], [0, 3, 4, 5, 6, 7] ]
1
2
3
4
5
参-(5分)
这是一个背包问题的变形。即便不熟悉背包问题,也不难找到解题思路:
找出所有可能的装备分配方案
计算每一个方案的攻击值
选择攻击值最大的分配方案
找出将m件装备分配给n位英雄的所有方案是解决问题的核心。
>>> def bag(m, n, result, series=list()): if n == 1: for i in range(m+1): result.append(series+[i]) #print(result[-1]) else: for i in range(m+1): bag(m-i, n-1, result, series+[i]) >>> result = list() >>> bag(5, 3, result) # 将5件装备分配给3位英雄,共有56种分配方案 >>> p = [ [0,1,3,5,7,9], [0,1,1,3,3,7], [0,3,4,5,6,7] ] >>> v = list() >>> for item in result: # 计算每一种方案的攻击值 v.append(p[0][item[0]] + p[1][item[1]] + p[2][item[2]]) >>> max(v) # 最大攻击值是10 10 >>> result[v.index(max(v))] # 最佳分配方案 [4, 0, 1] # 第1位英雄持有4件装备,第2位英雄没有装备,第3位英雄持有1件装备。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
3.10 空间直线相交问题
ABCD是欧氏空间中不重合的四个点,判断过点AB的直线和过点CD的直线是否相交。
参-(5分)
假如使用空间解析几何的方式,这个问题对于程序员来说是一个难题。不过,如果你熟悉NumPy,理解点积(np.dot)和叉积(np.cross)的话,解决这个问题就变得非常容易了。
计算向量ab和向量cd的叉积,得到一个新的向量orth
若向量orth的元素全部为零,则两直线平行,否则向量orth必定同时垂直于向量ab和向量cd
直线相交,则向量ac和向量orth的点积为零,否则直线必定不相交
>>> import numpy as np >>> def is_orthogonal(a, b, c, d): ab = np.array(a) - np.array(b) cd = np.array(c) - np.array(d) ac = np.array(a) - np.array(c) orth = np.cross(ab,cd) return orth.any() and np.dot(orth, ac) == 0 >>> a,b,c,d = (0,0,0),(1,0,0),(0,0,0),(0,1,0) >>> is_orthogonal(a, b, c, d) True >>> a,b,c,d = (0,0,0),(1,0,0),(0,0,1),(0,1,1) >>> is_orthogonal(a, b, c, d) False
1
2
3
4
5
6
7
8
9
10
11
12
13
14
HTTP Python
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。