十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

freeCodeCamp 每日编码挑战解析:Challenge 179 Pocket Change 零钱统计与美元格式化

freeCodeCamp 每日编码挑战解析:Challenge 179 Pocket Change 零钱统计与美元格式化 freeCodeCamp 每日编码挑战解析Challenge 179 Pocket Change 零钱统计与美元格式化【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCampfreeCodeCamp 的每日编码挑战Daily Coding Challenge系列中Challenge 179 Pocket Change 是一道练习数组归约、整数除法与字符串格式化基本功的 JavaScript 题目给定口袋中若干硬币的面值数组单位为美分返回格式化后的美元金额字符串。本文以 挑战原文 为骨架结合该仓库中挑战的题目结构、API 路由与 Prisma 数据模型实现完整讲解题面、测试用例、解题思路与官方解答并延伸说明这类挑战在 freeCodeCamp 中的运行机制。题目要求把美分数组换算成$D.CC字符串Challenge 179 的题面非常简洁Given an array of integers representing the coins in your pocket, with each integer being the value of a coin in cents, return the total amount in the format$D.CC.即函数countChange(change)接收一个整数数组每个元素代表口袋里一枚硬币的面值单位美分需要返回总金额格式为$D.CC。题面附带两条明确约束100 美分 1 美元需要以 100 为基数完成美元与美分之间的换算。输出格式严格要求金额不足 1 美元时美元部分要包含前导零如$0.41美分部分必须始终是恰好两位数字如$0.05而不是$0.5。这两个约束正是本道题的考察重点Math.floor取整拆分、取模运算求余数以及padStart补齐位数。全部测试用例6 组输入与期望输出原文档在--hints--区块中给出了 6 组测试断言覆盖了不同规模的数组、跨美元边界、整数美元等典型场景输入数组期望返回值用例覆盖点[25, 10, 5, 1]$0.41不足 1 美元时美元部分带前导零[25, 10, 5, 1, 25, 10, 25, 1, 1, 10, 5, 25]$1.43跨过 1 美元边界总美分 100[100, 25, 100, 1000, 5, 500, 2000, 25]$37.55大面值1000、2000 美分混入[10, 5, 1, 10, 1, 25, 1, 1, 5, 1, 10]$0.70再次验证前导零与个位美分[1]$0.01单枚最小硬币美分补零[25, 25, 25, 25]$1.00恰好整美元美分为00最后一组[25, 25, 25, 25]是最容易被忽略的边界情况总和为 100 美分期望输出是$1.00而非$1直接验证了美分始终恰好两位的硬性要求。测试用例在挑战文件中以assert.equal(...)形式给出例如assert.equal(countChange([25, 10, 5, 1]), $0.41); assert.equal(countChange([25, 25, 25, 25]), $1.00);解题思路拆解三步走把问题拆成三个步骤即可得到清晰解法累加总美分用Array.prototype.reduce把数组所有硬币面值求和得到totalCents。拆分美元与美分Math.floor(totalCents / 100)得到完整美元数dollarstotalCents % 100得到剩余美分数cents。格式化输出美元部分直接拼入模板字符串美分部分用String.prototype.padStart(2, 0)保证至少两位不足两位时补前导零。其中第 3 步是本题的得分关键cents.toString().padStart(2, 0)同时处理了0.01个位美分补零与1.00整美元时美分为00两种情况。官方解答reduce Math.floor padStart 的经典组合原文档在--solutions--区块中给出了官方解答function countChange(change) { const totalCents change.reduce((sum, coin) sum coin, 0); const dollars Math.floor(totalCents / 100); const cents totalCents % 100; return $${dollars}.${cents.toString().padStart(2, 0)}; }逐行解读change.reduce((sum, coin) sum coin, 0)以0为初始值累加所有面值不依赖数组是否排序、是否包含大面值。Math.floor(totalCents / 100)Math.floor对正整数取整结果就是完整美元数。totalCents % 100取模得到不足 1 美元的零头美分。$${dollars}.${cents.toString().padStart(2, 0)}模板字符串拼出$D.CCpadStart(2, 0)保证美分恰好两位。官方解答没有使用toFixed(2)。原因在于toFixed处理的是小数而非整数美分拆分而这里先以整数运算完成换算再用字符串补齐位数从根本上避免了浮点精度问题——这也是金额计算始终用整数美分、避免浮点运算这一良好实践在入门题中的体现。拓展解法多种等价实现除官方解答外还有几种思路等价、可读性同样良好的实现方案一Math.trunc替代Math.floor正整数场景等价function countChange(change) { const totalCents change.reduce((sum, coin) sum coin, 0); const dollars Math.trunc(totalCents / 100); const cents totalCents % 100; return $${dollars}.${cents.toString().padStart(2, 0)}; }本题输入均为正整数Math.trunc与Math.floor结果一致若输入可能为负则二者有差异但本挑战不涉及。方案二toFixed(2)写法不建议function countChange(change) { const totalCents change.reduce((sum, coin) sum coin, 0); return $${(totalCents / 100).toFixed(2)}; }虽然对当前测试用例也能通过但依赖浮点除法与toFixed的四舍五入规则在真实金额计算场景下存在精度隐患不如纯整数运算稳妥。方案三手写补零逻辑function countChange(change) { const totalCents change.reduce((sum, coin) sum coin, 0); const dollars Math.floor(totalCents / 100); const cents totalCents % 100; const centsStr cents 10 ? 0${cents} : ${cents}; return $${dollars}.${centsStr}; }用条件判断替代padStart原理相同适合想刻意练习字符串拼接的读者。这道题在 freeCodeCamp 中的运行机制Challenge 179 属于每日编码挑战Daily Coding ChallengeJavaScript 系列。它的题目编号、难度等级与展示方式可以从仓库中的几处结构配置得到印证。挑战文件本身的结构挑战文件 69738771fb5a7b8b24cca2a5.md 的 frontmatter 定义了id: 69738771fb5a7b8b24cca2a5全局唯一的挑战 IDtitle: Challenge 179: Pocket Change系列内序号与标题challengeType: 2828 对应每日编码挑战这一特殊类型dashedName: challenge-179用于生成 URL 的短名称。正文则按--description--题面、--hints--断言、--seed--种子代码、--solutions--官方解答四个区块组织这一模板与 freeCodeCamp 所有挑战的标准格式一致。所在区块与课程编排该文件位于daily-coding-challenges-javascript区块目录下区块的编排信息记录在 daily-coding-challenges-javascript.json 中challengeOrder按id与title列出了从 Challenge 1 到 Challenge 200 的全部题目Challenge 179 Pocket Change 的id与 frontmatter 完全对应说明该题目已正式纳入课程顺序helpCategory: JavaScript题目归属于 JavaScript 帮助分类blockLayout: legacy-challenge-list区块采用经典挑战列表布局usesMultifileEditor: true支持多文件编辑器isUpcomingChange: true该区块当前标记为即将上线的变更表明它仍处于开发/预览阶段。服务端数据模型与 API每日编码挑战并非直接在浏览器端读取上面的 markdown而是将挑战数据题面、测试、代码模板同步进 MongoDB 数据库由 API 层按日期对外提供。相关证据集中在api/目录Prisma 数据模型api/prisma/schema.prismamodel DailyCodingChallenges { id String id default(auto()) map(_id) db.ObjectId challengeNumber Int date DateTime title String description String javascript DailyCodingChallengeApiLanguage python DailyCodingChallengeApiLanguage } type DailyCodingChallengeApiLanguage { tests DailyCodingChallengeApiLanguageTests[] challengeFiles DailyCodingChallengeApiLanguageChallengeFiles[] } type DailyCodingChallengeApiLanguageTests { text String testString String } type DailyCodingChallengeApiLanguageChallengeFiles { contents String fileKey String }该模型的关键设计在于一道挑战同时携带javascript与python两套语言的tests测试断言和challengeFiles代码模板而description中保存的正是如 Challenge 179 那样的题面文本。公开查询路由api/src/daily-coding-challenge/routes/daily-coding-challenge.ts提供 6 个只读 GET 端点端点说明GET /daily-coding-challenge/date/:date按YYYY-MM-DD获取某天挑战GET /daily-coding-challenge/day/:day按MM-DD不限定年份获取GET /daily-coding-challenge/today获取今日挑战按美国中部时间计算GET /daily-coding-challenge/month/:month按YYYY-MM列出某月挑战摘要GET /daily-coding-challenge/all列出全部挑战摘要GET /daily-coding-challenge/newest返回最新挑战的日期注意这些路由只用于获取挑战信息提交仍走主挑战完成路由见 api/src/daily-coding-challenge/README.md。所有接口都会拒绝返回晚于今日美国中部时间的挑战避免提前泄题。请求参数的模式校验定义在 api/src/daily-coding-challenge/schemas/daily-coding-challenge.ts例如date参数要求format: date、day参数要求匹配^\d{2}-\d{2}$。时区处理辅助函数api/src/daily-coding-challenge/utils/helpers.ts是每日机制的幕后功臣getNowUsCentral()通过date-fns-tz的getTimezoneOffset(America/Chicago, ...)计算当前美国中部时间getSourceDate()把任意日期映射回 2025-08-11 至 2026-08-10 这一年原始挑战周期内的对应日期并专门把 2 月 29 日映射到 2 月 28 日确保非闰年也能取到题。前端页面的呈现客户端侧每日挑战的入口由一个小组件渲染client/src/components/daily-coding-challenge/widget.tsx它根据美国中部时间生成今日挑战的链接getMonthDayUsCentral()并提供归档入口。挑战内部页顶部会显示日期面包屑client/src/templates/Challenges/components/daily-challenge-bread-crumb.tsx其中使用 client/src/components/daily-coding-challenge/helpers.ts 中的isValidDateOrMonthDayString/formatDisplayDate校验并格式化日期例如把02-14显示为 February 14。日期工具同样把02-29规整为02-28与后端逻辑保持一致。测试验证用 Node.js 本地跑通全部用例无需搭建完整环境仅凭官方解答即可在本地 Node.js 环境中验证 6 组断言function countChange(change) { const totalCents change.reduce((sum, coin) sum coin, 0); const dollars Math.floor(totalCents / 100); const cents totalCents % 100; return $${dollars}.${cents.toString().padStart(2, 0)}; } const tests [ [[25, 10, 5, 1], $0.41], [[25, 10, 5, 1, 25, 10, 25, 1, 1, 10, 5, 25], $1.43], [[100, 25, 100, 1000, 5, 500, 2000, 25], $37.55], [[10, 5, 1, 10, 1, 25, 1, 1, 5, 1, 10], $0.70], [[1], $0.01], [[25, 25, 25, 25], $1.00] ]; let passed 0; for (const [input, expected] of tests) { const actual countChange(input); const ok actual expected; if (ok) passed; console.log(${ok ? PASS : FAIL} countChange([${input}]) ${actual} (expected ${expected})); } console.log(\n${passed}/${tests.length} tests passed);运行后 6 组断言应全部 PASS。若某组失败可重点检查两处美元部分是否遗漏前导零如$0.41被写成$.41、美分部分是否保证两位如$1.4而非$1.43。小结Challenge 179 Pocket Change 用一道贴近生活的题目把三个高频 JS API 串成一条清晰解题链reduce做归约求和、Math.floor/%做整数拆分、padStart做格式化补零同时暗含金额用整数美分运算的工程建议。放到 freeCodeCamp 每日编码挑战的语境下它还展示了从 markdown 题面--description--/--hints--/--seed--/--solutions--到 Prisma 数据模型、再到按日期公开的 REST API 与前端日历时区的完整链路是理解该系列挑战如何生产、如何下发、如何判题的一个绝佳切片。【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表