O‘REILLY: Lightbulb Start Watching —— 从指定时间开始计算多组时间差之和(秒数)

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

思路及代码

思路

  1. 定义存储时间差的变量 result
  2. 判断 start_watching 变量是不是 None
  3. 如果 start_watching 变量是 None,则按照第一题直接计算时间差,并加到 result 里;
  4. 如果 start_watching 变量不是 None,则首先找到列表中奇数位(从0开始数)里比 start_watching 更大的,减去 start_watching 计算时间差,然后从奇数位 +2 的位置开始按照第一题直接计算后面每对的时间差,并加到 result 里;
  5. 返回 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)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值