Baba英语
编程学习路线图

Human Resource Machine · 关卡攻略

关卡逐关攻略

HRM 把编程扒到最裸:你只有搬运、跳转、判断几条命令,却要拼出解法。这里每一关给你目标、可直接照抄的解法代码、和它为什么这样写。解法均经权威解法库核准。全 41 关(第 5、15、18、27、33 关为剧情过场,无代码)。后期关卡(乘除、排序、质因数分解…)已进入正经算法,难度陡增,可当进阶挑战。

1收发室Mail Room顺序 · 输入输出
目标

把 INBOX 里的三样东西,一件一件搬到 OUTBOX。

解法
INBOX
OUTBOX
INBOX
OUTBOX
INBOX
OUTBOX
讲解

inbox 从进货口拿一件、outbox 往出货口送一件,重复三次。这是最基础的“取输入、给输出”,先熟悉两条命令。

2忙碌收发室Busy Mail Room循环 ★
目标

不管 INBOX 里有几件,全部原样搬到 OUTBOX。

解法
a:
    INBOX
    OUTBOX
    JUMP  a
讲解

jump a 让程序不断跳回标签 a,形成循环——只写一次、重复执行;INBOX 空了游戏自动结束。核心一句:别重复自己,让机器重复。

3拷贝地板Copy Floor内存 · 按编号取
目标

地板上摆着一排字母方块。按题目要求,把其中三个(正好在 4、0、3 号格)按这个顺序送出去。

解法
COPYFROM 4
OUTBOX
COPYFROM 0
OUTBOX
COPYFROM 3
OUTBOX
讲解

copyfrom N = 从 N 号地板格把东西拿到手上(不清空原格)。地板格就是能“按编号存取”的抽屉——这是内存/变量最朴素的样子。

4乱序处理器Scrambler Handler暂存 · 交换顺序
目标

INBOX 里的东西成对出现。把每一对的前后两个“调个个儿”,再送出去。

解法
a:
    INBOX
    COPYTO   0
    INBOX
    OUTBOX
    COPYFROM 0
    OUTBOX
    JUMP     a
讲解

先拿第一个、copyto 0 存进 0 号格暂存;再拿第二个直接送出;最后把 0 号格里存的第一个送出——两个的顺序就换过来了。这就是“用一个临时变量交换”。

5咖啡时间Coffee Time过场

这一关是剧情过场——喝杯咖啡、歇口气,没有编程任务,直接进入下一关。

6多雨的夏天Rainy Summer加法 ADD
目标

INBOX 成对出现。把每一对的两个数相加,送出它们的和。

解法
a:
    INBOX
    COPYTO 0
    INBOX
    ADD    0
    OUTBOX
    JUMP   a
讲解

第一个数存进 0 号格;拿第二个时 add 0 = 手上的数 + 0号格的数,得到和再送出。第一次用到 ADD——让程序会算数。

7零的歼灭者Zero Exterminator条件跳转 · 判零
目标

把 INBOX 里的东西送出去,但把所有的 0 都扔掉、不要送。

解法
a:
    INBOX
    JUMPZ a
    OUTBOX
    JUMP  a
讲解

JUMPZ = 如果手上的值是 0 就跳转。这里“是 0 就跳回开头重新拿”(等于丢弃这个 0),不是 0 才送出。第一次“看情况做决定”的条件分支。

8三倍房间Tripler Room乘法=重复加法
目标

把 INBOX 里的每个数乘以 3,送出结果。

解法
a:
    INBOX
    COPYTO 0
    ADD    0
    ADD    0
    OUTBOX
    JUMP   a
讲解

机器没有乘法,就用加法凑:存一份 x 到 0 号格,手上是 x,add 0 → 2x,再 add 0 → 3x。记住:乘法就是重复的加法。

9保零计划Zero Preservation Initiative条件 · 反向过滤
目标

和第 7 关正好相反——只把 0 送出去,其它数字全部扔掉。

