ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

freeCodeCamp 每日编程挑战 249 “String Math“:基于定界符奇偶性的字符串算术解析

freeCodeCamp 每日编程挑战 249 “String Math“:基于定界符奇偶性的字符串算术解析 freeCodeCamp 每日编程挑战 249 String Math基于定界符奇偶性的字符串算术解析【免费下载链接】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第 249 题 String Math 要求实现一个doMath函数从混杂数字与任意字符的字符串中提取数字并依据相邻数字之间非数字字符个数的奇偶性决定执行加法还是减法。本文以该挑战的原始题目文档为主体完整拆解五条断言测试、种子代码与官方参考解法并结合仓库中挑战类型的定义、课程块结构与题目生成模板说明这道题在 freeCodeCamp 课程体系中的定位与工程实现细节。挑战背景与题目定位该题的完整题目文件位于 curriculum/challenges/english/blocks/daily-coding-challenges-javascript/69bc6cb30c1d112a2e110a06.md其 YAML 前置元数据front matter声明了四个关键字段--- id: 69bc6cb30c1d112a2e110a06 title: Challenge 249: String Math challengeType: 28 dashedName: challenge-249 ---其中challengeType: 28是理解整道挑战的关键。在仓库的类型定义文件 packages/shared/src/config/challenge-types.ts 中可以看到28被显式定义为dailyChallengeJsJavaScript 每日挑战29则是dailyChallengePy。同一文件中的viewTypes映射将dailyChallengeJs标记为classic视图submitTypes映射将其提交方式标记为tests——也就是说这道题使用经典编辑器界面、通过断言测试assert判定提交结果这也是题目中所有测试都以assert.equal形式出现的原因。该题在课程结构文件 curriculum/structure/blocks/daily-coding-challenges-javascript.json 中以如下条目注册该文件同时声明了usesMultifileEditor: true与disableLoopProtectTests: true等块级配置{ id: 69bc6cb30c1d112a2e110a06, title: Challenge 249: String Math }从该结构文件可以看出JavaScript 每日挑战是一个持续增长的题目列表String Math 排在 Challenge 248: Sorted Array Swap 之后、Challenge 250: Hidden Key 之前是题库中的一道常规字符串处理题。题目规则完整描述题目文档的# --description--部分给出了如下规则原文为英文此处按原意完整翻译并组织给定一个包含数字和其他字符的字符串需要根据数字之间非数字字符的个数对数字执行数学运算如果分隔两个数字的字符个数为偶数使用加法如果为奇数使用减法连续的数位构成单个数字如10是十而不是 1 和 0运算按从左到右的顺序执行不考虑运算优先级忽略开头和结尾的非数字字符。题目给出的示例给定3ab10c8返回5。因为3和10之间有 2 个字符ab偶数先做加法得13随后结果与8之间有 1 个字符c奇数做减法13 - 8 5。这里有一个容易忽略的语义细节操作数序列是当前累积结果 下一个数字而不是前一个数字 后一个数字。即每取到一个新数字都与当前累计值result运算这正是从左到右顺序执行左结合、无优先级的体现。测试用例五条断言的完整继承题目文档# --hints--部分给出了五条assert.equal断言这是判题的全部依据完整保留如下doMath(3ab10c8)应返回5。assert.equal(doMath(3ab10c8), 5);doMath(6MINUS4)应返回2。assert.equal(doMath(6MINUS4), 2);doMath(9plus3)应返回12。assert.equal(doMath(9plus3), 12);doMath(5fkwo#10i#%.15P20!#B/25)应返回15。assert.equal(doMath(5fkwo#10i#%.15P20!#B/25), 15);doMath(a.67,1$lk6ldf34#LD]2d32d22l3,l3L#2gh35s09ifdf#$t9sm49t0df3$^%[vc;:0:4mt)应返回67。assert.equal(doMath(a.67,1$lk6ldf34#LD]2d32d22l3,l3L#2gh35s09ifdf#$t9sm49t0df3$^%[vc;:0:4mt), 67);这五条用例覆盖了题目的各个边界用例关键点3ab10c8→5基础用例偶数定界加法 奇数定界减法6MINUS4→2定界符是 6 个字母MINUS偶数→6 4 10再按规则继续最终得2注意这里MINUS虽语义上是减按规则却触发了与奇偶相关的运算序列9plus3→12plus为 4 个字符偶数→9 3 125fkwo#10i#%.15P20!#B/25→15多数字、含符号字符的复杂混合串长乱码串 →67首尾非数字字符必须被忽略:0:这类0数字也要参与运算种子代码需要实现的函数签名题目文档# --seed--部分提供了编辑器中的初始代码函数必须命名为doMath且只接受一个字符串参数function doMath(str) { return str; }种子实现只是原样返回字符串解题者需要用真实逻辑替换函数体。官方解法逐行拆解题目文档# --solutions--部分给出了参考实现完整保留如下function doMath(str) { const tokens str.match(/(\d)|(\D)/g); let result null; let pendingOp null; for (const token of tokens) { if (/^\d$/.test(token)) { if (result null) { result parseInt(token); } else { result pendingOp add ? result parseInt(token) : result - parseInt(token); } } else { pendingOp token.length % 2 0 ? add : subtract; } } return result; }第一步正则分词tokenizationconst tokens str.match(/(\d)|(\D)/g);/(\d)|(\D)/g使用g标志的match把字符串切分为交替的 token 数组(\d)匹配一个或多个连续数字合并为一个整体满足连续数位构成单个数字的规则(\D)匹配一个或多个连续非数字。两个备选分支互斥且覆盖全部字符因此对整个字符串的切分是完整且无遗漏的。以3ab10c8为例切分结果为[3, ab, 10, c, 8]。注意数字 token 一定是纯数字串、非数字 token 一定是纯非数字串两类 token 严格交替出现首个 token 可能是数字也可能是非数字取决于字符串开头。第二步双状态扫描解法只维护两个状态变量result当前累计数值。初始为null用null而非某个数字哨兵值是为了区分尚未遇到第一个数字与已经累计出 0这两种情况pendingOp下一个数字到来时应当执行的运算取值add或subtract。它由上一个非数字 token 的长度奇偶性决定pendingOp token.length % 2 0 ? add : subtract;这正是题目核心规则的落地偶数个分隔字符 → 加法奇数个 → 减法。第三步数字 token 的左结合累积当 token 是数字时若result null这是字符串中第一个被保留的数字直接result parseInt(token)注意这天然实现了忽略前导非数字字符——出现在第一个数字之前的非数字 token 只会设置pendingOp而由于result仍为null该待处理运算永远不会被执行否则按pendingOp与当前累计值做加减法并立即更新result。这一步实现了从左到右顺序执行每个数字只与到目前为止的累计结果运算不存在优先级问题。同理字符串结尾的非数字 token 只会被读到并设置pendingOp之后循环结束对结果没有任何影响等价于忽略尾部字符。手动验证3ab10c8→5token类型动作resultpendingOp3数字首个数字初始化3nullab非数字长度 2偶数设置运算3add10数字3 1013addc非数字长度 1奇数设置运算13subtract8数字13 − 85subtract最终返回5与第一条断言一致。可以再用9plus3验证token 为[9, plus, 3]plus长度 4偶数→ add9 3 12通过。工程实现这道题在仓库中如何被生成与分发从仓库的源码结构看这道题并非手写散落文件而是由一套课程工具链统一生成题目模板。tools/challenge-helper-scripts/helpers/get-challenge-template.ts 中的getDailyJavascriptChallengeTemplate函数生成 JavaScript 每日挑战的占位模板其中硬编码了challengeType: 28与dashedName: challenge-${challengeNumber}并预留# --description--、# --hints--、# --seed--、# --solutions--四个区块——与本文件69bc6cb30c1d112a2e110a06.md的区块结构完全一致说明本文件正是由该模板实例化后填充题目内容的产物。批量创建脚本。tools/challenge-helper-scripts/create-daily-challenges.ts 以challengeOrder数组长度推定新题编号同时向 curriculum/structure/blocks/daily-coding-challenges-javascript.json 追加{ id, title }条目并写出对应的.md文件它还会校验 JavaScript 与 Python 两个每日挑战块题目数量一致不一致即抛错保证双语题库同步增长。服务端分发。api/src/daily-coding-challenge/README.md 说明 API 中设有专门获取每日挑战信息的端点提交判定仍走主 API 的通用测试提交流程这与submitTypes中dailyChallengeJs: tests的定义相呼应。因此若要查看这道题的完整生命周期可以按以下路径溯源结构注册curriculum/structure/blocks/→ 题目内容curriculum/challenges/english/blocks/→ 类型语义packages/shared/src/config/→ 生成工具tools/challenge-helper-scripts/→ 线上分发api/src/daily-coding-challenge/。小结Challenge 249: String Math 是一道典型的状态机式字符串处理题考察的三个能力点恰好对应官方解法的三段结构用正则/(\d)|(\D)/g完成数字合并、其余合并的交替分词用 token 长度的奇偶判定把定界字符数映射为加/减运算用单个result累积变量实现严格的左结合求值并借助result null的初始态自然地忽略前导与尾部非数字字符。五条断言覆盖了基础加减、多数字、符号字符与前导/尾部噪声等场景配合 curriculum/challenges/english/blocks/daily-coding-challenges-javascript/69bc6cb30c1d112a2e110a06.md 中的种子函数签名即可作为一套自洽、可离线验证的算法练习。【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表