CheckIO是一个通过闯关游戏学习编程的网站(Python和JavaScript)。通过解题开发新“岛屿”,同时,通过做任务获得Quest Points解锁会员题目。
文章内容:题目、我自己的思路和代码以及优秀代码,如果想看大神解题可以直接跳到“优秀代码”部分。
本题链接:https://py.checkio.org/en/mission/lightbulb-start-watching/
背景
这部分是关于灯泡的一系列任务,有助于了解流程以及对流程效果的评估。 在现实生活中,除了灯泡,也需要计算其他设备的效果,或者上班的工人以及他们的工资。
题目
这一任务是这个系列里的第二个任务。
你已经知道如何计算灯泡开着的时间(即房间亮的时间),我们再加一个参数——计时开始时间。
这意味着灯泡还像原来一样亮和灭。但是不同的是,这一任务中,我想知道从某个时间开始,房间亮着的时间。
这一任务增加了一个参数:开始计时时间,如果没有给定这个参数,则像第一个问题,计算灯泡亮的时间。
输入: 给定两个参数,第一个是必选参数,第二个是可选参数。第一个参数是时间格式组成的列表,第二个参数是时间。
输出: 秒数(整数)
举个栗子:
sum_light([
datetime(2015, 1, 12, 10, 0, 0),
datetime(2015, 1, 12, 10, 0, 10),
],
datetime(2015, 1, 12, 10, 0, 5)) == 5
sum_light([
datetime(2015, 1, 12, 10, 0, 0),
datetime(2015, 1, 12, 10, 0, 10),
], datetime(2015, 1, 12, 10, 0, 0)) == 10
sum_light([
datetime(2015, 1, 12, 10, 0, 0),
datetime(2015, 1, 12, 10, 10, 10),
datetime(2015, 1, 12, 11, 0, 0),
datetime(2015, 1, 12, 11, 10, 10),
], datetime(2015, 1, 12, 11, 0, 0)) == 610
假设:
- 列表中的时间已经按升序排序
- 列表中元素唯一(结果应该大于0)
- 列表中元素个数为偶数个(灯泡最后是关闭状态)
- 最小日期为:1970-01-01;最大日期为:9999-12-31
题目框架
from datetime import datetime
from typing import List, Optional
def sum_light(els: List[datetime], start_watching: Optional[datetime] = None) -> int:
"""
how long the light bulb has been turned on
"""
return 0
if __name__ == '__main__':
print("Example:")
print(sum_light([
datetime(2015, 1, 12, 10, 0, 0),
datetime(2015, 1, 12, 10, 0, 10),
],
datetime(2015, 1, 12, 10, 0, 5)))
assert sum_light(els=[
datetime(2015, 1, 12, 10, 0, 0),
datetime(2015, 1, 12, 10, 0, 10),
],
start_watching=datetime(2015, 1, 12, 10, 0, 5)) == 5
assert sum_light([
datetime(2015, 1, 12, 10, 0, 0),
datetime(2015, 1, 12, 10, 0, 10),
], datetime(2015, 1, 12, 10, 0, 0)) == 10
assert sum_light([
datetime(2015, 1, 12, 10, 0, 0),
datetime(2015, 1, 12, 10, 10, 10),
datetime(2015, 1, 12, 11, 0, 0),
datetime(2015, 1, 12, 11, 10, 10),
], datetime(2015, 1, 12, 11, 0, 0)) == 610
assert sum_light([
datetime(2015, 1, 12, 10, 0, 0),
datetime(2015, 1, 12, 10, 10, 10),
datetime(2015, 1, 12, 11, 0, 0),
datetime(2015, 1, 12, 11, 10, 10),
], datetime(2015, 1, 12, 11, 0, 10)) == 600
assert sum_light([
datetime(2015, 1, 12, 10, 0, 0),
datetime(2015, 1, 12, 10, 10, 10),
datetime(2015, 1, 12, 11, 0, 0),
datetime(2015, 1, 12, 11, 10, 10),
], datetime(2015, 1, 12, 10, 10, 0)) == 620
assert sum_light([
datetime(2015, 1, 12, 10, 0, 0),
datetime(2015, 1, 12, 10, 10, 10),
datetime(2015, 1, 12, 11, 0, 0),
datetime(2015, 1, 12, 11, 10, 10),
datetime(2015, 1, 12, 11, 10, 11),
datetime(2015, 1, 12, 12, 10, 11),
], datetime(2015, 1, 12, 12, 10, 11)) == 0
assert sum_light([
datetime(2015, 1, 12, 10, 0, 0),
datetime(2015, 1, 12, 10, 10, 10),
datetime(2015, 1, 12, 11, 0, 0),
datetime(2015, 1, 12, 11, 10, 10),
datetime(2015, 1, 12, 11, 10, 11),
datetime(2015, 1, 12, 12, 10, 11),
], datetime(2015, 1, 12, 12, 9, 11)) == 60
print("The second mission in series is done? Click 'Check' to earn cool rewards!")
难度: Simple
思路及代码
思路
- 定义存储时间差的变量
result
; - 判断
start_watching
变量是不是None
; - 如果
start_watching
变量是None
,则按照第一题直接计算时间差,并加到result
里; - 如果
start_watching
变量不是None
,则首先找到列表中奇数位(从0开始数)里比start_watching
更大的,减去start_watching
计算时间差,然后从奇数位+2
的位置开始按照第一题直接计算后面每对的时间差,并加到result
里; - 返回
result
。
代码
def sum_light(els: List[datetime], start_watching: Optional[datetime] = None) -> int:
result = 0
if start_watching == None:
for i in range(1, len(els), 2):
result += (els[i] - els[i-1]).total_seconds()
else:
for i in range(1, len(els), 2):
if start_watching < els[i]:
result += (els[i] - start_watching).total_seconds()
for j in range(i+2, len(els), 2):
result += (els[j] - els[j-1]).total_seconds()
break
else:
continue
return result
优秀代码
No.1
def sum_light(els: List[datetime], start_watching: Optional[datetime] = None) -> int:
"""how long the light bulb has been turned on"""
return sum(
(
max(start_watching or end, end) - max(start_watching or start, start)
).total_seconds()
for start, end in zip(els[::2], els[1::2])
)
No.2
def sum_light(els: List[datetime], start_watching: Optional[datetime] = None) -> int:
if not (sw:=start_watching): sw=els[0]
return sum(((d2-sw)*(d2>sw)-(d1-sw)*(d1>sw)).total_seconds()
for d1,d2 in zip(els[::2],els[1::2]))
No.3
def sum_light(els: List[datetime], start_watching: Optional[datetime] = datetime(1, 1, 1)) -> int:
els = sorted(els + [start_watching])
i = els.index(start_watching)
return sum([(els[j + 1] - els[j]).total_seconds() for j in range(i + (i % 2 == 0), len(els), 2)])
No.4
from datetime import datetime
def sum_light(els, start_watching = None):
bulb = False
seconds = 0
for x, y in enumerate(els):
bulb = not bulb
if bulb is False:
if start_watching and (y - start_watching).total_seconds() > 0:
seconds += (y - start_watching).total_seconds()
start_watching = None
elif start_watching is None:
seconds += (y - els[x - 1]).total_seconds()
return int(seconds)