解法
    JUMP c
a:
    OUTBOX
b:
c:
    INBOX
    JUMPZ a
    JUMP  b
讲解

拿一个数:如果是 0(JUMPZ 成立)就跳去 outbox 送出;不是 0 就跳回去重拿、丢掉。同一个 JUMPZ,把“成立时去哪”换一下,就从“扔掉0”变成“只留0”。

10八倍套间Octoplier Suite倍增技巧 ×8
目标

把 INBOX 里的每个数乘以 8,送出结果。

解法
a:
    INBOX
    COPYTO 0
    ADD    0
    COPYTO 0
    ADD    0
    COPYTO 0
    ADD    0
    OUTBOX
    JUMP   a
讲解

不用傻加 8 次。每次把当前结果存回 0 号格再自加:x → 2x → 4x → 8x,三次翻倍就到 8 倍。这叫“倍增”,比一个个加快得多——效率意识从这里开始。

11暗巷减法Sub Hallway减法 SUB
目标

INBOX 成对出现。每对输出两个方向的差:先 b−a,再 a−b。

解法
a:
    INBOX
    COPYTO   0
    INBOX
    COPYTO   1
    SUB      0
    OUTBOX
    COPYFROM 0
    SUB      1
    OUTBOX
    JUMP     a
讲解

SUB 是减法命令。把 a、b 分别暂存到 0、1 号格,正着减一次、反着减一次,各输出一个。第一次用到减法。

12四十倍器Tetracontiplier乘法 · 倍增
目标

把每个数乘以 40。

解法
a:
    INBOX
    COPYTO   0
    ADD      0
    COPYTO   0
    ADD      0
    COPYTO   0
    ADD      0
    COPYTO   0
    ADD      0
    ADD      0
    ADD      0
    ADD      0
    OUTBOX
    JUMP     a
讲解

先连续翻倍得到 8 倍(×2×2×2),再把这 8 倍自加到 40 倍(8×5)。大乘数的诀窍:先翻倍逼近、再累加,比一个个加省得多。

13相等房间Equalization Room相等判断
目标

INBOX 成对。两数相等就输出其中一个,不等就都扔掉。

解法
    JUMP     b
a:
    COPYFROM 0
    OUTBOX
b:
c:
    INBOX
    COPYTO   0
    INBOX
    SUB      0
    JUMPZ    a
    JUMP     c
讲解

两数相减,若差为 0(JUMPZ 成立)说明相等、就输出;否则跳过。“相减是不是 0”正是编程里判断两值相等的底层做法。

14取大房间Maximization Room比较 · 取最大
目标

INBOX 成对。输出较大的那个。

解法
a:
    INBOX
    COPYTO   0
    INBOX
    SUB      0
    JUMPN    b
    ADD      0
    JUMP     c
b:
    COPYFROM 0
c:
    OUTBOX
    JUMP     a
讲解

算 a−b:若为负(JUMPN 成立)说明 a 小、输出 b;否则输出 a。“相减看正负”是比大小的通用手段。

15过场过场

这一关是剧情过场,没有编程任务。

16绝对正能量Absolute Positivity条件 · 绝对值
目标

把每个数变成非负:负数取相反数,正数原样输出。

解法
    JUMP     c
a:
    COPYTO   0
    SUB      0
    SUB      0
b:
    OUTBOX
c:
    INBOX
    JUMPN    a
    JUMP     b
讲解

若是负数(JUMPN),用“0 减两次”把它翻正(x−x−x = −x);正数直接输出。绝对值 = 去掉符号、只留大小。

17专属休息厅Exclusive Lounge条件 · 异或
目标

INBOX 成对。两数“同号还是异号”,分别输出地板上预存的两个标记之一。

解法
a:
    INBOX
    JUMPN    c
    INBOX
    JUMPN    d
b:
    COPYFROM 4
    JUMP     e
c:
    INBOX
    JUMPN    b
d:
    COPYFROM 5
e:
    OUTBOX
    JUMP     a
