马世胜 王德贵
公元纪年对称日问题,也称为世界完全对称日。比如2021年12月2日,写成20211202,大家一眼就看出,这个数字是左右对称的,那么从公元纪年开始,到现在一共有多少个对称日呢?
今天我们就用Python来探讨一下公元纪年的对称问题。
我们习惯的日期格式是XXXX年X月X日,当然也可以用“.”代表年月。不过这种写法日期的位数不一致,可以用零来补位,这样年用4位数字,月和日用两位数字,加一起为8位数字。如:2021年12月2日,写成20211202。
在数学上,对称有两个含义:轴对称和中心对称。
轴对称,即是沿着某条直线,翻折180度后,完全重合,这条直线也叫对称轴,沿对称轴翻折后两侧重合的点,叫对称点。
中心对称,即是沿着某一点旋转180度,完全重合,这个点也叫对称中心,绕对称中心旋转180度重合的点,叫对称点。
日期数字是左右对称的,我们叫对称日,在数学上也叫回文数、回文日期,所以对称日属于轴对称。
公元纪年从1开始,前面无需加0,所以开始纪年应该是10101,年上正常按位计算,月和日都按两位算,这样就能开始计算从10101开始,到现在共有多少个对称日了。
程序设计思想是先建立各月份的日期数,并放在列表中,以备使用。
年、月、日三重循环,最外层是年,然后是月,最里层是日。
年循环,先判断某年是不是闰年,如果是闰年,则2月份为29天,否则为28天。再就是输入的年份,需要按照输入的月份和日期终止循环,如果不是输入的年份,则正常按月份的日期循环。
月循环,需要先知道是不是输入的年月,如果是则循环到月即可,否则正常按日期列表循环。如果是小于10的,则前面加0补位。
日循环,要判断是不是输入的日期,如果是输入的日期,则按日期终止循环,否则按日期列表循环。如果是小于10的,则前面加0补位。
当输入的日期,与循环日期相同时,不再继续循环,即循环到输入的当天。
将年月日转换为字符串,添加到列表中,然后将列表反序,再判断反序的列表和原列表是否相等,如果相等则添加到对称日列表中,以备查询和统计。
输出对称日列表的长度,也就是我们要求的值。也可以输出列表中的数据,即对称日,也可以做日期切片来显示多个数据。
自定义函数,来判断闰年。
年份循环中,判断是否为闰年,如为闰年则返回1,否则返回0,如果为1则2月份的天数为29,否则为28天。
年月日循环,以检查每天的日期是否为对称日。
輸出对称日长度,即为从纪年开始,到输入的日期中,有多少个对称日,然后输出最后一个对称日期,如果想输出全部日期,则修改程序即可。
在调试程序时,发现用列表反序,非常方便判断,可以不用管多少位数字,只是循环的时间复杂度会增大。比如2021年12月2日,是第513个对称日,显示最后10个对称日,如下图。
公元9999年12月31日前的对称日数目是796个,最后一个对称日是9290年9月29日。
20000年12月31日前的对称日数目是1226个,最后一个对称日是13809年8月31日。
这两个日期好像有点久远。但我们探讨的过程中,体会了其中的乐趣,Python程序简捷明了,易于理解。21世纪共有11个对称日,刚刚过了20211202之后,下一个就是2030年3月2日。
大家若有兴趣,可以用C语言和图形化来编程,这里我就不再叙述了。