时分秒重合问题

时分秒重合问题

今天晚上和同事吃饭时聊起了以前初中接触过的话题:24 小时内时针、分针和秒针重合几次。

吃完饭之后回来捋了下思路:

  • 假设时针的角速度为 ω(ω = 1 / 120 (度/秒)),那么分针的角速度就为 12ω,秒针的角速度为 720ω
  • 假设时针和分针在 t 秒后重合,那么分针在 t 时间内走过的角度减去时针在 t 时间内走过的角度,得到的结果肯定是 360 的整数倍
  • 根据上面的规则,可以算出时针和分针重合的时间 -- 集合 A
  • 同理也能算出分针和秒针重合的时间 -- 集合 B
  • 那么时针、分针及秒针三者重合的时间就是集合 A、B 的交集

具体实现代码如下:

/**
 * 时间补 0 
 * 
 * @param time 
 */
const padTime = (time: number) => {
    return time < 10 ? `0${time}` : `${time}`;
};

/**
 * 将秒转换为 HH:mm:ss 格式
 * 
 * @param seconds 
 */
const convert = (seconds: number) => {
    const hour: number = Number.parseInt(`${seconds / (60 * 60)}`),
        minute: number = Number.parseInt(`${(seconds - hour * 60 * 60 ) / 60}`),
        second: number = Math.round(seconds - hour * 60 * 60 - minute * 60);

    return `${padTime(hour)}:${padTime(minute)}:${padTime(second)}`;
}  

/**
 * 计算重叠时间
 * 
 * @param speedA 
 * @param speedB 
 */
const overlap = (speedA: number, speedB: number) => {
    const seconds: number = 24 * 60 * 60,
        speed1Circles: number = seconds * speedA / 360; // A 速度一天走的圈数

    let times: string[] = [];

    for (let i = 0; i < speed1Circles - 1; i++) {
        /**
         * speedA 在 t 时间内走过的角度 - speedB 在 t 时间内走过的角度 = 360 的整数倍
         * 
         * speedA * t - speedB * t = k * 360
         * t = (k * 360) / (speedA - speedB)
         * 
         */
         
         const time = (i * 360) / Math.abs(speedA - speedB); // 重合的时间

         if (time < (3600 * 24)) {
             times.push(convert(time));
         }
    }

    return times;
}
复制代码
// 时分秒角速度(度/秒)
const hSpeed: number = 1 / 120,
    mSpeed: number = 0.1,
    sSpeed: number = 6;
    
const timesA: string[] = overlap(mSpeed, hSpeed), // 时针和分针重合时间
    timesB: string[] = overlap(sSpeed, mSpeed), // 分针和秒针重合时间
    result: string[] = timesA.filter(num => timesB.includes(num)); // 二者取交集

console.log(timesA.length); // 22
console.log(timesB.length); // 1416
console.log(result); // [ '00:00:00', '12:00:00' ]
复制代码

根据运算结果可知,时针、分针、秒针三者在 24 小时内重合了 2 次,重合时间分别是在 0 点以及 12 点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值