[导读]:超平老师的Scratch蓝桥杯真题解读系列在推出之后,受到了广大老师和家长的好评,非常感谢各位的认可和厚爱。作为回馈,超平老师计划推出《Python蓝桥杯真题解析100讲》,这是解读系列的第25讲。
闰年问题,本题是2020年5月31日举办的第11届蓝桥杯青少组Python编程选拔赛真题,题目要求编程计算输入日期和2020年5月30日相差多少天,并输出是星期几,在计算时需要考虑闰年情况。
先来看看题目的要求吧。
提示信息:
闰年分为普通闰年和世纪闰年。
音通闰年:公历年份是4的倍数的,且不是100的倍数,为普通闰年。(如2004年就是闰年)。
世纪闰年:公历年份是整百数的,必须是400的倍数才是世纪闰年(如1900年不是世纪闰年,2000年是世纪闰年)。
总结:四年一闰,百年不闰,四百年再闰。
闰年的一年为366天,闰年的二月份为29天。平年一年为365天,平年的二月为28天。
每年的1、3、5、7、8、10、12月份为31天,4、6、9、11月份为30天。
编程实现:
用户输入未来的某一天,输入格式:“2020.6.1”,计算和2020年5月30日相差多少天,是星期几?(例如:今天和明天是相差一天)。
样例输入:
2020.6.1
样例输出:
2
星期 1
评分标准:
5分:能正确输出一组相差的天数及星期几;
10分:能正确输出两组相差的天数及星期几;
15分:能正确输出三组及以上相差的天数及星期几。
这是一道复杂的计算题,考查的知识点主要包括循环、双分支条件、列表操作和闰年算法等。
根据题目的描述,我们可以将需求拆分成如下3个部分:
判断闰年
计算日期差
计算星期几
下面,超平老师就逐一对这3个部分进行详细分析。
1.判断闰年
闰年的判断,简单来说,分为如下两种情况:
什么是普通闰年?就是指尾数不是00的年份,也就是不能被100整除的年份。在这个前提条件下,只要是能被4整除的年份都是闰年,其条件也就不难写出来了:
year?%?100?!= 0 and year % 4 == 0
对于世纪闰年来说,就更简单 ,只需要满足一个条件,即能被400整除,其条件如下:
year % 400 == 0
将上面两个条件综合起来,就可以得到判断闰年的完整条件,如下:
year % 100 != 0 and year % 4 == 0 or year % 400 == 0
注意,二者是逻辑或的关系。为了方便,我们可以使用自定义函数来实现闰年的判断逻辑。
2. 计算日期差
这是本题的难点,对于日期差的计算,要考虑的因素比较多,需要分情况讨论,如下:
我们可以举例来说明。
如果输入的是2020年的某一天,只需要统计整月的天数,再加上当前月份的天数。
当输入2020.8.20时,需要先将6月的30天和7月的31天进行累加,再加上8月份的20天,同时不要忘了5月31日这一天。
如果不是2020年,处理情况就稍微复杂一些了。
当输入2021.4.3时,则需要先计算2020.5.31到2020.12.31的天数,然后计算2021.1.1到2021.4.3所有的天数,在这个过程中,需要考虑特殊的闰二月。
当输入2022.6.7时,则需要先计算2020.5.31到2020.12.31的天数,然后计算2021年全年的天数,再统计2022.1.1到2022.6.7所有的天数,此过程也需要考虑特殊的闰二月。
为了更好地理解这个过程,可以绘制流程图如下:
由于每个月的天数是固定的,我们可以使用列表将月份保存起来,如下:
[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
注意,这是平年的月份,对于闰年,2月份需要增加一天。
3.?计算星期几
对于星期几的判断,最快捷的方法莫过于使用datetime模块中的weekday()方法。它通常与datetime模块中的date对象一起使用,用于获取指定日期是星期几。
from datetime import date
#?创建一个date对象表示指定日期
d?=?date(2023,?10,?20)??#?2023年10月20日
#?使用weekday()方法获取该日期是星期几,
# 返回值为0(星期一)到6(星期日)
weekday_number?=?d.weekday()
需要注意的是,使用weekday()方法得到的结果是数字0~6,分别表示从从星期一到星期日。
题目要求输出的是星期1、星期2...星期7,我们可以使用列表将它们保存起来,如下:
["星期1","星期2","星期3","星期4","星期5","星期6","星期7"]
然后通过下标直接就可以输出对应的星期几了。
思路有了,接下来,我们就进入具体的编程实现环节。
根据上面的思路分析,我们分3步来编写程序:
定义函数判断闰年;
计算天数;
计算星期几;
1. 定义函数判断闰年
根据前面的思路分析,定义函数如下:
输入一个年份,如果是闰年,则返回True,否则返回False。
2. 计算天数
首先是获取用户输入的年月日,然后根据不同情况来计算相差天数,代码如下:
代码比较多,强调4点:
1). 获取用户输入的年月日,使用了列表推导式和多变量赋值的编程技巧,前面已经多次介绍过,这里就不再赘述了;
2). 2020年5月31日这一天也需要计算的,所以将dis的初始值设置为1;
3). 在统计整年的天数时,其循环的范围是(2021,y),如果输入的是2021年,循环就不会执行,同时需要判断年份是否为闰年,闰年的天数为366;
4). 在统计整月的时候,需要考虑特殊的闰二月,如果是闰年并且是2月份在,则多加一天。
3. 计算星期几
这部分的代码比较简单,如下:
输入2020.6.1,效果如下:
输入2023.10.21,效果如下:
至此,整个程序就全部完成了,你也可以输入不同的日期来测试效果。
本题的分数为30分,代码在30行左右,涉及到的知识点包括:
循环语句,主要for...in循环;
条件语句,包括单分支和双分支;
循环和条件语句的相互嵌套;
函数的定义及使用;
列表运算;
日期对象的基本使用;
题目难度较大,代码量也比较多。难点有两个,一是要搞清楚计算相差天数的逻辑,二是使用date对象来获取星期几。
对于难点一,非常考验学生的逻辑思维能力和解决问题的能力,超平老师建议使用特例法,先列举几个具体的日期,看看是怎么计算的,然后画出流程图。
对于难点二,就看平时的积累了,日期时间对象是编程时常用的知识点,还是多运用,做到熟练掌握。
超平老师给你留一道思考题,如果不使用date对象,能否计算出星期几呢?
你还有什么好的想法和创意吗,也非常欢迎和超平老师分享探讨。
如果你觉得文章对你有帮助,别忘了点赞和转发,予人玫瑰,手有余香😄
需要源码的,可以移步至“超平的编程课”gzh。