讲解

分别判断两个数的正负,符号相同和不同走不同分支。这就是“异或(XOR)”的思想:两者不一样时为真。

18过场过场

这一关是剧情过场,没有编程任务。

19倒计时Countdown循环 · 计数
目标

对每个数,从它一路数到 0,逐个输出(正数递减、负数递增)。

解法
a:
    INBOX
    COPYTO   0
b:
c:
    OUTBOX
    COPYFROM 0
    JUMPZ    a
    JUMPN    d
    BUMPDN   0
    JUMP     b
d:
    BUMPUP   0
    JUMP     c
讲解

每次输出当前值,再朝 0 挪一步:正数用 BUMPDN 减 1、负数用 BUMPUP 加 1,到 0 就停。BUMPUP/BUMPDN 是“某格 ±1”的快捷命令。

20乘法车间Multiplication Workshop乘法 = 重复加法
目标

INBOX 成对。输出两数之积 a×b。

解法
a:
    COPYFROM 9
    COPYTO   4
    INBOX
    COPYTO   1
    INBOX
    COPYTO   0
b:
    JUMPZ    c
    COPYFROM 4
    ADD      1
    COPYTO   4
    BUMPDN   0
    JUMP     b
c:
    COPYFROM 4
    OUTBOX
    JUMP     a
讲解

机器没有乘法,就把 a 累加 b 次:用一个计数器存 b,每加一次就减 1,减到 0 停。乘法的本质就是“把一个数加另一个数那么多次”。

21零止求和Zero Terminated Sum循环 · 哨兵值
目标

INBOX 是若干段,每段以 0 结尾。输出每一段的和。

解法
a:
    INBOX
    JUMPZ    d
b:
    COPYTO   0
    INBOX
    JUMPZ    c
    ADD      0
    JUMP     b
c:
    COPYFROM 0
d:
    OUTBOX
    JUMP     a
讲解

一路累加,直到碰到 0(哨兵/终止符)就输出这段的和、重新开始。用一个特殊值 0 标记“段结束”,真实数据里很常见(如字符串的结尾)。

22斐波那契访客Fibonacci Visitor变量 · 数列递推
目标

对每个输入 n,输出不超过 n 的斐波那契数列(1,1,2,3,5,8…)。

解法
a:
    INBOX
    COPYTO   0
    COPYFROM 9
    COPYTO   1
    COPYTO   2
    BUMPUP   2
b:
    OUTBOX
    COPYFROM 1
    ADD      2
    COPYTO   3
    COPYFROM 0
    SUB      3
    JUMPN    a
    COPYFROM 2
    COPYTO   1
    COPYFROM 3
    COPYTO   2
    JUMP     b
讲解

用两个格子记住“前两项”,每次输出当前项、再把两项相加得下一项,直到超过 n。斐波那契就是“下一项 = 前两项之和”的经典递推。

23最小的数The Littlest Number比较 · 求最小
目标

每段(0 结尾)里,输出最小的那个数。

解法
    JUMP     b
a:
    COPYFROM 0
    OUTBOX
b:
    INBOX
    JUMP     d
c:
    ADD      0
d:
    COPYTO   0
e:
    INBOX
    JUMPZ    a
    SUB      0
    JUMPN    c
    JUMP     e
讲解

记住“目前最小”,每来一个就比一比、更小就替换;到段尾输出冠军。这是“擂台式”求最值:保留当前最好,逐个挑战。

24取余模块Mod Module取余 = 反复减
目标

INBOX 成对。输出 a mod b(a 除以 b 的余数)。

解法
a:
    INBOX
    COPYTO   0
    INBOX
    COPYTO   1
    COPYFROM 0
b:
    SUB      1
    JUMPN    c
    JUMP     b
c:
    ADD      1
    OUTBOX
    JUMP     a
讲解

用 a 反复减 b,直到再减就变负——最后剩下的就是余数。取余的本质是“减到不够减为止,剩多少”。

