news 2026/9/11 23:37:27

freeCodeCamp Daily Coding Challenge 315(Summer Solstice)题解:用 JavaScript 根据纬度计算昼夜时长

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
freeCodeCamp Daily Coding Challenge 315(Summer Solstice)题解:用 JavaScript 根据纬度计算昼夜时长

freeCodeCamp Daily Coding Challenge 315(Summer Solstice)题解:用 JavaScript 根据纬度计算昼夜时长

【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp

本篇技术指南围绕 freeCodeCamp 开源仓库中每日编码挑战(Daily Coding Challenge)第 315 题「Summer Solstice(夏至)」展开,完整还原题目要求、输出约定、全部测试断言与官方参考解法,并逐行拆解公式推导与边界处理。读完本文,你将掌握"基于纬度计算昼长、将小时数四舍五入到偶数、以 24 字符串对称排布昼夜符号"这类模拟/数学类题目的完整解题范式,同时了解该挑战在 freeCodeCamp 每日挑战体系(challengeType 28)中的真实运行机制。

一、挑战背景与题目定位

这道题位于curriculum/challenges/english/blocks/daily-coding-challenges-javascript/6a15cadf5f240d05a2649559.md,是 JavaScript 每日编码挑战块(block)中的第 315 道,标题为 "Challenge 315: Summer Solstice",其challengeType: 28表示这是一个每日编码挑战类型的题目。

题目的现实背景是:夏至是北半球一年中白昼最长的一天(南半球则是最短的一天)。本题要求写一个函数getDaytimeHours(latitude),给定一个纬度值,返回一个 24 字符的字符串,用符号直观地展示该纬度在夏至当天的昼夜分布。

二、题目要求与输出格式

原题(--description--部分)给出的完整规范如下:

  • 输入纬度取值范围为90(北极)到 -90(南极),闭区间

  • 白天小时数的计算公式为:

    白天小时数 = 12 + (latitude / 90) * 12
  • 将计算出的白天小时数四舍五入到最近的偶数

  • 返回一个 24 字符的字符串,其中"☀️"代表白天的小时,"🌑"代表夜晚的小时,且:

    • 每个字符代表一个小时,从午夜(第 0 小时)开始
    • 日出与日落围绕正午对称

原题给出的示例:纬度为0(赤道)时白昼为 12 小时,日出 6:00 AM、日落 6:00 PM,返回值应为:

"🌑🌑🌑🌑🌑🌑☀️☀️☀️☀️☀️☀️☀️☀️☀️☀️☀️☀️🌑🌑🌑🌑🌑🌑"

三、数学建模:从纬度到昼夜字符串

解题的第一步是把自然语言描述转成可计算的数学模型。

3.1 昼长公式

按题目公式,给定纬度latitude,理论昼长(小时)为:

daylight = 12 + (latitude / 90) * 12

验证两个极端:

  • latitude = 90(北极):daylight = 12 + 12 = 24,即极昼,全天 24 小时都是白天;
  • latitude = -90(南极):daylight = 12 - 12 = 0,即极夜,全天 24 小时都是夜晚。

3.2 四舍五入到最近偶数

题目要求将昼长取整到最近的偶数。例如-33度时:

daylight = 12 + (-33 / 90) * 12 = 12 - 4.4 = 7.6

7.6 到最近的偶数是 8(距离 7.6 更近的偶数是 8,因为 6 与 7.6 的差为 1.6,而 8 与 7.6 的差为 0.4)。因此得到 8 小时白昼。

官方参考解法中使用的小技巧是:先除以 2 再四舍五入,最后乘回 2:

const daylightHours = Math.round((12 + (latitude / 90) * 12) / 2) * 2;

Math.round(x / 2) * 2是"四舍五入到最近偶数"的标准实现:任何数除以 2 后四舍五入为整数,再乘 2,结果必为偶数,且是最接近原值的那个偶数。

3.3 日出/日落对称排布

由于日出与日落围绕正午(第 12 小时)对称,可得:

sunrise = 12 - daylightHours / 2 sunset = 12 + daylightHours / 2

以赤道(latitude = 0)为例:daylightHours = 12,则sunrise = 6sunset = 18,与题目示例完全一致。

四、官方参考解法逐行解析

原文档--solutions--部分给出的参考实现如下:

function getDaytimeHours(latitude) { const daylightHours = Math.round((12 + (latitude / 90) * 12) / 2) * 2; const sunrise = 12 - daylightHours / 2; const sunset = 12 + daylightHours / 2; let result = ""; for (let hour = 0; hour < 24; hour++) { result += hour >= sunrise && hour < sunset ? "☀️" : "🌑"; } return result; }

