圈内内参|这期聊一个社区级的算法挑战。结论先放一句:一个被包装成“营救 Peter Norvig”的谜题,内核是 Advent of Code 2022 第 5 天“Supply Stacks”,输入放大到约 8.6 万行、合计超过 5 亿次箱子移动。作者 Thea 最后把它从 7 秒压到 89 毫秒,靠的不是更快地模拟,而是完全不模拟。信源先说清楚:这篇没有大厂内部匿名信源可用,全部基于 Dev.to 上一篇公开文章和它下面 22 条顶级评论,做不了我们惯常那种多源交叉核验,所以所有推断我标“(分析)”,其余可核对的正文内容标“(确认)”。
Thea 的文章 8 月 31 日发布,9 月 12 日最后编辑过。公开资料写她是前端工程师,常驻格鲁吉亚巴统,技术栈是 Python、Vue、React。但真正让我注意到这事的是挑战来源:她在 DEV 前端挑战赛上交了个纯 HTML 和 CSS 做的哈恰普里,然后作品下面有人留了条邀请,说有个“英雄之旅”挑战,要营救 Peter Norvig,跟他墙上的钟对决。一个 CSS 作品分流入一道算法竞赛题,这个入口不对劲,但正是整个事件的逻辑起点:包装层先于题目层存在。
从公开文章能直接确认的内容如下(确认):挑战叙事把 Peter Norvig 写成被挑战者“劫持”,说他代码占内存、CPU 持续繁忙;ThePrimeagen 的 Rust 解法被点名说处理不了这个输入规模。这些是文章里白纸黑字写的,拿到原文就能核对。“挑战已发布两年、大约一百名开发者参与、没人解出”这个说法,只能降级成“据文章”——它是挑战者本人在谜题里说的话,Thea 转录了一层,没有独立信源(未证实)。
这里有个细节我花了不少时间去查。文章里出现“钢筋女孩”这个词,格鲁吉亚语不常见,我停下来查证。结果评论里有个叫 Giorgi Kobaidze 的格鲁吉亚开发者说,他没听说过这个说法。挑战者后来也承认是现场编的。这件事很小,但值得立此存照:这次挑战的叙事层和事实层从头到尾是混着走的,有些符号是线索,有些符号只是氛围。把氛围组当线索读是浪费,把线索划成氛围组跳过是错过。Thea 后来能绕出来,关键一步就是从一个 GIF 线索——关于 Ygritte 眉毛动作的——跳到技术边界:堆栈数量受输入格式限制,移动数量则可以大到离谱。这一步跨出去,整个问题就变了。
挑战者花在包装上的工夫远超常规:Peter Norvig、ThePrimeagen、《信条》、《边境杀手》、April Ludgate 的 GIF,层层嵌套。这种设计能活两年、百人尝试未破,说明它真正测的不是算法,是参与者在高密度叙事噪声里回到问题原文、识别字面条件的能力。Thea 被人建议的做法是关掉 IDE,拿彩色铅笔把箱子画出来。这个动作看着像拖延,其实是后面一切优化的起点。一个人先在纸面上搞懂箱子到底怎么移动,才有底气放弃模拟。(分析,非事实):这种把中等难度算法题包成侦察任务的玩法持续存在,原因其实很朴素——题目本身零门槛,但叙事包装让它变成了社交网络上的内容产品。没有包装,AoC Day 5 没人会在两年里反复试。
等 Thea 把题从彩蛋里剥出来,内核就是 AoC 2022 Day 5“Supply Stacks”。这题她应该早熟,但输入已经放大到另一个量级:大约 8.6 万行、3 万条移动指令,单条指令有时候一次移动几万个箱子,合计对应超过 5 亿次箱子移动,而且部分指令要求移动的数量超过源堆栈实际拥有量。这个规模就是故意设的,让老老实实模拟箱子的解法全部撞墙。她的第一版用 JavaScript,数组表示堆栈,splice() 一次性切整块、倒转、推入。逻辑通,输出“JUAREZ”——正好和《边境杀手》里的地名对上,算作逻辑自证。但耗时 7 秒。7 秒在本地不算灾难,可对手是墙上的钟,不够。
第二版把数据表示改成引用重排:不复制箱子数据,只改指向,耗时压到 2 秒。到这一步还是常规优化。真正的转折在第三步——她开始问一个更根本的问题:题目只要求每个堆栈顶部的箱子,那为什么要完整算完所有堆栈?于是反向追踪,从最终需要的顶部位置倒着推,再配合一次廉价的正向遍历只记录每个堆栈大小,用 min(count, size) 修正超出实际大小的移动。最后 JavaScript 约 89 毫秒,Python 移植版 100–200 毫秒。复杂度 O(堆栈数 × 移动指令数),跟箱子总数脱钩。5 亿这个数字被整个绕开。
写到这,我觉得最值得记的还不是 89 毫秒这个结果,也不是她凌晨五点左右发现起始仓库其实是自己的 Python LeetCode 仓库,而是思路转变的那个节点:优化到某个阶段,不能再问“怎么让这个操作更快”,得问“这个操作还需要做吗”。这话容易读成鸡汤,但工程圈里大量所谓高级优化,只是第一种思路的加码。Bellatrix Ouranos 在评论里说得更直白:移动 5 亿个箱子的最快方式,是不去移动它们。
社区里另一条路线也值得记。评论里 UnitBuilds 说应该用 Rust 强制零分配重写,然后真跑出来:第一部分低于 2 微秒,第二部分约 2.3 微秒。跟 Thea 的 89 毫秒并排,差了两个数量级,但这是两条路。UnitBuilds 把“模拟”压到硬件极限,Thea 让模拟不再成立。不是谁强谁弱,我都很难说更喜欢哪一个——但(分析):在 AI 编程工具越来越擅长给第一种建议的环境里,第二种思路会变稀缺。因为第二种思路的第一步,是放下手头上已经在跑的那套东西,回到问题定义本身。AI 建议的默认方向,恰恰是帮你把手头那套跑得更快。
Thea 文章最后一部分,当信号看更有价值。她说这次挑战让她找回了长时间独自跟代码搏斗的乐趣,尤其在 AI 能快速给出建议的时代。这句话单拎出来像情怀,放进整个机制里,它指向的是一个正在被省略的步骤:建立自己的问题模型。挑战者中途让她关掉 IDE、拿彩色铅笔去画箱子,这个动作在今天很容易被工具替代掉。但如果她一开始就拿到 AI 的建议——“看顶部就行,引用重排”——大概率能更快交答案,但 7 秒到 2 秒到 89 毫秒那段挣扎就没了,也没了那句“编程再次非常有趣”。我没立场说这一定不好,只是在记录一个确凿发生的位移:画箱子的动作,在工具链里越来越没有位置。
几个值得盯的信号,盖文不下注,只列出来: 一、AoC 2022 Day 5 接下来会不会被更多社区挑战者拿去包装成类似的叙事谜题。如果出现第二例、第三例,“算法题社交化”就成了值得单开一篇的内容分发选题。 二、UnitBuilds 那个 2 微秒 Rust 零分配解法,后续会不会把“极致做”和“完全不做”两条路并案写。他的代码本身就是工程圈性能偏执当前落脚点的一个截面。 三、最值得长期看的是 AI 工具在社区长周期独立解题里的参与度变化。如果有更多开发者主动关掉 AI 做“独自搏斗”式练习,哪怕只是刻意练习,这个文化转向本身就够再写一篇。这几条都是公开可核验的,过几个月拿回来对着看,比现在拍脑袋判断“AI 会不会改变编程学习”靠谱。
