此题为第十五届蓝桥杯模拟赛(第一期)Python赛道的第三题 填空题
问题描述
对于一个日期,我们可以计算出年份的各个数位上的数字之和,也可以分别计算月和日的各位数字之和。请问从 1900 年 1 月 1 日至 9999 年 12 月 31 日,总共有多少天,年份的数位数字之和等于月的数位数字之和加日的数位数字之和。
例如,2022年11月13日满足要求,因为 2+0+2+2=(1+1)+(1+3) 。
请提交满足条件的日期的总数量。
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
我的解题
分析
需要遍历年份 1900~9999 、月份及所对应的天数,这里就需要考虑一个平闰年的区分了,主要体现在 2 月上,其它都好说:
- 我们需要遍历 1900 年到 9999 年,以及所对应的月份及其所对应的天数。所以我们可以先判断输入的月份是否为大小月,大月输出 31 天,小月输出 30 天,但是 2 月可能会因为平闰年使得天数存在 28 天、29 天的情况。
- 第一个函数我们可以先写出传入年、月的,除了 2 月以外的月份我们就直接输出其天数(根据大小月),对于 2 月,我们需要根据输入的年份判断是否是平闰年输出 29、28 天。所以第二个函数我们写判断闰年的,输入为年份,是闰年输出 29 天、不是闰年输出 28 天。
- 完成以上两个主要函数后,最后就是对年份、月份、日的位数分别求和,所以写第三个函数用于传入数值,对此数值的各个位求和输出结果就行了。
- 在主干代码中就是遍历年份、月份、日了,然后判断年份数位之和是否与月日的数位之和相等,相等就引入一个变量去累计,最后遍历完成输出就行了。
编程
以下是本人实践的代码:
#判断平闰年并输出对应2月的天数
def leapYear(year):
if year%4==0 and year%100!=0 or year%400==0:
return 29
else:
return 28
#输出对应大小月所对应的天数
def monthDays(year,month):
if month in [1,3,5,7,8,10,12]:
return 31
elif month in [4,6,9,11]:
return 30
elif month==2:
return leapYear(year)
#数字的数位求和
def sumDigits(num):
sum=0
while num!=0:
sum += num % 10
num = num // 10
return sum
if __name__ == '__main__':
count = 0
for num_year in range(1900,10000): #遍历年
for num_month in range(1,13): #遍历月
for num_day in range(1,monthDays(num_year,num_month)+1): #遍历月份所对应的日
if sumDigits(num_year) == sumDigits(num_month) + sumDigits(num_day):
count += 1
print(count)
运行结果
结果是 70910
AI 解题
问了几个大模型(通义千问的 qwen-max、qwen-plus、qwen-turbo,智谱 AI 的 ChatGLM-Turbo,讯飞星火 V3.0),都存在问题,要么运行出错,要么一些小细节没有考虑进去,导致结果有所偏差,下面我给出来他们的代码并 AI 注释,但是有些地方还是值得学习的。
qwen-max
原始代码
from datetime import datetime, timedelta
def digit_sum(n):
return sum(int(digit) for digit in str(n))
count = 0
start_date = datetime(1900, 1, 1)
end_date = datetime(9999, 12, 31)
for year in range(start_date.year, end_date.year + 1):
for month in range(1, 13):
for day in range(1, (datetime(year, month, 1).replace(day=1) + timedelta(days=32)).day):
if digit_sum(year) == digit_sum(month) + digit_sum(day):
count += 1
print(count)
代码存在问题,OverflowError: date value out of range
不修复了,懒……
不过其取月份所对应的天数倒是有点意思,datetime()函数也不错,记下来了。
讯飞星火 V3.0
原始代码
def is_valid_date(year, month, day):
# 判断日期是否有效
if year < 1900 or year > 9999:
return False
if month < 1 or month > 12:
return False
if day < 1 or day > 31:
return False
return True
def sum_of_digits(n):
# 计算数字的各个位数的和
return sum(map(int, str(n)))
def count_valid_dates():
count = 0
for year in range(1900, 10000):
for month in range(1, 13):
for day in range(1, 32):
if is_valid_date(year, month, day):
if sum_of_digits(year) == sum_of_digits(month) + sum_of_digits(day):
count += 1
return count
result = count_valid_dates()
print(result)
代码中有一个地方存在问题,就是遍历的当前月份天数(第 19 行),它并没有将大小月、平闰年考虑进去,故运行后的得到的结果 71834 不准确;再者,其代码中对年月日的效验有些多余,没有实际效果,所以我对其修改后就可以得到正确的答案了:
修复后的代码
#判断平闰年并输出对应2月的天数
def leapYear(year):
if year%4==0 and year%100!=0 or year%400==0:
return 29
else:
return 28
#输出对应大小月所对应的天数
def monthDays(year,month):
if month in [1,3,5,7,8,10,12]:
return 31
elif month in [4,6,9,11]:
return 30
elif month==2:
return leapYear(year)
def sum_of_digits(n):
# 计算数字的各个位数的和
return sum(map(int, str(n)))
def count_valid_dates():
count = 0
for year in range(1900, 10000):
for month in range(1, 13):
for day in range(1, monthDays(year,month)+1):
if sum_of_digits(year) == sum_of_digits(month) + sum_of_digits(day):
count += 1
return count
result = count_valid_dates()
print(result)
运行结果是 70910。
评价:该大模型对各个数位求和非常的巧妙,用了高阶函数 map()和 sum()函数进行求和,牛!
qwen-plus
原始代码
def digit_sum(n):
"""
计算一个数的数字和
参数:
n:整数
返回值:
数字和
"""
return sum(int(digit) for digit in str(abs(n)))
count = 0
for year in range(1900, 10000):
for month in range(1, 13):
for day in range(1, (month == 2 and (year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) or year % 4 != 0) + 29) or 31):
"""
考虑闰年和平年的天数
"""
if digit_sum(year) == digit_sum(month) + digit_sum(day):
count += 1
print(count)
运行结果是 70388。
相比之下,结果漏了好多,现在对其分析分析:可以发现第 7 行代码貌似少了 30、28 这两个选项,就是小月的天数和平年的 2 月的天数。
不过其对数位求和方式也很独特,利用 sum()函数和推导式求和。
此处暂时不修复代码了,麻烦。
qwen-turbo
原始代码
def count_days():
"""
计算满足年份、月份和日期之和相等的天数
"""
total_days = 0
for year in range(1900, 10000):
if len(str(year)) == 4:
for month in range(1, 13):
if len(str(month)) == 1 or len(str(month)) == 2:
for day in range(1, 32):
if len(str(day)) == 1 or len(str(day)) == 2:
year_sum = sum(int(digit) for digit in str(year))
month_sum = sum(int(digit) for digit in str(month))
day_sum = sum(int(digit) for digit in str(day))
if year_sum == month_sum + day_sum:
total_days += 1
return total_days
print(count_days())
运行结果是 71834。
结果明显大了,查看代码,发现第 10 行的天数没有去考虑大小月,闰平年的二月天数,所以其结果是偏大的。
此处不修复代码了,其数位求和也是用的推导式和 sum()函数组合。
存档地址:https://www.yuque.com/worthstudy/study/mphfsxuhm900647s
暂无评论内容