逐行拆解:

  1. 第 2 行:按公式计算昼长并四舍五入到最近偶数,得到daylightHours(必为 0~24 之间的偶数);
  2. 第 3~4 行:由对称性计算日出小时与日落小时;
  3. 第 6~9 行:遍历 0~23 共 24 个小时,凡是落在[sunrise, sunset)区间(含日出、不含日落)的记为白天"☀️",其余记为夜晚"🌑"
  4. 第 11 行:返回 24 字符的结果串。

注意边界语义:hour < sunset采用左闭右开区间,确保昼长恰好等于daylightHours个白天符号。当daylightHours = 24sunrise = 0sunset = 24,24 个小时全部为"☀️";当daylightHours = 0sunrise = sunset = 12,没有任何小时满足hour >= 12 && hour < 12,24 个小时全部为"🌑"

五、全部测试断言验证

原文档--hints--部分共给出 7 组断言,逐一演算验证如下:

纬度理论昼长取偶后昼长日出日落结果形态是否符合断言
012126186 夜 + 12 昼 + 6 夜
90242402424 昼(极昼)
-9000121224 夜(极夜)
-337.688168 夜 + 8 昼 + 8 夜
66.520.867202222 夜 + 20 昼 + 2 夜
4017.333183213 夜 + 18 昼 + 3 夜
-505.33369159 夜 + 6 昼 + 9 夜

其中getDaytimeHours(66.5)是一个很好的取整示例:理论昼长约 20.87 小时,除以 2 得约 10.43,Math.round(10.43) = 10,乘 2 得 20,验证了"四舍五入到最近偶数"的行为(20.87 更接近 20 而非 22)。

六、种子代码与开发入口

挑战的--seed--部分提供了初始脚手架,学习者需要在此基础上补齐逻辑:

function getDaytimeHours(latitude) { return latitude; }

初始代码直接返回纬度值,显然无法通过任何断言。正确的思路是严格遵循第三节的数学模型:计算昼长 → 取偶 → 求日出日落 → 按小时拼接符号。注意不要改动函数名getDaytimeHours与参数名latitude,因为测试断言(assert.equal)直接以该函数名为调用入口。

七、该挑战在 freeCodeCamp 每日挑战体系中的位置

7.1 block 结构配置

本题位于块配置文件 curriculum/structure/blocks/daily-coding-challenges-javascript.json 中,编号为 315(challengeOrder第 315 项,id 为6a15cadf5f240d05a2649559,紧随其后的第 316 题是 "1337 Speak")。整个 block 共 365 道题,对应一年中的每一天;块配置中usesMultifileEditor: truehelpCategory: "JavaScript",说明该系列以 JavaScript 为求解语言,并在多功能编辑器中作答。

7.2 前端如何消费 challengeType 28

在 client/src/client-only-routes/show-daily-coding-challenge.tsx 中可以看到,前端在组织每日挑战数据时显式使用challengeType: 28,对应类型定义 client/src/redux/prop-types.ts 中的challengeType: 28 | 29。也就是说,这类题目的渲染与提交走的是独立的每日编码挑战通道,而非普通的课程挑战。

7.3 每日挑战的种子机制

365 道挑战并非手工录入数据库,而是通过脚本批量生成的。在 tools/daily-challenges/seed-daily-challenges.ts 中:

  • 从 "Dev Playground" superblock 通过 GraphQL 拉取 JavaScript 与 Python 两套挑战;
  • 校验数量必须为EXPECTED_CHALLENGE_COUNT = 365,且 JS/Python 两套数量一致;
  • 2025-08-11为起始日期,每道挑战向后顺延一天(START_DATE + i * ONE_DAY_IN_MS)写入 MongoDB 的DailyCodingChallenges集合。

具体的运行流程记录在 tools/daily-challenges/README.md 中:复制sample.env.env、确保依赖已安装、以"显示 upcoming changes"模式启动主客户端以便脚本通过 GraphQL 获取挑战,然后在tools/daily-challenges目录下执行pnpm seed-daily-challenges完成入库。

7.4 后端 API 路由

挑战内容由 api/src/daily-coding-challenge/routes/daily-coding-challenge.ts 对外提供,包括:

  • GET /daily-coding-challenge/date/:date:按YYYY-MM-DD日期取当日挑战(不会返回晚于美国中部时间今天的挑战);
  • GET /daily-coding-challenge/day/:day:按MM-DD(如09-30)取挑战,闰日02-29会被特殊处理;
  • GET /daily-coding-challenge/todayGET /daily-coding-challenge/month/:monthGET /daily-coding-challenge/allGET /daily-coding-challenge/newest等。

