
freeCodeCamp 每日编程挑战实战解析Challenge 290 Pizza Party 的向上取整与聚合算法【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp本篇技术指南以 freeCodeCamp 仓库中的 Challenge 290: Pizza Party每日编程挑战系列之一为核心从题目规则、数学建模、逐行代码实现到测试用例验证完整剖析这道数组聚合类算法题。读者读完将掌握Math.ceil向上取整、Math.max下限约束、Array.reduce聚合等 JavaScript 核心技巧并了解该挑战在 freeCodeCamp 每日编程挑战体系challengeType 28中的真实运行机制。一、题目总览为披萨派对计算订购数量挑战文件位于 curriculum/challenges/english/blocks/daily-coding-challenges-javascript/69f8c998d78ad3171a0713bd.md归属于daily-coding-challenges-javascript挑战块。题目场景非常贴近生活给定一个数组表示今天每个人的工作时长小时请返回为披萨派对需要订购的披萨数量。要完成这道题必须严格遵循以下四条业务规则切片换算将每个人的工作时长除以 3得到其应得的披萨切片数禁止半片不能吃半片披萨因此每个人的切片数需向上取整到最近的整数最低保障每个人至少分到 2 片整披萨订购每份披萨含 8 片总切片数换算成披萨后需向上取整到最近的整数个披萨。这是一个典型的分步计算 → 逐项聚合 → 最终取整的数组处理问题考察的是对reduce、Math.ceil、Math.max的组合运用能力。二、从题目到数学模型在动手写代码之前先把文字规则翻译成数学表达式。设输入数组为hoursWorked每人工作时长的数组那么第 1 步单人的切片数slices_i max( ceil(hours_i / 3), 2 )ceil(hours_i / 3)实现除以 3 后向上取整对应规则 1 和规则 2max(..., 2)实现每人至少 2 片的下限约束对应规则 3。第 2 步总切片数totalSlices sum(slices_i) // 对每个人累加第 3 步最终披萨数pizzas ceil(totalSlices / 8)每片披萨 8 片、向上取整对应规则 4。值得注意的是Math.max(Math.ceil(hours / 3), 2)这一表达式把取整和下限两个逻辑合并成了一步先算出按工时换算的切片数并取整再与 2 比较取较大值。这样即使某人的工时小于 6 小时ceil(hours/3) 2也能保证其至少获得 2 片。三、种子代码与解决方案逐行拆解3.1 初始种子代码挑战为学习者提供了如下函数骨架位于原文档的# --seed--部分function getPizzasToOrder(hoursWorked) { return hoursWorked; }学习者需要把return hoursWorked替换为真正的计算逻辑使函数接收每人工作时长数组、返回订购披萨数。3.2 官方解决方案function getPizzasToOrder(hoursWorked) { const totalSlices hoursWorked.reduce((sum, hours) { return sum Math.max(Math.ceil(hours / 3), 2); }, 0); return Math.ceil(totalSlices / 8); }逐行解读代码片段作用hoursWorked.reduce((sum, hours) ..., 0)遍历数组以0为初始值累加每个人的切片数Math.ceil(hours / 3)每小时 3 片换算并向上取整规则 1、2Math.max(..., 2)与 2 比较保证每人最少 2 片规则 3Math.ceil(totalSlices / 8)每披萨 8 片总切片换算后向上取整规则 4整个方案只用一次reduce就完成了所有人的切片数聚合再通过一次Math.ceil收尾时间复杂度和空间复杂度均为O(n)仅需遍历一次数组、无额外存储是这道题在性能上的最优解。四、测试用例验证理解边界与陷阱原文档的# --hints--部分给出了 5 个断言用例每个都用assert.equal校验函数输出。下面逐一演算帮助理解规则之间的交互用例 1getPizzasToOrder([8, 8, 8])→2每人 8 小时ceil(8/3) 3均大于 2故每人 3 片共 9 片ceil(9/8) 2。✅用例 2getPizzasToOrder([10, 9, 8, 2, 2, 6, 10])→310 小时 →ceil(10/3) 49 小时 →ceil(9/3) 38 小时 →ceil(8/3) 32 小时 →ceil(2/3) 1但max(1, 2) 22 小时 → 同上2 片6 小时 →ceil(6/3) 210 小时 → 4 片合计4332224 20片ceil(20/8) 3。✅ 这个用例同时覆盖了最低 2 片保障和整披萨取整两条规则。用例 3getPizzasToOrder([1, 2, 3, 4, 5])→21 小时 →max(ceil(1/3), 2) 22 小时 →max(1, 2) 23 小时 →max(1, 2) 24 小时 →max(ceil(4/3), 2) max(2, 2) 25 小时 →max(2, 2) 2合计 10 片ceil(10/8) 2。✅ 该用例集中考验工时不足 3 小时也要 2 片的边界逻辑。用例 4getPizzasToOrder([8, 8, 8, 8, 8, 8, 8, 8])→38 人各 3 片共 24 片ceil(24/8) 3。✅ 恰好整批 3 个披萨验证无余数时的取整行为。用例 5getPizzasToOrder([9, 9, 6])→19 小时 →ceil(9/3) 3两次6 小时 →ceil(6/3) 2合计 8 片ceil(8/8) 1。✅ 恰好 1 个披萨再次验证整除场景。用例 6getPizzasToOrder([10, 12, 16, 9, 8, 11, 15, 8, 0])→510 → 4、12 → 4、16 →ceil(16/3)6、9 → 3、8 → 3、11 →ceil(11/3)4、15 → 5、8 → 3、0 →max(0, 2) 2合计446334532 34片ceil(34/8) 5。✅ 该用例包含 0 工时考验最低切片保障和较大数值的聚合。从这 6 组用例可以看出测试设计覆盖了一般换算、下限约束、整除与不整除、0 工时等典型边界情况。五、挑战在 freeCodeCamp 体系中的定位5.1 挑战块与元数据本挑战的 frontmatter 声明了challengeType: 28与dashedName: challenge-290并在 curriculum/structure/blocks/daily-coding-challenges-javascript.json 中注册为Challenge 290: Pizza Partyid 为69f8c998d78ad3171a0713bd前后分别是 Challenge 289 Sum of Differences 与 Challenge 291 FizzBuzz Count。从该块配置可看出其工程特征isUpcomingChange: true属于进行中的课程变更usesMultifileEditor: true在挑战编辑界面使用多文件编辑器helpCategory: JavaScript归入 JavaScript 帮助分类blockLayout: legacy-challenge-list采用传统挑战列表布局。5.2 每日挑战的 API 支撑此类挑战的数据由 API 侧的 daily-coding-challenge 模块对外提供。路由实现位于 api/src/daily-coding-challenge/routes/daily-coding-challenge.ts共注册了 6 个公开 GET 端点端点说明/daily-coding-challenge/date/:date按YYYY-MM-DD精确日期获取某天挑战/daily-coding-challenge/day/:day按MM-DD获取对应日期的挑战2 月 29 日映射到 2 月 28 日/daily-coding-challenge/today获取美国中部时区America/Chicago当天的挑战/daily-coding-challenge/month/:month按YYYY-MM获取整月挑战列表/daily-coding-challenge/all获取全部挑战列表仅返回已发布日期/daily-coding-challenge/newest获取最新一期挑战的日期请求/响应结构由 TypeBox schema 定义在 api/src/daily-coding-challenge/schemas/daily-coding-challenge.ts单个挑战响应包含id、date、challengeNumber、title、description以及javascript/python两套语言字段各含tests与challengeFiles。Pizza Party 这类题目的测试断言正是在此类结构中以testString形式交付给前端执行的。5.3 日期相关的实现细节源码中有几个值得注意的日期处理细节见 api/src/daily-coding-challenge/utils/helpers.ts 与路由文件今天以美国中部时间为准由getNowUsCentral()计算再经getUtcMidnight归一化为 UTC 零点用于数据库查询getSourceDate会把MM-DD映射回具体的 UTC 日期并处理闰年 2 月 29 日这类边界所有查询都会过滤date today US Central的挑战避免返回未发布的未来题目路由注释明确指出最后一个挑战日期为 2026 年 8 月 10 日之后将不再返回数据。六、举一反三从本题延伸的实战要点6.1 取整三件套的选择Math.ceil(x)向上取整适合必须准备足量的场景本题的披萨、物资采购、服务器容量规划Math.floor(x)向下取整适合最多能装多少的场景Math.round(x)四舍五入适合统计平均类场景。6.2 用Math.max施加下限约束Math.max(value, min)是给计算结果设置下限的惯用写法等价于value min ? min : value。同理Math.min(value, max)可以施加上限。本题的每人至少 2 片正是这种模式的典型应用。6.3reduce的聚合思维当需要把数组中的每一项折算成一个数值时reduce(callback, initialValue)是最直接的工具。本题把每人切片数在回调内即时计算并累加避免先map再sum的两趟遍历代码更紧凑。若希望可读性优先也可拆成两步function getPizzasToOrder(hoursWorked) { const slicesPerPerson hoursWorked.map(hours Math.max(Math.ceil(hours / 3), 2) ); const totalSlices slicesPerPerson.reduce((sum, s) sum s, 0); return Math.ceil(totalSlices / 8); }两种写法结果一致前者更高效后者更利于调试中间值。6.4 可能的陷阱忘记最低切片保障若直接sum Math.ceil(hours / 3)则[1, 2]这类用例会得到ceil(1/3)ceil(2/3) 2片、1 个披萨而正确答案要求每人 2 片即 4 片、1 个披萨——对于本例恰好一致但在更大的输入下会显著低估订购量先取整再求和 vs 先求和再取整必须每人分别向上取整后再累加而不是总工时除以 3 后一次性取整否则会系统性少算切片忽略 0 工时成员ceil(0/3) 0若不做max(..., 2)约束0 工时者将得不到任何切片。七、总结Challenge 290: Pizza Party 是一道短小精悍的数组聚合题通过工时 ÷ 3 向上取整、每人至少 2 片、每 8 片 1 个披萨向上取整三层规则串起了Math.ceil、Math.max、Array.prototype.reduce三个高频 API并用 6 组覆盖边界条件的断言固化了正确行为。学习者既可以把它当作日常算法练习也可以顺着本仓库的 challenge 文档、挑战块配置 与 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),仅供参考