4.4 综合案例解析
例4-8 输入若干个成绩,求所有成绩的平均分。每输入一个成绩后询问是否继续输入下一个成绩,回答“yes”就继续输入下一个成绩,回答“no”就停止输入成绩。
基本思路:使用循环结构+异常处理结构来保证用户输入的合法性。关于异常处理结构请参考第11章。
1. numbers = [] 2. while True: 3. x = input(’请输入一个成绩:') 4. #异常处理结构,用来保证用户只能输入实数 5. try: 6. #先把x转换成实数,然后追加到列表numbers尾部 7. numbers.append(float(x)) 8. except: 9. print(’不是合法成绩’) 10. 11. #下面的循环用来限制用户只能输入任意大小写的“yes”或者“no” 12. while True: 13. flag = input(’继续输入吗?(yes/no)').lower() 14. if flag not in ('yes', 'no'): 15. print(’只能输入yes或no') 16. else: 17. break 18. if flag=='no': 19. break 20. 21. #计算平均分 22. print(sum(numbers)/len(numbers))
例4-9 编写程序,判断今天是今年的第几天。
基本思路:先假设二月有28天,然后获取当前日期,如果是闰年再把二月改为29天。如果当前是一月,该月第几天也就是今年的第几天;如果不是一月,先把前面已经过完的所有整月天数加起来,再加上当月的第几天,就是今年的第几天。
1. import time 2. 3. date = time.localtime() #获取当前日期时间 4. year, month, day = date[:3] #获取年、月、日信息 5. day_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] 6. #一年中每个月的天数 7. if year%400==0 or (year%4==0 and year%100! =0): #判断是否为闰年 8. day_month[1] = 29 #闰年的2月是29天 9. if month==1: 10. print(day) 11. else: 12. print(sum(day_month[:month-1])+day) #前面所有月的天数加上 13. #本月第几天
例4-10 编写代码,输出由星号*组成的菱形图案,并且可以灵活控制图案的大小。
基本思路:首先使用一个for循环输出菱形的上半部分,然后再使用一个for循环输出菱形的下半部分。
1. n = int(input(’输入一个整数:')) 2. for i in range(n): 3. print(('* '*i).center(n*3)) #center()是字符串排版方法,居中对齐 4. #其中的参数n*3表示排版后字符串长度 5. for i in range(n, 0, -1): 6. print(('* '*i).center(n*3))
图4-3和图4-4分别为参数n等于6和9的运行效果。
图4-3 n=6的运行效果
图4-4 n=9的运行效果
例4-11 快速判断一个数是否为素数。
基本思路:除了2之外的所有偶数都不是素数;大于5的素数对6的余数必然是1或5,但对6的余数是1或5的不一定是素数;如果一个大于2的整数n不能被2或3到n的平方根之间的奇数整除,那么它是素数。
1. n = input("Input an integer:") 2. n = int(n) 3. #2是素数 4. if n == 2: 5. print('Yes') 6. #除了2之外的所有偶数必然不是素数 7. elif n%2 == 0: 8. print('No') 9. else: 10. #大于5的素数必然出现在6的倍数两侧 11. #因为6x+2、6x+3、6x+4肯定不是素数,假设x为大于1的自然数 12. m = n % 6 13. if m! =1 and m! =5: 14. print('No') 15. else: 16. #判断整数n是否能被3到n的平方根之间的奇数整除 17. for i in range(3, int(n**0.5)+1, 2): 18. if n%i == 0: 19. print('No') 20. break 21. else: 22. print('Yes')
例4-12 编写程序,计算组合数C(n,i),即从n个元素中任选i个,有多少种选法。
基本思路:以Cni(8,3)为例。
对于(5,8]区间的数,分子上出现一次而分母上没出现;(3,5]区间的数在分子、分母上各出现一次;[1,3]区间的数分子上出现一次而分母上出现两次。根据这一规律,可以编写如下非常高效的组合数计算程序。
1. def Cni(n, i): 2. if not (isinstance(n, int) and isinstance(i, int) and n >=i): 3. print('n and i must be integers and n must be >=i.') 4. return 5. result = 1 6. #使用i和n-i把1到n之间的自然数分成3个区间 7. #使用Min表示i和n-i中较小的数,Max表示其中较大的数 8. Min, Max = sorted((i, n-i)) 9. for i in range(n,0, -1): 10. if i >Max: 11. result *= i 12. elif i<=Min: 13. result /= i 14. return result 15. 16. print(Cni(6,2))
例4-13编写程序,输入一个自然数n,然后计算并输出前n个自然数的阶乘之和1!+2!+3!+…+n!的值。
基本思路:在前一项(n-1)!的基础上再乘以n就可以得到下一项。
1. n = int(input(’请输入一个自然数:')) 2. #使用result保存最终结果,t表示每一项 3. result, t = 1, 1 4. for i in range(2, n+1): 5. #在前一项的基础上得到当前项 6. t *= i 7. #把当前项加到最终结果上 8. result += t 9. print(result)
例4-14 编写代码,模拟决赛现场最终成绩的计算过程。至少有3个评委,打分规则为删除最高分和最低分之后计算剩余分数的平均分。
基本思路:首先使用一个循环要求用户输入评委人数(应大于2,至少有3个评委),然后再使用一个循环输入每个评委的打分,在两个循环中都使用了异常处理结构来保证用户输入的是整数,最后删除最高分和最低分,并计算剩余分数的平均分。
1. while True: 2. try: 3. n = int(input(’请输入评委人数:')) 4. if n <= 2: 5. print(’评委人数太少,必须多于2个人。') 6. else: 7. break 8. except: 9. #pass是空语句,表示什么也不做 10. pass 11. 12. scores = [] 13. 14. for i in range(n): 15. #这个while循环用来保证用户必须输入0到100之间的数字 16. while True: 17. try: 18. score = input(’请输入第{0}个评委的分数:'.format(i+1)) 19. #把字符串转换为实数 20. score = float(score) 21. assert 0<=score<=100 22. scores.append(score) 23. #如果数据合法,跳出while循环,继续输入下一个评委的分数 24. break 25. except: 26. print(’分数错误’) 27. 28. #计算并删除最高分与最低分 29. highest = max(scores) 30. lowest = min(scores) 31. scores.remove(highest) 32. scores.remove(lowest) 33. finalScore = round(sum(scores)/len(scores),2) 34. 35. formatter = ’去掉一个最高分{0}\n去掉一个最低分{1}\n最后得分{2}' 36. print(formatter.format(highest, lowest, finalScore))
例4-15 编写程序,实现人机对战的尼姆游戏。
问题描述:尼姆游戏是这样一个游戏:假设有一堆物品,计算机和人类玩家轮流从其中拿走一部分。在每一步中,人或计算机可以自由选择拿走多少物品,但是必须至少拿走一个并且最多只能拿走一半物品,然后轮到下一个玩家。拿走最后一个物品的玩家输掉游戏。
基本思路:在每次循环中让人类玩家先拿走一定数量的物品,然后再让计算机取走一些物品,要求拿走的物品数量不超过剩余数量的一半。如果物品全部取完则结束游戏,并且判定拿走最后一个物品的玩家为输。
1. from random import randint 2. 3. n = int(input(’请输入一个正整数:')) 4. while n > 1: 5. #人类玩家先走 6. print("该你拿了,现在剩余物品数量为:{0}".format(n)) 7. #确保人类玩家输入合法整数值 8. while True: 9. try: 10. num = int(input(’输入你要拿走的物品数量:')) 11. #确保拿走的物品数量不超过一半 12. assert 1 <= num <= n//2 13. break 14. except: 15. print(’最少必须拿走1个,最多可以拿走{0}个。'.format(n//2)) 16. n -= num 17. if n == 1: 18. print(’恭喜,你赢了!') 19. break 20. #计算机玩家随机拿走一些,randint()用来生成指定范围内的一个随机数 21. n -= randint(1, n//2) 22. else: 23. print(’哈哈,你输了。')