25累计倒数Cumulative Countdown循环 · 累加
目标

对每个 n,输出 n+(n−1)+…+1 的总和。

解法
a:
    INBOX
    JUMPZ    d
    COPYTO   1
b:
    COPYTO   0
    BUMPDN   1
    JUMPZ    c
    ADD      0
    JUMP     b
c:
    COPYFROM 0
d:
    OUTBOX
    JUMP     a
讲解

从 n 开始,把 n、n−1、n−2… 一直加到 1。等差数列求和最朴素的写法:一个个加起来。

26短除法Small Divide除法 = 数减几次
目标

INBOX 成对。输出 a÷b 的商(整数,向下取整)。

解法
a:
    COPYFROM 9
    COPYTO   7
    INBOX
    COPYTO   0
    INBOX
    COPYTO   1
b:
    COPYFROM 0
    SUB      1
    JUMPN    c
    COPYTO   0
    BUMPUP   7
    JUMP     b
c:
    COPYFROM 7
    OUTBOX
    JUMP     a
讲解

数 a 里能减掉几个 b,商就是几。用计数器记录减的次数,减到不够为止。除法就是“反复减、数次数”,和取余(第 24 关)是一对孪生。

27过场过场

这一关是剧情过场,没有编程任务。

28三数排序Three Sort排序 · 比较交换
目标

每三个数一组,从小到大排好序输出。

解法
a:
    INBOX
    COPYTO   0
    INBOX
    COPYTO   1
    INBOX
    COPYTO   2
    SUB      1
    JUMPN    c
b:
    COPYFROM 2
    COPYTO   3
    COPYFROM 1
    COPYTO   2
    COPYFROM 3
    COPYTO   1
c:
    COPYFROM 1
    SUB      0
    JUMPN    d
    COPYFROM 1
    COPYTO   3
    COPYFROM 0
    COPYTO   1
    COPYFROM 3
    COPYTO   0
d:
    COPYFROM 1
    SUB      2
    JUMPN    b
    COPYFROM 2
    OUTBOX
    COPYFROM 1
    OUTBOX
    COPYFROM 0
    OUTBOX
    JUMP     a
讲解

三个数两两比较,谁小谁靠前,需要时交换位置,比完输出。这是“排序”的最小案例;再多的数也是同样“比较+交换”反复做(见第 41 关)。

29存储楼层Storage Floor指针 · 间接寻址
目标

INBOX 给一个地址编号,输出地板上那个编号格子里的东西。

解法
a:
    INBOX
    COPYTO   10
    COPYFROM [10]
    OUTBOX
    JUMP     a
讲解

`COPYFROM [10]` 是关键——方括号表示“取 10 号格里存的数当地址、再去那个地址取值”。这就是指针/间接寻址:格子里存的不是数据,而是“数据在哪”。

30字符串存储楼层String Storage Floor指针 · 字符串
目标

INBOX 给一个起始地址,从那里开始输出一串字母,直到遇到 0(结尾)。

解法
a:
    INBOX
    COPYTO   24
b:
    COPYFROM [24]
    JUMPZ    a
    OUTBOX
    BUMPUP   24
    JUMP     b
讲解

用间接寻址从起点逐格读取,读到 0 就停。字符串在内存里就是“一串连续字符 + 一个结尾标记 0”——这里第一次把指针和字符串合起来用。

31字符串反转String Reverse栈 · 反转
目标

读入一个以 0 结尾的字符串,倒着输出它。

解法
a:
b:
    BUMPUP   14
    INBOX
    JUMPZ    c
    COPYTO   [14]
    JUMP     b
c:
d:
    BUMPDN   14
    JUMPZ    a
    COPYFROM [14]
    OUTBOX
    JUMP     d
讲解

先把字符一个个存进连续的格子(指针向上走),到结尾再从最后一格往回读(指针向下走)。“后进先出”正是“栈”的思想,反转是它最经典的用途。

