
freeCodeCamp JavaScript 每日挑战 349Cell Signal——用三个信号塔坐标在手机网格上定位【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp本篇指南完整讲解 freeCodeCamp 课程中 JavaScript 每日编码挑战Daily Coding Challenges第 349 题 “Cell Signal”给定一个包含三个信号塔读数的网格如何判定手机所在单元格。你将完整继承原题的题面规则、全部 5 个测试用例与参考实现并进一步结合仓库中的区块配置文件、挑战类型定义与挑战页面源码理解这道题在 freeCodeCamp 课程体系中的实际运行形态最终掌握“约束交集 方向距离判定”这一类网格定位题的通用解法。题目背景网格中的手机定位该题目来自 freeCodeCamp 课程仓库的 JavaScript 每日挑战区块挑战文件为 6a22d77ddf034bc4e35b1d56.md。在区块结构文件 daily-coding-challenges-javascript.json 的challengeOrder中它被排定为 “Challenge 349: Cell Signal”相邻题依次为 Challenge 348: Loan Calculator 与 Challenge 350: Letter Distance。题面原文如下Given a grid containing three cell tower readings, determine the location of the phone.Each cell in the grid is either0(no tower) or a positive integer representing the number of cells to the phone, measured in a straight line: horizontal, vertical, or diagonal.Return the[row, col]of the cell that is the correct number of cells from all three towers.There is always exactly one solution.翻译成中文网格中每个单元格要么是0无信号塔要么是一个正整数表示该信号塔到手机的直线格数——这个直线只能是水平、垂直或 45° 对角线方向要求返回[row, col]行、列该单元格必须同时满足全部三个信号塔的距离约束题目保证有且只有一个解因此找到第一个满足条件的单元格即可返回。题目的输入输出契约是function findSignal(grid) { // grid: 二维整数数组 // 返回值: [row, col] 或 undefined题面保证一定有解 }初始脚手架seed代码如下读者需要在函数体内完成实现function findSignal(grid) { return grid; }核心数学什么叫“直线距离为 dist”这是本题唯一的难点也是最容易写错的地方。所谓“手机在信号塔的dist格之外”指的是二者位于同一条水平线、同一条垂直线或同一条对角线上且相隔恰好dist格。设候选手机位置为(r, c)信号塔位于(tr, tc)记行差dr |r - tr|、列差dc |c - tc|则合法位置等价于以下三种情形之一方向条件垂直方向同一列dc 0且dr dist水平方向同一行dr 0且dc dist对角线方向45°dr dc dist注意两点距离不是欧氏距离也不是曼哈顿距离而是轴对齐或对角线上的格数dist至少为 1正整数所以手机不可能恰好落在信号塔格子上——这也意味着所有非零格子都可以直接从候选集中排除。参考实现用一个布尔函数把上表压缩成一行判定等价地写成了(dr dist || dc dist) (dr 0 || dc 0 || dr dc)拆解来看前一半(dr dist || dc dist)要求至少一个轴方向的差恰好等于dist后一半(dr 0 || dc 0 || dr dc)要求另一个轴差为 0水平/垂直或者两轴差相等对角线。两者合起来恰好覆盖且仅覆盖上表的三种合法方向其余所有位置例如 L 形偏移都会被排除。完整测试用例原题 5 组断言原题提供了 5 组测试全部采用assert.deepEqual深比较比较的是[row, col]的精确数值与顺序。以下 5 组用例与原题文档逐字对应可直接复制到本地 Node 环境自测assert.deepEqual(findSignal([[0, 0, 1], [0, 1, 0], [0, 0, 1]]), [1, 2]);第一个用例中塔[1,2]的读数为1。答案[1, 2]距塔[0,2]值 1垂直 1 格距塔[1,1]值 1水平 1 格距塔[2,2]值 1垂直 1 格三个约束同时成立。assert.deepEqual(findSignal([[0, 2, 0], [1, 0, 0], [0, 0, 1]]), [2, 1]);答案[2,1]距塔[0,1]值 2垂直 2 格距塔[1,0]值 1对角线 1 格dr1, dc1距塔[2,2]值 1水平 1 格。这组用例特意验证了对角线方向的判定。assert.deepEqual(findSignal([[0, 0, 2, 0], [0, 0, 0, 0], [2, 0, 0, 0], [0, 0, 0, 1]]), [2, 2]);答案[2,2]距塔[0,2]值 2垂直 2 格距塔[2,0]值 2水平 2 格距塔[3,3]值 1对角线 1 格。assert.deepEqual(findSignal([[0, 3, 0, 0, 0], [0, 0, 0, 0, 2], [0, 0, 0, 0, 0], [4, 0, 0, 0, 0], [0, 0, 0, 0, 0]]), [3, 4]);答案[3,4]距塔[0,1]值 3对角线 3 格dr3, dc3距塔[1,4]值 2垂直 2 格距塔[3,0]值 4水平 4 格。assert.deepEqual(findSignal([[3, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 2, 0, 0, 0, 2]]), [3, 3]);答案[3,3]距塔[0,0]值 3对角线 3 格距塔[5,1]值 2对角线 2 格dr2, dc2距塔[5,5]值 2对角线 2 格dr2, dc2。这是 6×6 网格三塔两塔共用同一答案验证了多塔交叉约束收敛到唯一解的情形。参考实现逐段解析原题给出的参考解法原文档# --solutions--部分完整如下随后逐段分析function findSignal(grid) { const rows grid.length; const cols grid[0].length; const towers []; for (let r 0; r rows; r) { for (let c 0; c cols; c) { if (grid[r][c] ! 0) towers.push([r, c, grid[r][c]]); } } function isValid(r, c, tr, tc, dist) { const dr Math.abs(r - tr); const dc Math.abs(c - tc); return (dr dist || dc dist) (dr 0 || dc 0 || dr dc); } for (let r 0; r rows; r) { for (let c 0; c cols; c) { if (grid[r][c] ! 0) continue; if (towers.every(([tr, tc, dist]) isValid(r, c, tr, tc, dist))) { return [r, c]; } } } }第一步预提取信号塔。外层遍历一次网格把所有非零格子收进towers数组每个元素是[行, 列, 距离读数]三元组。题目保证恰好三个塔但代码并不写死为 3——towers.every(...)对任意数量的塔都成立实现上更具鲁棒性。第二步单塔判定函数isValid。如上节分析它只负责回答“候选点是否恰好位于该塔的水平/垂直/对角线dist格处”。把它抽成函数后主循环只需对每个候选点调用every做全量约束检查。第三步扫描候选点并早退。第二个双重循环遍历所有格子if (grid[r][c] ! 0) continue;跳过信号塔格子——因为读数是正整数手机不可能与塔同格这个跳过是正确性要求而非单纯的性能优化towers.every(...)要求候选点同时满足全部塔的约束约束交集一旦命中就立即return [r, c]。由于题面保证有且仅有一个解扫描到第一个合法点即全局解。复杂度设网格为rows × cols、塔数为t本题恒为 3时间复杂度为O(rows * cols * t)空间复杂度O(t)。对日常挑战的网格规模用例中最大 6×6而言完全不是问题。常见错误与陷阱结合判定条件(dr dist || dc dist) (dr 0 || dc 0 || dr dc)实现时最容易踩的坑有误用欧氏/曼哈顿距离用Math.sqrt(dr*dr dc*dc) dist或dr dc dist都无法区分“直线上的点”与“L 形偏移的点”。例如对 45° 方向、dist 2的塔(dr2, dc2)的欧氏距离是2√2 ≠ 2会漏掉对角线解。忘记dr 0 || dc 0分支如果只写dr dc dr dist就只能找出对角线方向的候选水平/垂直方向的合法解全部被丢弃。忘记跳过非零格若不continue信号塔自身所在格子dr 0, dc 0不会恰好满足任何正dist的约束虽然不会误判但属于无谓的无效检查更重要的是在“手机恰好与某塔同格”这类变体中逻辑会崩坏。返回值顺序断言使用assert.deepEqual比较[row, col]返回[c, r]会直接失败。every与some混淆题目要求“距所有塔都是正确格数”必须全部满足用some会导致任一单塔满足即返回产生假解。题目在 freeCodeCamp 课程体系中的位置理解这道题的运行环境有助于知道它如何被交付给学习者挑战类型定义。文件头元数据中challengeType: 28对应共享包 challenge-types.ts 中的dailyChallengeJs 28Python 版每日挑战为dailyChallengePy 29。同一文件定义了三类映射关系viewTypes中[dailyChallengeJs]: classic见 challenge-types.ts——每日挑战复用经典classic挑战视图渲染编辑器与测试面板submitTypes中[dailyChallengeJs]: tests见 challenge-types.ts——提交时运行的是“跑测试”型判定即本文的 5 组assert.deepEqual断言getIsDailyCodingChallenge与getDailyCodingChallengeLanguage两个工具函数把 28/29 归入每日挑战集合并分别映射到javascript/python语言标签。区块配置。daily-coding-challenges-javascript.json 声明了该区块的关键属性helpCategory: JavaScript、usesMultifileEditor: true、disableLoopProtectTests: true、blockLayout: legacy-challenge-list并且isUpcomingChange: true表明该区块处于待上线/变更状态。本区块从 “Challenge 1: Vowel Balance” 一直排到 “Challenge 365: The Last Challenge: Bucket Fill 3”全年 365 天每日一题本块同时被挂载在dev-playground超级区块下见 dev-playground.json供开发者/学习者在练习场中按序刷题。运行时数据流。在线页面上每日挑战由客户端组件 show-daily-coding-challenge.tsx 承接组件在 第 157163 行 按日期向${apiLocation}/daily-coding-challenge/day/{monthDay}发起请求先经validateDailyCodingChallengeSchema做 JSON Schema 校验再由formatChallengeData把数据库返回的 JavaScript 变体拼装成challengeType: 28、helpCategory: JavaScript的挑战节点见 第 91114 行最终注入ShowClassic组件渲染——即学习者看到的正是本挑战文件的题面、测试断言与script.js编辑区。Python 变体challengeType: 29编辑区main.py走同一管线仅语言与文件键不同。值得注意的边界仓库中该挑战文件本身没有tests段落5 组断言写在# --hints--小节内而区块 JSON 与在线 API 管线javascript.tests字段共同承担了测试的最终交付这也是该区块disableLoopProtectTests: true与在线校验流程配合的原因。小结与自测建议本题的通用解法可以归纳为三步预提取全部约束源信号塔→ 为每个约束源定义单点判定函数轴对齐/对角线距离→ 全网格扫描并用every做约束交集命中即返回。这一模式可迁移到本区块其他同类题目如 Challenge 243: Rook Attack、Challenge 245: Spiral Matrix 等网格题均位于 区块目录。自测步骤将本文给出的 5 组assert.deepEqual断言与你的findSignal实现放入同一个 Node.js 文件用 Node 内置的node:assert替换assert或在 freeCodeCamp 编辑器内直接提交确认全部通过对照“常见错误”一节逐一验证水平/垂直/对角线三种方向在 5 组用例中的覆盖用例 1、3 覆盖垂直与水平用例 2、4、5 覆盖对角线——全部通过说明方向判定逻辑完备。【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考