FEATURED · 精选文章

freeCodeCamp 每日编码挑战解析:Challenge 190 冰球半决赛对阵(Winter Games Day 11: Ice Hockey)

发布时间 / 2026/9/10 1:30:59
来源 / 创域科博编辑部
栏目 / 资讯中心
freeCodeCamp 每日编码挑战解析:Challenge 190 冰球半决赛对阵(Winter Games Day 11: Ice Hockey) freeCodeCamp 每日编码挑战解析Challenge 190 冰球半决赛对阵Winter Games Day 11: Ice Hockey【免费下载链接】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-javascript 区块的第 190 道每日编码挑战为研究对象完整拆解其题目设定、积分规则、输入输出格式并给出官方参考解法与多种可复现的 JavaScript 实现。读完本文你将掌握「字符串结构化解析 → 加权计分 → 按指标排序 → 规则配对输出」这一经典编程解题链路并了解该挑战在 freeCodeCamp 每日编码挑战体系challengeType: 28中的定位与数据流转方式。一、题目背景为六支冰球队排出半决赛对阵Challenge 190 隶属于 freeCodeCamp 的每日编码挑战Daily Coding Challenges标题为Winter Games Day 11: Ice Hockey延续了连续多天以冬季运动会为主题的系列挑战。其完整题目描述位于 697a49e9860d24853adef67b.md。题目要求如下给定一个包含 6 支冰球国家队及其循环赛round robin后战绩记录的数组确定半决赛的对阵组合。你需要为每支球队计算总积分然后返回如下格式的字符串The semi-final games will be (1st) vs (4th) and (2nd) vs (3rd).即积分第 1 名对阵第 4 名、第 2 名对阵第 3 名——这是体育赛事中常见的「1-4、2-3 交叉配对」赛制。二、输入数据格式与积分规则2.1 记录字符串格式数组中的每一项都是一个字符串格式为TEAM: W-OTW-OTL-L其中字段含义单场积分W常规时间内获胜场数wins in regulation3 分OTW加时赛获胜场数overtime wins2 分OTL加时赛落败场数overtime losses1 分L常规时间内落败场数losses0 分积分累加即可得到球队总积分。题目给出的示例FIN: 2-2-1-0 → 2×3 2×2 1×1 0×0 11 分这个加权计分模型模拟了冰球联赛中「鼓励常规时间取胜、加时赛惜败仍有安慰分」的真实积分制度是解题的关键业务规则。2.2 输出格式函数需要返回一条完整句式的字符串将排好名次的球队名称插入占位符The semi-final games will be FIN vs SWE and CAN vs USA.注意球队名称保持输入中的大写缩写原样输出句子其余部分包括标点与空格必须逐字符一致否则无法通过断言测试。三、测试用例与断言分析原文档在# --hints--部分提供了 4 组测试用例均通过assert.equal对getSemifinalMatchups的返回值做严格全等比较用例 1[CAN: 2-2-0-1, FIN: 2-2-1-0, GER: 1-0-1-3, SUI: 0-1-3-1, SWE: 1-1-2-1, USA: 2-1-0-2]→ 返回The semi-final games will be FIN vs SWE and CAN vs USA.用例 2[CAN: 2-1-1-1, CZE: 1-1-1-2, FIN: 1-2-1-1, NOR: 0-1-1-3, SLO: 1-0-1-3, USA: 5-0-0-0]→ 返回The semi-final games will be USA vs CZE and CAN vs FIN.用例 3[CAN: 3-2-0-0, CZE: 2-1-2-0, LAT: 0-0-1-4, ITA: 1-1-1-2, DEN: 1-0-0-4, USA: 3-1-1-0]→ 返回The semi-final games will be CAN vs ITA and USA vs CZE.用例 4[AUT: 2-2-1-0, DEN: 1-0-0-4, ITA: 1-1-1-2, JPN: 3-2-0-0, KOR: 2-1-2-0, LAT: 0-0-1-4]→ 返回The semi-final games will be JPN vs ITA and AUT vs KOR.以用例 1 验证计分逻辑FIN 得2×32×21×111分居首SWE 得1×31×22×17分CAN 得2×32×210分USA 得2×31×28分最终排名 FIN CAN USA SWE配对结果为 FIN vs SWE 与 CAN vs USA与断言一致。四、解题思路四步法这类题目的解法可以稳定地拆解为四个步骤解析Parse以: 为分隔符切分球队名与战绩字段再以-为分隔符切分四个战绩数字计分Score按W×3 OTW×2 OTL×1 L×0计算每队总积分排序Rank按积分降序对球队排序题目输入保证 6 支球队积分无并列无需处理平局 tie-break配对Pair取排序后的第 1、4 名与第 2、3 名按模板字符串拼装结果。五、官方参考解法逐行解读原文档# --solutions--中给出的官方解法如下function getSemifinalMatchups(teams) { const teamPoints teams.map(teamStr { const [name, record] teamStr.split(: ); const [W, OTW, OTL, L] record.split(-).map(Number); const points W * 3 OTW * 2 OTL * 1 L * 0; return { name, points }; }); teamPoints.sort((a, b) b.points - a.points); const [first, second, third, fourth] teamPoints; return The semi-final games will be ${first.name} vs ${fourth.name} and ${second.name} vs ${third.name}.; }5.1 解析阶段const [name, record] teamStr.split(: );split(: )使用「冒号加空格」作为分隔符一次拿到球队名与战绩子串。紧接着const [W, OTW, OTL, L] record.split(-).map(Number);先用split(-)得到[2, 2, 1, 0]这样的字符串数组再通过map(Number)一次性把四个字段转换为数值类型。这里调用Number作为回调是值得注意的惯用法——它等价于map(str Number(str))比parseInt更简洁且足够应对纯数字字符串。5.2 计分与排序const points W * 3 OTW * 2 OTL * 1 L * 0;虽然L乘以 0 恒等于 0但保留这一项能完整映射题目中的业务规则增强代码可读性。teamPoints.sort((a, b) b.points - a.points);使用降序比较函数b.points - a.points排序后数组依次为积分从高到低的球队。注意sort是原地排序in-place会直接修改teamPoints数组。5.3 配对输出const [first, second, third, fourth] teamPoints;通过数组解构一次取出前四名。随后用模板字符串template literal拼装最终句式实现 1 vs 4、2 vs 3 的交叉配对return The semi-final games will be ${first.name} vs ${fourth.name} and ${second.name} vs ${third.name}.;模板字符串中的${...}插值让句子拼接清晰、不易出现手动字符串拼接常见的漏空格、漏句号问题。六、替代实现更函数式的写法除官方解法外你也可以用更函数式的方式组织代码将「解析 计分」收敛进一个工具函数再以管道式调用完成function getSemifinalMatchups(teams) { const score (teamStr) { const [name, record] teamStr.split(: ); const [W, OTW, OTL, L] record.split(-).map(Number); return { name, points: W * 3 OTW * 2 OTL * 1 }; }; const ranked teams.map(score).sort((a, b) b.points - a.points); const [first, second, third, fourth] ranked; return The semi-final games will be ${first.name} vs ${fourth.name} and ${second.name} vs ${third.name}.; }也可以使用reduce在单次遍历中同时完成切分与累加当输入是[{team, W, OTW, OTL, L}]这样的对象数组时更自然function getSemifinalMatchups(teams) { const ranked teams .map(teamStr { const [name, rest] teamStr.split(: ); const [W, OTW, OTL] rest.split(-).map(Number); return { name, points: W * 3 OTW * 2 OTL * 1 }; }) .sort((a, b) b.points - a.points); const [first, second, third, fourth] ranked; return The semi-final games will be ${first.name} vs ${fourth.name} and ${second.name} vs ${third.name}.; }无论哪种写法核心链路都是「split解析 → 加权计分 → 降序排序 → 模板字符串输出」。七、在 freeCodeCamp 每日编码挑战体系中的定位7.1 区块结构与 challengeType这道题位于curriculum/challenges/english/blocks/daily-coding-challenges-javascript/目录是拥有 365 道题的 JavaScript 每日挑战区块中的第 190 道。区块元数据定义在 daily-coding-challenges-javascript.json其中challengeType在题目 frontmatter 中标记为28该文档第 4 行对应客户端中「每日编码挑战」这一特殊题型challengeOrder按顺序列出全部挑战Challenge 190 的 id 为697a49e9860d24853adef67b前后分别是 Challenge 189Alpine Skiing与 Challenge 191Bobsled可见冬季运动会系列挑战是连续排布的。7.2 前端数据模型与校验客户端通过client/src/utils/daily-coding-challenge-validator.ts用 Joi 定义并校验从数据库读取的每日挑战结构每个挑战包含id、challengeNumber、title、date、description以及javascript与python两种语言的teststexttestString对和challengeFilesfileKeycontents。Challenge 190 的--hints--中那些assert.equal(...)片段正是会被存储为tests[].testString并在浏览器中执行的测试代码。7.3 API 数据获取端点后端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获取整月挑战列表仅返回 id、编号、日期、标题GET /daily-coding-challenge/all— 获取全部已发布挑战GET /daily-coding-challenge/newest— 获取最新挑战的日期。这些端点只负责返回挑战信息挑战的提交仍走主挑战完成路由。需要说明的是上述端点与challengeType: 28的数据管道共同构成了每日挑战的「后端取题 → 前端作答 → 断言测试」完整闭环而本文核心的getSemifinalMatchups函数即是在该管道中供学习者实现、被testString断言的代码。7.4 数据种子脚本tools/daily-challenges/seed-daily-challenges.ts负责把开发沙箱dev playground区块中的挑战按天写入 MongoDB 的DailyCodingChallenges集合挑战总数校验为 365 天起始日期固定为2025-08-11T00:00:00.000Z之后的每一天依序对应一道挑战脚本注释明确警告发布后不得更改起始日期。因此这道编号 190 的冰球题在发布日历中对应 2025-08-11 起算的第 190 天。八、易错点与调试建议分隔符细节解析记录时split(: )的分隔符是「冒号 空格」与输入格式TEAM: W-OTW-OTL-L严格对应写成split(:)会把战绩子串开头多带一个空格导致Number解析出错或名称提取异常数值类型转换忘记map(Number)会得到字符串数组2 * 3虽能隐式转换但2 2会变成字符串拼接22因此显式map(Number)是更稳妥的做法排序方向sort((a, b) b.points - a.points)是降序若误写成a.points - b.points升序第 1、4 名将完全颠倒4 组断言全部失败输出句式返回值必须是完整句子且大小写、空格、标点与原文档# --description--中给出的模板完全一致这是assert.equal严格比较最容易踩坑的地方测试先行在本地 Node 环境中先把 4 组断言跑通直接执行assert.equal(getSemifinalMatchups([...]), ...)再提交到挑战界面可显著提升调试效率。九、总结Challenge 190 是一道「业务规则建模 字符串解析 排序」的经典入门级算法题用 6 条TEAM: W-OTW-OTL-L记录模拟冰球循环赛积分再按积分排出 1-4、2-3 的半决赛对阵。官方解法仅用一次map、一次sort与一个模板字符串就完成了全部逻辑充分展示了split、解构赋值、Number回调与比较函数排序这些 JavaScript 基础 API 的组合用法。如果你想动手验证可基于 697a49e9860d24853adef67b.md 中的种子代码与 4 组断言在本地运行函数并对比输出结果。【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