32库存报告Inventory Report遍历 · 计数
目标

对每个输入值,数一数它在地板上那串数里出现了几次,输出次数。

解法
a:
    INBOX
    COPYTO   16
    COPYFROM 14
    COPYTO   15
    COPYTO   17
b:
    COPYFROM [15]
    JUMPZ    e
    SUB      16
    JUMPZ    d
c:
    BUMPUP   15
    JUMP     b
d:
    BUMPUP   17
    JUMP     c
e:
    COPYFROM 17
    OUTBOX
    JUMP     a
讲解

从头到尾扫一遍地板列表,每个都和目标比一比,相等就计数 +1,扫到 0 结束、输出计数。“遍历一遍、边走边数”是最基础的统计操作。

33过场过场

这一关是剧情过场,没有编程任务。

34元音焚化炉Vowel Incinerator字符串 · 过滤
目标

读入一个字符串,输出它、但烧掉所有元音(A E I O U)。

解法
    JUMP     c
a:
    COPYFROM 7
    OUTBOX
b:
c:
    INBOX
    COPYTO   7
    COPYFROM 5
    COPYTO   6
d:
    COPYFROM [6]
    JUMPZ    a
    SUB      7
    JUMPZ    b
    BUMPUP   6
    JUMP     d
讲解

每读一个字母,挨个和地板上预存的 5 个元音比一比:撞上任何一个就跳过不输出,否则原样送出。“逐个对照黑名单过滤”是文本处理的常见套路。

35去重Duplicate Removal去重 · 查表
目标

读入一个字符串,每个字母只留第一次出现,重复的删掉。

解法
    COPYFROM 14
    JUMP     b
a:
    COPYFROM 11
    COPYTO   [14]
    OUTBOX
    BUMPUP   14
    SUB      14
b:
    COPYTO   [14]
c:
    COPYTO   14
    INBOX
    COPYTO   11
d:
    COPYFROM [14]
    JUMPZ    a
    SUB      11
    JUMPZ    c
    BUMPUP   14
    JUMP     d
讲解

每输出一个字母,就把它记进一张“见过的表”;后面再遇到就查表、见过就跳过。“用一张表记录见过什么”是去重的通用办法(哈希集合的雏形)。

36字典排序器Alphabetizer字符串比较 · 字典序
目标

给两个字符串,输出按字典顺序排在前面的那个。

解法
a:
b:
    COPYFROM 23
    COPYTO   22
c:
    INBOX
    COPYTO   [22]
    JUMPZ    d
    BUMPUP   22
    JUMP     c
d:
    COPYFROM 23
    COPYTO   22
e:
    COPYFROM [22]
    JUMPZ    j
    INBOX
    COPYTO   21
    JUMPZ    a
    SUB      [22]
    JUMPZ    f
    JUMPN    l
    JUMP     g
f:
    COPYFROM 21
    OUTBOX
    BUMPUP   22
    JUMP     e
g:
h:
    COPYFROM [22]
    JUMPZ    i
    OUTBOX
    BUMPUP   22
    JUMP     h
i:
j:
k:
    INBOX
    JUMP     k
l:
    COPYFROM 21
    OUTBOX
m:
    INBOX
    JUMPZ    b
    OUTBOX
    JUMP     m
讲解

从头逐字符比较两个字符串:第一个不同的位置谁的字母小谁排前;若一个是另一个的前缀,短的排前。“逐字符比大小”就是字典序,也是所有文字排序的基础。

37寻宝链Scavenger Chain链表 · 指针跳转
目标

地板上是一条寻宝链:每站存着[一个字母, 下一站地址]。INBOX 给起点,顺着链一路输出字母,直到走到头。

解法
a:
    INBOX
b:
    COPYTO   22
    COPYFROM [22]
    OUTBOX
    BUMPUP   22
    COPYFROM [22]
    JUMPN    a
    JUMP     b
讲解

