ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

freeCodeCamp 每日编程挑战解析:用 Python 实现 Pangram 判定函数

freeCodeCamp 每日编程挑战解析:用 Python 实现 Pangram 判定函数 freeCodeCamp 每日编程挑战解析用 Python 实现 Pangram 判定函数【免费下载链接】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」系列的Challenge 24: Pangram展开完整讲解题目规则、8 组自动化测试用例、种子代码结构以及官方参考解法的逐行原理并结合仓库中 API 路由、测试执行机制与课程结构文件帮助读者掌握「字符串清洗 集合去重 有序比较」这一类经典判题思路并能在本地用 unittest 独立复现验证。一、挑战背景什么是 Pangram 判定Pangram全字母短句指一句话中包含字母表中每一个字母至少一次的文本最著名的英文例子是The quick brown fox jumps over the lazy dog.快速棕狐跳过懒狗。本题在此基础上做了一个变体不要求使用完整的 26 个字母而是给定一个任意的字母集合判断输入文本是否恰好使用了该集合中的全部字母、且没有使用集合之外的字母。这道题位于仓库课程结构daily-coding-challenges-python块的 Challenge 24: Pangram挑战 id6821ec02237de8297eaee79a对应的挑战源文件为 6821ec02237de8297eaee79a.md。从课程结构文件可见该块共包含数百道 Python 每日挑战Challenge 1: Vowel Balance 一直到 Challenge 200本道题是其中典型的字符串处理 集合逻辑题目challengeType: 29表明它是每日编程挑战类型的课程条目。二、题目描述与两条核心规则原题描述如下Given a word or sentence and a string of lowercase letters, determine if the word or sentence uses all the letters from the given set at least once and no other letters.给定一个单词或句子以及一串小写字母判断该单词或句子是否至少一次用到了给定集合中的全部字母并且没有使用其他字母。题目明确了两条处理规则忽略文本中的非字母字符Ignore non-alphabetical characters in the word or sentence即空格、标点、数字等一律不参与判定忽略字母大小写Ignore letter casing in the word or sentence即Hello与hello、World与world视为相同字母。这意味着判定过程是一个双条件逻辑输入文本去重后的小写字母集合 给定字母集合。既不能缺少给定集合中的任何字母all the letters at least once也不能多出任何给定集合之外的字母no other letters。三、8 组测试用例逐一拆解题目的# --hints--小节用 Pythonunittest写入了 8 组判定用例通过runPython在浏览器内执行并调用TestCase().assertIs(is_pangram(...), True/False)进行断言。全部用例整理如下输入 sentence输入 letters期望结果解释helloheloTruehello 只含 h/e/l/o且四字母齐全hellohelFalse缺少字母ohellohelowFalse多出字母whello 中没有 whello worldhelowrdTrue空格被忽略h/e/l/o/w/r/d 恰好齐全Hello World!helowrdTrue大小写被忽略感叹号被忽略Hello World!heliowrdFalse缺少l且多出ifreeCodeCampfrcdmpFalsefreeCodeCamp 含有给定集合之外的 e/o/aThe quick brown fox jumps over the lazy dog.abcdefghijklmnopqrstuvwxyzTrue经典全字母短句恰好用全 26 个字母从这组用例可以归纳出测试设计者的三个考察点缺失判定第 2、6 组验证给定集合中某个字母没有出现时必须返回False多余判定第 3 组验证文本出现了集合外字母时必须返回False清洗规则第 4、5 组验证空格与标点被忽略第 5 组同时验证大小写被忽略第 8 组验证恰好使用完整字母表的全字母短句判定。四、种子代码你需要补全的函数骨架题目在# --seed--中给出如下函数骨架def is_pangram(sentence, letters): return sentence学习者需要在不改变函数签名is_pangram(sentence, letters)的前提下补全函数体使其对上述 8 组用例全部返回正确布尔值。初始骨架直接return sentence说明这里只是占位等待学习者用逻辑替换。五、官方参考解法逐行剖析题目在# --solutions--中提供了官方参考解法import re def is_pangram(sentence, letters): used_letters [] for char in sentence.lower(): if re.match(r[a-z], char) and char not in used_letters: used_letters.append(char) sorted_letters .join(sorted(letters.lower())) sorted_used_letters .join(sorted(used_letters)) return sorted_letters sorted_used_letters逐行拆解其核心思路sentence.lower()先统一转小写一次性满足忽略大小写规则让后续正则只需匹配[a-z]一个区间re.match(r[a-z], char)用正则逐字符过滤只保留字母表中的小写字母天然忽略非字母字符空格、数字、标点全部被跳过。注意这里使用re.match而非re.search因为re.match从字符串开头匹配对单个字符char而言二者等价但语义上更直接char not in used_letters去重保证同一个字母只记录一次——这正是uses all the letters ... at least once至少一次的落地点出现多次与出现一次等价.join(sorted(letters.lower()))与.join(sorted(used_letters))对给定集合与文本提取出的字母分别排序后拼接成字符串return sorted_letters sorted_used_letters字符串相等比较同时验证不缺失文本集合是给定集合的超集方向与不溢出文本集合不包含给定集合之外的字母。排序消除了字母出现顺序对比较结果的影响把集合相等这一无序概念转化为有序字符串的相等判断。复杂度分析时间复杂度遍历sentence为 O(n)n 为句子长度去重时的char not in used_letters是列表线性查找 O(m)m 为已收集字母数排序为 O(k log k)k ≤ 26整体最坏约 O(n·m k log k)。由于字母表最多 26 个字母常数很小空间复杂度O(k)k 为去重后的字母数最大 26。六、更 Pythonic 的备选解法集合Set视角官方解法用排序后字符串相等模拟集合比较而 Python 原生集合可以让这道题的语义更直白。由于字母集合天然无序集合相等正是set set的原生语义可以写成import re def is_pangram(sentence, letters): used set(re.findall(r[a-z], sentence.lower())) return used set(letters.lower())这里re.findall一次性提取全部小写字母并交给set()去重set(letters.lower())把给定集合也转成集合最后直接比较。这种写法与官方解法逻辑等价同样先忽略大小写、忽略非字母、再去重最后做集合相等判断且省去了排序步骤代码更短、语义更接近uses all the letters ... and no other letters的题面描述。对学习者而言两种解法都可以通过全部 8 组用例官方解法胜在不依赖集合的等值语义、纯字符串操作即可完成集合解法胜在可读性。推荐理解官方解法后再尝试用集合重写体会同一逻辑的不同表达。七、测试是如何运行的runPython 与 unittest 断言机制题目中的每个 hint 都是一段嵌入 Markdown 的 JavaScript 代码其核心是调用浏览器沙箱中的runPython({test: () { runPython( from unittest import TestCase TestCase().assertIs(is_pangram(hello, helo), True)) }})这段测试的含义是runPython(...)将 Python 代码字符串注入挑战环境执行from unittest import TestCase导入 Python 标准库单元测试框架TestCase().assertIs(is_pangram(hello, helo), True)断言函数返回值与期望的布尔值是同一个对象assertIs检查身份等价对布尔值而言即要求严格返回True/False而非1/0等可隐式转换的值。这意味着学习者实现的is_pangram必须返回真正的布尔值。若写成return 1或返回字符串assertIs会判定失败——这是本挑战在严格返回类型层面的隐性要求也是初学 Python 时容易踩的坑。八、这道题在 freeCodeCamp 项目中的位置理解一道挑战如何上线到产品中能帮助学习者把握整套课程的工程链路。从当前仓库源码可以确认以下事实1. 课程结构定义挑战在 curriculum/structure/blocks/daily-coding-challenges-python.json 的challengeOrder中被登记为Challenge 24: Pangramid6821ec02237de8297eaee79a该块配置了usesMultifileEditor: true、helpCategory: Python、blockLayout: legacy-challenge-list即学习者通过多文件编辑器完成 Python 每日挑战。2. 每日挑战的数据发布接口挑战内容描述、hints、测试经 tools/daily-challenges/seed-daily-challenges.ts 脚本从课程源文件灌入数据库该脚本同时拉取 JavaScript 与 Python 两套挑战并断言二者数量一致。运行方式在 tools/daily-challenges/README.md 中有说明复制sample.env为.env、启动客户端、进入tools/daily-challenges后执行pnpm seed-daily-challenges。挑战数据落库后由 API 侧的公开只读路由对外提供实现在 api/src/daily-coding-challenge/routes/daily-coding-challenge.tsGET /daily-coding-challenge/today返回今日挑战GET /daily-coding-challenge/date/:date按YYYY-MM-DD返回指定日期挑战GET /daily-coding-challenge/day/:day按MM-DD返回用于跨年循环展示GET /daily-coding-challenge/month/:month按YYYY-MM返回当月挑战列表GET /daily-coding-challenge/all返回全部已发布挑战的摘要列表GET /daily-coding-challenge/newest返回最新一条挑战的日期。路由层对未来挑战做了屏蔽——例如date路由中若查询日期晚于美国中部时区当日则返回404 Challenge not found源码注释还指出挑战数据截止于 2026-08-10。日期相关的时区换算逻辑getNowUsCentral、getUtcMidnight、getSourceDate等集中在 api/src/daily-coding-challenge/utils/helpers.ts其中getSourceDate会把任意日期映射回 2025-08-11 至 2026-08-10 的原始挑战周期并将 2 月 29 日映射到 2 月 28 日。接口响应结构与校验定义在 api/src/daily-coding-challenge/schemas/daily-coding-challenge.ts每条挑战包含id、date、challengeNumber、title、description以及javascript与python两种语言的teststext testString与challengeFiles。3. 前端入口客户端首页/地图页通过 client/src/components/daily-coding-challenge/widget.tsx 提供前往今日挑战与挑战归档两个入口按钮client/src/components/daily-coding-challenge/helpers.ts 负责把当前美国中部时间格式化为MM-DD含闰日映射用于拼装挑战路由。九、易错点与调试建议不要忽略去重只判断文本字母 ⊆ 给定集合是不够的还必须保证给定集合的每个字母都至少出现一次。忘掉去重直接做排序比较会在letters含重复字母时出错不要忽略非字母字符若不过滤空格与标点hello world这类带空格的用例会直接失败统一大小写时机先lower()再过滤否则re.match(r[a-z], char)会漏掉大写字母返回布尔值而非其他真值测试用assertIs(..., True)必须返回True/False字面量本地快速验证把函数定义与 8 组用例抄入本地文件用python -m unittest或直接断言脚本跑一遍即可脱离浏览器环境复现全部判定逻辑。十、小结Pangram 挑战看似简单实则完整覆盖了字符串类编程题的四个经典环节输入清洗忽略非字母、归一化忽略大小写、去重至少一次、集合比较不多不少。官方解法用排序后字符串相等实现集合语义是纯字符串工具链的优雅示范集合写法则更贴近题面语义。无论哪种解法最终都要通过 8 组unittest断言。将解题逻辑与 API 路由、日期辅助函数 以及 课程结构文件 串联起来观察就能看到一道题目从 Markdown 源文件到数据库、再到前端挑战页面的完整工程链路——这正是 freeCodeCamp 每日编程挑战模块的技术全貌。【免费下载链接】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 READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进