日期边界逻辑(美国中部时区、UTC 午夜换算)实现在该目录的utils/helpers.ts中,前端日历组件则位于 client/src/components/daily-coding-challenge/calendar.tsx。

7.5 JS/Python 双语言一致性校验

仓库还提供了专门的测试 curriculum/src/test/daily-challenges.test.js,用于保证每日挑战的 JavaScript 与 Python 两个版本:数量相等、id 一一对应、标题与描述一致、测试断言数量一致。这道 Summer Solstice 题同样遵循该约定,说明此类题目在两种语言下共享同一套题目语义与判题断言。

八、总结与举一反三

Challenge 315 表面上是一道"天文计算"题,内核其实是三个通用技能的叠加:

  1. 公式化建模:把自然语言("夏至昼最长""围绕正午对称")翻译成确定的数学表达式;
  2. 取整技巧Math.round(x / 2) * 2是实现"四舍五入到最近偶数"的简洁写法,可迁移到任何需要偶数取整的场景;
  3. 区间遍历与符号拼接:用左闭右开区间[sunrise, sunset)精确控制 24 个字符中白天符号的个数,天然规避了"多一个少一个"的边界错误。

掌握这三点后,同类问题(如按月份绘制昼夜图、按时区计算日出日落表、甚至前文提到的 Challenge 133 "Daylight Hours" 与 Challenge 222 "Equinox Shadows" 等天文主题兄弟题)都可以套用相同的分析路径快速求解。

关键源码索引:

  • 挑战原文档:curriculum/challenges/english/blocks/daily-coding-challenges-javascript/6a15cadf5f240d05a2649559.md
  • block 配置:curriculum/structure/blocks/daily-coding-challenges-javascript.json
  • 每日挑战种子脚本:tools/daily-challenges/seed-daily-challenges.ts
  • 每日挑战 API 路由:api/src/daily-coding-challenge/routes/daily-coding-challenge.ts
  • 前端展示组件:client/src/client-only-routes/show-daily-coding-challenge.tsx
  • JS/Python 一致性测试:curriculum/src/test/daily-challenges.test.js

【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 23:36:06

安当DBG:保险理赔系统怎么给证件号、银行卡与病历字段上字段级加密——客服坐席按角色最小可见、外包公估脱敏留证的落地路径

引言&#xff1a;理赔系统里最该保护、也最容易被看光的字段 保险业务的核心是"理赔"&#xff0c;而理赔系统的核心数据&#xff0c;是三类高度敏感、又必须被反复查询的字段&#xff1a;被保人证件号、理赔收款银行卡号、以及出险病历与诊断结论。这三类字段有两个共…

作者头像 李华
网站建设 2026/9/11 23:35:27

Restormer自定义训练测试全流程:轻量Transformer图像复原实战

简介&#xff1a;本资源是一套面向深度学习初学者与图像恢复研究者的Restormer模型自定义训练与测试代码实现&#xff0c;聚焦Transformer架构在图像去雨、去模糊等低级视觉任务中的实践应用。代码复现完整&#xff0c;含训练、验证、推理全流程&#xff0c;注释详尽&#xff0…

作者头像 李华
网站建设 2026/9/11 23:32:37

火灾目标检测数据集与YOLO训练工程实践指南

简介&#xff1a;本资源是一套面向计算机视觉初学者与算法工程师的火灾安全检测专用数据集&#xff0c;聚焦烟雾与明火两类关键目标的识别任务&#xff0c;适用于YOLO、Faster R-CNN等主流目标检测模型的训练与验证。压缩包共含2000个文件&#xff0c;主体为3007张高质量JPG图像…

作者头像 李华
网站建设 2026/9/11 23:32:00

基于YOLOv3与贝叶斯分类的手语识别技术详解

简介&#xff1a;一套基于图像的手语识别系统完整项目&#xff0c;聚焦人体动作识别方向&#xff0c;面向计算机专业毕业设计、课程设计及期末大作业场景。项目包含25个Python源文件&#xff0c;以及UI界面文件、YOLO模型配置、训练好的pkl模型和文档说明&#xff0c;覆盖数据预…

作者头像 李华
网站建设 2026/9/11 23:31:45

仿鸟扑翼机器人动力学评估与Simulink仿真建模

简介&#xff1a;本资源是一套面向电子信息工程、计算机及数学专业本科生的仿生机器人课程设计与毕业设计实践材料&#xff0c;聚焦扑翼飞行器动力学建模与Simulink仿真验证。资源提供完整可运行的MATLAB/Simulink工程&#xff0c;涵盖系统初始化、能量评估与整机动力学仿真三大…

作者头像 李华