ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

freeCodeCamp Python 每日编程挑战实战:用模运算与 datetime 实现 Moon Phase 月相计算

freeCodeCamp Python 每日编程挑战实战:用模运算与 datetime 实现 Moon Phase 月相计算 freeCodeCamp Python 每日编程挑战实战用模运算与 datetime 实现 Moon Phase 月相计算【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp导读本篇以 freeCodeCamp 开源课程中daily-coding-challenges-python区块的第 60 道挑战「Space Week Day 6: Moon Phase」为骨架完整讲解如何基于一个 28 天简化月相周期与固定参考新月日期2000-01-06编写moon_phase函数。读完本文你将掌握 Pythondatetime解析日期、计算天数差、取模映射周期索引以及区间判定这一套通用解题范式并能理解该挑战在 freeCodeCamp 平台中作为challengeType: 29dailyChallengePy的运行与测试机制。挑战背景Space Week 系列中的 Python 每日一题这道挑战位于课程区块 daily-coding-challenges-python.json 之中。从该区块结构文件可以看到它被标记为isUpcomingChange: true使用多文件编辑器usesMultifileEditor: true帮助分类为 PythonhelpCategory: Python布局采用legacy-challenge-list。挑战编号为 Challenge 60标题为「Space Week Day 6: Moon Phase」是连续七天的「太空周」Space Week系列之一Challenge 5561覆盖恒星分类、系外行星搜索、着陆点、适居带、月相、发射燃料等天文主题其源文件位于 68c497f3aaefc9fd9f1b0e24.md。从平台类型系统看这道题对应challengeType: 29。在 packages/shared/src/config/challenge-types.ts 中dailyChallengeJs 28、dailyChallengePy 29并且getDailyCodingChallengeLanguage会将dailyChallengePy映射为python说明该挑战的作答语言与在线评测均为 Python。题目规则精读28 天简化月相模型题目要求给定一个格式为YYYY-MM-DD的日期字符串依据以下规则判定该日对应的月相使用简化后的 28 天太阴月周期等分为四个 7 天的阶段New新月周期第 17 天Waxing盈月周期第 814 天Full满月周期第 1521 天Waning亏月周期第 2228 天第 28 天之后周期从头开始重新进入第 1 天新月。以2000-01-06作为参考新月即周期第 1 天来推算任意给定日期所处的相位。保证不会出现早于参考日期的输入。函数需返回对应的相位字符串。特别说明第 1 天即新月当天表示距离上一个新月已经过去了 0 天。这里需要区分物理月相与题目简化模型的差异真实月球周期约 29.5 天且各相位不等长但本题刻意将其抽象为整除性良好的 28 天模型目的是聚焦「日期差 → 取模 → 区间映射」这一核心编程能力这也是 Space Week 系列在算法难度上的定位。关键算法拆解天数差、取模与区间判定整个解题核心分三步1. 解析日期字符串使用 Python 标准库datetime.datetime.strptime将YYYY-MM-DD解析为datetime对象格式串固定为%Y-%m-%dref_date datetime.strptime(2000-01-06, %Y-%m-%d) target_date datetime.strptime(date_string, %Y-%m-%d)strptime的格式指令必须与输入严格一致%Y为四位年份、%m为两位月份、%d为两位日期。如果输入格式与格式串不匹配会抛出ValueError。2. 计算与参考日期的天数差两个datetime对象直接相减得到timedelta取其.days属性即为整数天数差diff_days (target_date - ref_date).days题目保证输入日期不早于2000-01-06因此diff_days 0可以安全地直接取模。3. 取模映射到周期第几天再落入相位区间28 天周期意味着用% 28取模后得到0 ~ 27的余数。由于题目把第 1 天视为新月当天0 天已过需要把余数加 1 映射回「第 128 天」的语义cycle_day (diff_days % 28) 1随后按区间做 if / elif / else 判定if cycle_day 7: return New elif cycle_day 14: return Waxing elif cycle_day 21: return Full else: return Waning值得强调的是1这一步若不做偏移diff_days % 28为 0 时恰好是新月当天会被误判为周期末尾加 1 后新月当天落在第 1 天与题目「Day 1 represents the day of the new moon, meaning 0 days have passed since the last new moon」的定义完全吻合。官方参考答案逐行解析原文档# --solutions--段给出了完整参考实现完整源码见挑战文件from datetime import datetime def moon_phase(date_string): ref_date datetime.strptime(2000-01-06, %Y-%m-%d) target_date datetime.strptime(date_string, %Y-%m-%d) diff_days (target_date - ref_date).days cycle_day (diff_days % 28) 1 if cycle_day 7: return New elif cycle_day 14: return Waxing elif cycle_day 21: return Full else: return Waning该实现具有如下值得借鉴的特点纯标准库只依赖datetime无需第三方库可直接在任意 Python 3 环境运行常数时间复杂度strptime与日期差计算均为 O(1)不受输入日期跨度影响即使输入跨越数十年边界安全diff_days % 28天然处理跨越多个月相周期的日期例如相隔 28、56、84 天……的日期会落回同一相位语义清晰cycle_day变量名直接对应「周期内第几天」区间边界与题目四阶段一一对应易于审阅与维护。人工验证推算以文档 hints 中的用例验证算法正确性输入日期与 2000-01-06 的天数差diff_days % 28cycle_day期望输出2000-01-12667New2000-01-13778Waxing2014-10-1553911516Full2012-10-2146712324Waning2022-12-14837312New可见cycle_day落在第 7 天时仍属New第 17 天第 8 天起进入Waxing区间边界为闭区间包含与题目规则一致。在线评测机制hints 如何驱动验证原文档的# --hints--段提供了 5 条自动化测试采用 freeCodeCamp 的 Python 挑战评测约定——在浏览器内通过 Pyodide 运行({test: () { runPython( from unittest import TestCase TestCase().assertEqual(moon_phase(2000-01-12), New)) }})每条 hint 都先导入unittest的TestCase再以assertEqual断言moon_phase对给定日期的返回值。这意味着评测环境会先执行学习者提交的moon_phase定义再依次执行这 5 个断言5 个用例覆盖了四种相位输出中的三种边界New出现两次并横跨 2000、2012、2014、2022 四个年份足以验证跨周期取模的正确性。从实现层面看该评测跑在浏览器端 Web Worker 中的 Pyodide 之上相关代码见 tools/client-plugins/browser-scripts/python-worker.tsrunPython是对pyodide.runPython(pyCode, { globals })的封装每次运行都会创建全新的全局字典并注册print、input等自定义模块保证用户代码的隔离执行index.d.ts 中声明了__runPython: (code: string) PromisePyodideInterface这一全局类型。因此本题的「Python 每日挑战」无需本地安装任何 Python 环境直接在课程页面即可作答与判题。种子代码与作答入口挑战的# --seed--段给出了种子函数学习者需在保留函数签名moon_phase(date_string)的前提下补齐实现def moon_phase(date_string): return date_string种子代码目前直接返回原输入字符串显然无法通过任何 hint作答者的任务即是用上文算法替换函数体。需要注意的是函数名必须保持为moon_phase参数名保持为date_string因为 hints 中的runPython代码直接以moon_phase(...)形式调用答案只需让 5 条TestCase().assertEqual全部通过即可种子代码中没有预先import datetime因此标准答案在函数外顶部自行引入from datetime import datetime作答时也应如此或在函数体内局部导入。扩展思考变体与进阶方向掌握了本题的核心范式后可以继续探索以下变体它们与本题同属daily-coding-challenges-python区块的 Space Week 系列适合作为配套练习反向推算Challenge 61: Launch Fuel从规则反向出发给定相位反推日期或计算燃料需求考验对周期模型的逆向理解多相位细分将 28 天周期改为 8 个 3.5 天相位或 29.5 天真实周期练习非整数周期与取整策略参考日期参数化把2000-01-06与周期长度28提取为常量或函数参数提高代码复用性输入校验为date_string增加格式校验如datetime.strptime失败时抛出带说明的异常增强健壮性。在 freeCodeCamp 生态中这类每日挑战还与 api/src/daily-coding-challenge/README.md 描述的后端「获取每日挑战信息」接口、client/src/components/daily-coding-challenge/widget.tsx 展示的首页每日挑战小组件以及 tools/daily-challenges/seed-daily-challenges.ts 的种子脚本共同构成完整的「每日编码挑战」功能链路。小结「Moon Phase」这道题是学习 Python 日期处理与模运算应用的典型范例通过datetime.strptime完成字符串解析、timedelta.days计算绝对天数差、% 28 1完成周期索引映射、if / elif 完成相位区间判定。它覆盖了日常编码中高频出现的「日历计算」问题模型而 freeCodeCamp 提供的浏览器内 Pyodide 评测环境则让你可以零本地配置地即时验证解法。建议在 挑战源文件 中对照 hints 逐条运行验证再尝试上述进阶变体巩固理解。【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表