freeCodeCamp 每日编程挑战精讲:跳台滑雪 Ski Jumping 得分计算与奖牌排名判定
2026/9/10 5:22:16 网站建设 项目流程

freeCodeCamp 每日编程挑战精讲:跳台滑雪 Ski Jumping 得分计算与奖牌排名判定

【免费下载链接】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 Challenges)JavaScript 模块的第 183 道题「Winter Games Day 4: Ski Jumping」展开,完整讲解跳台滑雪比赛的总分计算规则、与其他选手的排名比较逻辑以及奖牌判定实现。读完本文,你将掌握「数组求和、合并排序、名次计算」这一经典算法套路,并了解该挑战在 freeCodeCamp 仓库中的完整实现链路(题目文件、校验规则与提交接口)。

挑战背景:Winter Games 系列与每日编程挑战模块

这道题位于curriculum/challenges/english/blocks/daily-coding-challenges-javascript目录下,是该模块中的Challenge 183,属于连续的「Winter Games」(冬季运动会)主题系列(Challenge 180–196)的第四天题目,从 Opening Day 国家旗帜 开始,经过 Snowboarding、Biathlon,到本日的 Ski Jumping,以及后续的 Cross-Country Skiing 等。

从块的元数据 daily-coding-challenges-javascript.json 可以看到,该块使用challengeType: 28(每日编程挑战类型),helpCategory为 JavaScript,并启用了usesMultifileEditor多文件编辑器。整个模块共有 365 个挑战文件(约 246+ 道编号题目,含 JavaScript 与 Python 双语言版本),覆盖数组、字符串、数学、日期、算法等大量基础编程场景,是一套非常适合刷题练习的题单。

题目要求与输入参数解析

原题描述(697a49e6ff50d756c9b69360.md)如下:

Given distance points, style points, a wind compensation value, and K-point bonus value, calculate your score for the ski jump and determine if you won a medal or not. Your score is calculated by summing the above four values.

你需要实现函数skiJumpMedal(distancePoints, stylePoints, windComp, kPointBonus),它接收四个参数:

参数含义类型说明
distancePoints距离分number(浮点)依据跳跃距离获得的分数
stylePoints风格分number(浮点)裁判对空中与落地姿态的打分
windComp风补偿值number(浮点)可正可负,顺风为负(惩罚)、逆风为正(补偿)
kPointBonusK 点加分number(浮点)基于 K 点基准线的额外加分

总分规则myScore = distancePoints + stylePoints + windComp + kPointBonus,即四项直接相加,无任何加权或取整。

奖牌判定规则(与当前所有选手的已完成总分比较):

  • 若你的分数是全场最佳(第一名),返回"Gold"
  • 若是第二,返回"Silver"
  • 若是第三,返回"Bronze"
  • 否则返回"No Medal"

其他选手当前的已完成总分为:

165.5 172.0 158.0 180.0 169.5 175.0 162.0 170.0

共 8 位选手,最高分为 180.0。因此只有当你的总分排名进入前三(即严格高于至少 5 位选手、且只允许 0–2 位选手分数高于你)时才能获得奖牌。

测试用例详解:六组断言验证

题目在--hints--段提供了 6 组官方测试用例,直接使用 Node.js 内置的assert进行断言(assert.equal):

assert.equal(skiJumpMedal(125.0, 58.0, 0.0, 6.0), "Gold"); assert.equal(skiJumpMedal(119.0, 50.0, 1.0, 4.0), "Bronze"); assert.equal(skiJumpMedal(122.0, 52.0, -1.0, 4.0), "Silver"); assert.equal(skiJumpMedal(118.0, 50.5, -1.5, 4.0), "No Medal"); assert.equal(skiJumpMedal(124.0, 50.5, 2.0, 5.0), "Gold"); assert.equal(skiJumpMedal(119.0, 49.5, 0.0, 3.0), "No Medal");

逐一验算(其他选手最高分 180.0):

调用四项之和与 180.0 比较排名期望结果
skiJumpMedal(125.0, 58.0, 0.0, 6.0)189.0189 > 180第 1"Gold"
skiJumpMedal(119.0, 50.0, 1.0, 4.0)174.0仅 180.0 更高第 2(Silver)→ 但用例期望"Bronze"?见下方说明"Bronze"
skiJumpMedal(122.0, 52.0, -1.0, 4.0)177.0仅 180.0 更高第 2"Silver"
skiJumpMedal(118.0, 50.5, -1.5, 4.0)171.0高于 3 位选手第 5"No Medal"
skiJumpMedal(124.0, 50.5, 2.0, 5.0)181.5181.5 > 180第 1"Gold"
skiJumpMedal(119.0, 49.5, 0.0, 3.0)171.5高于 3 位选手第 5"No Medal"

其中第二个用例值得注意:119.0 + 50.0 + 1.0 + 4.0 = 174.0,高于其余 7 位选手(仅次于 180.0),本应排第 2 名并返回"Silver",但题目期望返回"Bronze"。这说明排名判定并非简单的“比 180.0 小就是第二”,而是基于完整排序后你的名次索引。结合官方解答实现来看,正确计算方式是:把 8 位选手的分数与你自己的分数合并为 9 个元素的数组,降序排序后通过indexOf找到你自己的位置,位置0对应第一名(Gold)、1对应第二名(Silver)、2对应第三名(Bronze)。该用例与本系列 Challenge 18「Second Best」等题目一脉相承,都在训练“在给定集合中定位自身排名”的数组处理能力。

从起始代码到实现:四步拆解