读出当前站的字母输出,再读出“下一站地址”跳过去,直到地址为负(链尾)。这就是“链表”:数据不必连续摆放,每个节点自己记着“下一个在哪”。

38数字爆破Digit Exploder除法 · 拆数位
目标

把每个三位数拆成单个数字输出(如 123 → 1、2、3)。

解法
a:
    COPYFROM 9
    COPYTO   0
    COPYTO   1
    INBOX
    COPYTO   2
b:
    COPYFROM 2
    SUB      11
    JUMPN    c
    COPYTO   2
    BUMPUP   0
    JUMP     b
c:
d:
    COPYFROM 2
    SUB      10
    JUMPN    e
    COPYTO   2
    BUMPUP   1
    JUMP     d
e:
    COPYFROM 0
    JUMPZ    f
    OUTBOX
    JUMP     g
f:
    COPYFROM 1
    JUMPZ    h
g:
    COPYFROM 1
    OUTBOX
h:
    COPYFROM 2
    OUTBOX
    JUMP     a
讲解

除以 100 得百位、余数再除以 10 得十位、剩下的是个位。“除法取商和余数”就能把一个数按位拆开——这是进制的核心操作。

39重定坐标Re-Coordinator除法 · 商与余数
目标

对每个输入,求它除以每行宽度(这里是 15)的商和余数,分别输出——相当于把线性编号换算成网格的行、列坐标。

解法
    JUMP     b
a:
    ADD      15
    OUTBOX
    COPYFROM 1
    OUTBOX
b:
    COPYFROM 14
    COPYTO   1
    INBOX
c:
    SUB      15
    JUMPN    a
    COPYTO   0
    BUMPUP   1
    COPYFROM 0
    JUMP     c
讲解

反复减 15、数减了几次(商=行),减到不够、剩下的(余数=列)。一次除法同时给出商和余数,正是“一维编号 ↔ 二维坐标”互换的关键。

40质数工厂Prime Factory质因数分解
目标

把每个数分解成质因数,从小到大逐个输出(如 12 → 2、2、3)。

解法
    COPYFROM 24
a:
    COPYTO   5
    COPYTO   2
    BUMPUP   5
    INBOX
    COPYTO   0
b:
    BUMPUP   5
c:
    COPYFROM 24
    COPYTO   1
    COPYTO   2
    BUMPDN   0
    JUMPZ    a
    BUMPUP   0
d:
    SUB      5
    JUMPN    b
    COPYTO   2
    BUMPUP   1
    COPYFROM 2
    JUMPZ    e
    JUMP     d
e:
    COPYFROM 5
    OUTBOX
    COPYFROM 1
    COPYTO   0
    JUMP     c
讲解

从最小的质数 2 开始试除:能整除就输出这个因子、并把数除掉;除不尽就换更大的除数,直到剩 1。这是“质因数分解”,也是很多数学/密码学问题的地基——难度已相当高。

41排序楼层Sorting Floor排序算法
目标

读入一串以 0 结尾的数,全部存到地板上,从小到大排好序后输出。

解法
a:
b:
    BUMPUP   24
    INBOX
    JUMPZ    d
    COPYTO   [24]
    JUMP     a
c:
    COPYFROM [19]
    OUTBOX
    COPYFROM [24]
    COPYTO   [19]
d:
    BUMPDN   24
    JUMPZ    b
    COPYTO   23
e:
    COPYFROM 23
    COPYTO   19
f:
    BUMPDN   23
    JUMPZ    c
    COPYFROM [23]
    SUB      [19]
    JUMPN    e
    JUMP     f
讲解

把所有数先存下来,再反复扫描、每轮挑出剩下里最小的一个输出(选择排序)。这是完整的“排序算法”——第 28 关三个数的放大版,也是计算机最核心的基本功之一。

怎么用 卡住了再来看。先自己试,真想不出再照解法抄一遍,重点是读懂「讲解」里它为什么这样写——比抄答案更重要的是弄懂那一步。解法参考 cowboy/human-resource-machine-solutions。