Python趣味算法入门 - 打鱼还是晒网

问题描述

中国有句俗语叫“三天打鱼两天晒网”。某人从1990年1月1日起便开始“三天打鱼两天晒网”,问这个人在以后的某一天中是“打鱼”还是“晒网”。

分析

“三天打鱼两天晒网”总共是五天,也就是说五天一个循环,在循环里,头三天这个人在打鱼,后两天这个人在晒网,于是我们只要知道从1990年1月1日起到需要询问的某一天为止过去了多少天,用天数对5取余数,得到的结果分别去对应:0-打鱼、1-打鱼、2-打鱼、3-晒网、4-晒网,就能知道这个人在那一天是“打鱼”还是“晒网”。

于是相应的,题目就转化成从询问某一天距离1990年1月1日过去了多少天。

对于时间的处理,Python自带的模块比如datetime就可以快速完成,所以就本题而言,如果用Python,除去输入输出的代码,也就是一句话的事。

import datetime
act = ["打鱼","打鱼","打鱼","晒网","晒网"]
start = datetime.datetime(1990,1,1)
year,month,day = map(int,input().split())
days = (datetime.datetime(year,month,day) - start).days # 计算过去了多少天
print(f"他在{act[days%5]}")

顺便提一句,dateime是内置模块,模块中有个datetime的类,用于表示某一天(可以精确到秒),还有个timedelta的类,表示两个datetime的距离(时间差)。而这个timedelta有两个属性:days和seconds。使用days就可以直接得出两个日期之间距离多少天,不满24小时的时间会保存在seconds属性里,也就是说seconds并不是指两个日期之间总共距离多少秒,而是减去所有整天后剩下多少秒。

回到题目,显然这一题问的是怎样计算两个日期之间的距离,虽然问哥不提倡重复造轮子,但是如果时间允许,倒是可以拿来做做练习。

让我们来思考一下,计算两个公历日期之间有多少天是什么步骤,

  1. 首先要知道两个日期之间差了多少年;
  2. 其次要看距离不够一年的时间里有哪几个月;
  3. 最后再查看不够一个月的时间里还差多少天。

由于本题的起始日期是一年的头一天,所以第2和第3点等于白给,在不考虑查询的日期是否有误的情况下(比如输入2022年13月32日),难度只在于注意闰年平年、大小月的天数不同。

对于闰年,我们已知判读条件有两个:1、能被400整除;2、能被4整除但不能被100整除,所以可定义一个函数用来判断某一年是否是闰年。然后遍历从1990年开始到输入的年份,如果是闰年就加366天,平年就加365天。

计算完年份差,再继续计算差了哪几个月。因为起始日期是1月,所以输入的月份之前都是要累加天数的范围。比如输入的月份是5,则要加上1、2、3、4,四个月的天数。循环最大到11,因为如果输入的月份是12,我们也无法把它看作整月,而如果输入的月份是1,我们只要加上整年的天数即可,所以12是不用检查的。

最后,我们只要加上不足一个月的天数即可,因为起始日期是1号,所以我们直接用输入的日期减去1,得到天数,然后累加在一起即可。

完整代码如下:

def isLeapYear(y):
    return True if y%4==0 and y%100!=0 or y%400==0 else False

months = [31,28,31,30,31,30,31,31,30,31,30,31]
act = ["打鱼","打鱼","打鱼","晒网","晒网"]

year,month,day = map(int,input().split())

days = 0
for y in range(1990, year):
    days += 366 if isLeapYear(y) else 365
for m in range(1, month): # 此处的month-1是减去起始月份,也就是距离1月有哪几个月
    if m in [1,3,5,7,8,10]: # 大月
        days += 31
    elif m in [4,6,9,11]: # 小月
        days += 30
    elif isLeapYear(year): # 闰年的二月
        days += 29
    else:
        days += 28
days += day-1 # 同理,此处day-1也是减去起始天,距离1号有几天

print(f"他在{act[days%5]}")

当然,本题还有很多写法,比如先给1到12月定义一个天数的列表或字典,然后在遍历的时候调取等等,思路大同小异,不再赘述。

输出

2022 10 1
他在打鱼
2011 10 2
他在晒网
2011 10 3
他在打鱼

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

请叫我问哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值