题目提供的起始代码(--seed--段)为:

function skiJumpMedal(distancePoints, stylePoints, windComp, kPointBonus) { return distancePoints; }

默认实现只返回distancePoints,显然无法通过任何测试。完整的解题思路分为四步:

  1. 计算你的总分:将四个入参直接相加,得到myScore
  2. 构造完整成绩集合:用展开运算符[...otherScores, myScore]把 8 位已知选手的分数和你的分数合并为一个 9 元素数组。注意这里不能直接修改otherScores数组,展开语法创建的是新数组。
  3. 降序排序:调用sort((a, b) => b - a)。必须传入比较函数,因为 JavaScript 默认的sort()按字符串字典序排序,180.0会排在189.0之后导致错误结果。
  4. 确定名次并映射奖牌allScores.indexOf(myScore)返回你的分数在排序后数组中的第一个匹配下标,加 1 即为名次;1"Gold"2"Silver"3"Bronze",其余 →"No Medal"

官方参考解法逐行解读

题目--solutions--段给出的参考实现:

function skiJumpMedal(distancePoints, stylePoints, windComp, kPointBonus) { const myScore = distancePoints + stylePoints + windComp + kPointBonus; const otherScores = [165.5, 172.0, 158.0, 180.0, 169.5, 175.0, 162.0, 170.0]; const allScores = [...otherScores, myScore]; allScores.sort((a, b) => b - a); const rank = allScores.indexOf(myScore) + 1; if (rank === 1) return "Gold"; if (rank === 2) return "Silver"; if (rank === 3) return "Bronze"; return "No Medal"; }

要点分析:

  • otherScores是题目内置常量:8 位选手的分数硬编码在函数体内,与题目描述给出的列表完全一致,顺序无关紧要(排序会重排)。
  • indexOf的语义:若多位选手分数并列,indexOf返回第一次出现的下标,排名按“并列取最前名次”处理;在本题目给定的数据中不存在与你同分的边界情况,因此简单可靠。
  • 返回值为字符串字面量:必须严格返回"Gold""Silver""Bronze""No Medal"四个精确字符串,大小写与空格都不能错,否则断言失败。
  • 浮点数安全:所有分值都有一位小数且数值较小,IEEE 754 双精度表示下求和与比较无精度问题,可以直接使用===语义的indexOf定位。

边界情况与易错点

  • 忘记传排序比较函数allScores.sort()会按字符串排序,189会排在180之前吗?字符串比较下"180"vs"189"实际仍可得到正确顺序,但遇到"9""10"这类情况就会出错。本题分数均为三位整数部分,字符串序恰好与数值序一致,但养成传入(a, b) => b - a的习惯仍是正确做法。
  • 误改原始数组:若直接otherScores.push(myScore)会改变题目隐含的常量数组,虽然本题无副作用要求,但展开语法更符合纯函数风格。
  • 名次从 1 开始:排序后下标是 0 基的,indexOf + 1才能映射到正确的奖牌规则。
  • 返回值必须精确"Bronze"不是"bronze""No Medal"不是"No medal",断言是严格相等比较。

延伸:这道题在 freeCodeCamp 中的完整技术链路

每日编程挑战在仓库中并不是孤立的题目文件,而是连接着前端校验、后端 API 与数据存储的完整功能模块,可以从这条链路更深入地理解题目的运行环境:

  • 题目文件:本题的 Markdown 源文件 697a49e6ff50d756c9b69360.md 采用 freeCodeCamp 挑战的标准 Frontmatter(idtitlechallengeType: 28dashedName)加--description----hints----seed----solutions--分段结构,由课程构建工具解析渲染。
  • 前端数据校验:daily-coding-challenge-validator.ts 使用 Joi 定义了从数据库返回的每日挑战结构(idchallengeNumbertitledatedescription,以及 JavaScript/Python 两种语言的testschallengeFiles),validateDailyCodingChallengeSchema用于在前端消费数据前做运行时校验。
  • 后端公开路由:daily-coding-challenge.ts 提供了 6 个只读接口:按日期/daily-coding-challenge/date/:date、按日/day/:day、今日/today、按月/month/:month、全部/all、最新日期/newest,均通过 Prisma 查询dailyCodingChallenges表,并且会拒绝返回晚于美国中部时间当天的挑战。
  • 提交与完成记录:挑战的完成提交走通用挑战完成路由,其请求/响应结构定义在 daily-coding-challenge-completed.ts,请求体包含 24 位 ObjectId 格式的id与语言(javascript/python二选一),响应会返回pointscompletedDailyCodingChallenges数组。

通过这条链路可以看出:你在页面上完成的skiJumpMedal代码会作为 JavaScript 语言条目被提交、校验并由题库打分,这正是一道面向真实学习场景设计的完整闭环题目。

练习建议

  • 在浏览器控制台或 Node.js REPL 中逐条运行 6 组测试断言,验证自己的实现。
  • 尝试不依赖sort,改用一次遍历统计“有多少位选手分数高于你”来判定名次,对比两种思路的时间复杂度与代码简洁度。
  • 修改otherScores构造更复杂的场景(如与你同分、10 位选手、带小数位差异),观察indexOf与并列排名的表现。
  • 继续挑战同系列题目,如 Challenge 182: Biathlon 罚圈距离计算(数组遍历与乘加累加)和 Challenge 184: Cross-Country Skiing 相对成绩转换(字符串时间解析与格式化),它们与本日的排序排名题共同构成了“Winter Games”一周的算法热身。

【免费下载链接】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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询