第二十一夜 数字黑洞与西西弗斯的惩罚
上一夜的习题Ⅱ,你写过一个程序,从 9376 往前接一位,把 0 到 9 各试了一遍,看哪个数字接得上。把所有的可能挨个试一遍,这是程序最笨、也最诚实的功夫。这一夜,这个功夫要升级一次。不是十个数字挨个试,是九千个号码一起试。因为这一夜要进数字王国的边疆,那里有两座洞。第一座洞不挑食,一串数字不管多长,掉进去几步就安家。第二座洞挑剔,可整个王国的九千个四位数,一个不少,全被它收了。第二座洞你其实见过。第二夜的那幅画里,它露过一面,只给了一幅画的功夫。这一夜回去,把没讲完的讲完。
先看第一座。数字王国的人讲一个老故事。有个人叫西西弗斯,得罪了天上的神,罚他把一块圆石推上山顶。石头太重,每一次快到顶,就滚下来,他就再推。神仙罚人,从不罚一次性的痛,罚的是重复。后世有个叫加缪的法国人把这个故事讲成了现代哲学,他说,那块石头是每个人手里的日子。数字王国的人听了这个故事,想起自己家里的一件事,就给一道算术起了这个名字。
规则很简单。任取一串数字,比如 1234567890。数一数里面有几个偶数,几个奇数,一共几位。偶数是 2、4、6、8、0,五个;奇数是 1、3、5、7、9,也是五个;一共十位。把这三个数并排写成新数,就是 5510。对 5510 再来一遍。5、5、1 三个奇数,0 一个偶数,共四位,新数 134。再来一遍。134 里,4 一个偶数,1、3 两个奇数,共三位,新数 123。再走一步试试。
1+2=3
123 里面,2 是偶数,一个;1 和 3 是奇数,两个;一共三位。偶数一个,奇数两个,总位数三位,拼起来还是 123。它到了家。再推多少遍,还是 123。石头再也滚不下去了。
名字里是惩罚,洞里是安家。这是这一夜的第一层反转。数字王国的人起这个名字的时候,大约只想着推石头的苦,没有想过最后一格棋盘上的结局。西西弗斯推了千万年,石头永远滚下来;123 只用了三步,就再也不用推了。神仙要是这么罚数,数们都抢着去。
这个洞还有一件更奇怪的事,它不在乎来路有多长。规则里说的不是四位数,不是十位数,是任取一串。我拿程序试过一串一万位的数字,随机生成的,一万个数字排成一条长队。你猜几步到家。四步。第一步,一万位塌成 13 位;第二步,13 位塌成 4 位;第三步到 123;第四步,验证它确实不再动了。一万个数字的队伍,走了四步。这个洞吞噬一切长度,靠的不是什么深渊巨口,是一把尺子。不管多长的串,数完偶数奇数位数,写出来的新数只有三段,而这三段天然满足一件事,偶数的个数加奇数的个数,恰好等于总位数。也就是说,第一步落地之后,天下所有的新数都守着同一个约束,三个组成部分,前两个加起来等于第三个。我让程序把这种受约束的数枚举了两百万个,全部走了一遍,最顽固的也只用了三步。这就是两百万次勘探换来的判决,这座洞的深,不在于它的口子开得多大,在于它的底是平的,谁都摔得到,摔到了就站得住。
有两个细节要交代,都是坑。第一个,0 算不算偶数。算。数学里 0 是偶数,这里照办,所以 134 里的 0 计入偶数那一栏。第二个,拼新数的时候如果奇数是零个,写不写那个 0。比如数字串 40,偶数两个,奇数零个,共两位。新数写成 202,还是写成 22。我两种都跑了。按前一种,40 走三步到家;按后一种,22 再变 202,也走四步到家。殊途同归,步数不同,家是同一个。较真的读者可以自己跑一遍,这个洞对细节的宽容大得出奇。
这座洞是谁发现的,查不到了。中文世界管它叫西西弗斯黑洞,趣味数学的读物里流传了几十年,始作俑者无据可查。本书的规则,这样的数登记为民间流传。跟它相对的第二座洞就完全两样了,发现者的姓名、年代、发表在哪儿,一笔一笔都查得清清楚楚。因为这座洞的发现者,不是数学家。
他叫卡普雷卡尔,印度人,1905 年生,一辈子在孟买东北一座叫德夫拉利的小镇上当学校教师。不是大学教授,不是研究院的研究员,是一个每天给学生上课、批作业的教书匠。他业余的全部爱好,是自己跟数字玩。1949 年,他四十四岁,玩出了第二座洞。1955 年,他把这个发现写成一篇几页的短文,发表在一份叫 Scripta Mathematica 的数学杂志上,题目老老实实,就叫「数 6174 的一个有趣性质」。又过了二十年,1975 年,美国科普作家马丁·加德纳在他那档举世闻名的「数学游戏」专栏里写了它,从此全世界的趣味数学爱好者都认识了这个数。一个人,一间小镇教室,一支笔,玩出了一个全世界传诵的数。顺带说一句,这位教师的发现不止这一个。他发现过一类自己平方之后劈成两半再相加还能还原自己的数,最典型的是 45,因为 45 的平方是 2025,20 加 25 等于 45。他还发现过一类怎么也写不成「一个数加上它的数位和」的数,干脆用家乡的名字给它们命名,叫德夫拉利数。小镇给了他饭碗,他给小镇留了名。
6174 这座洞的规则,你在第二夜已经见过,这里正名。任写一个四位数,要求四个数字不全相同。把数字从大到小排一遍,得到最大的数;从小到大排一遍,得到最小的数;大的减小的。对差数再做同样的事。这一套动作,天下人叫它重排求差。卡普雷卡尔发现,不管你从哪个四位数出发,反复重排求差,至多七步,必定落在 6174。到了 6174 之后呢,你在第二夜也见过,7641 减 1467,还是 6174。
先补一句三位数的。四位数的规则缩到三位数上,洞还在,只是门牌换了。任取一个三位数,三个数字不全相同,重排求差,反复做,最后必定落在 495。比如 207,720 减 027 得 693,963 减 369 得 594,954 减 459 得 495,到了。三位数的 495 和四位数的 6174,是同一座井的两层,不是两座洞。这一点我可以说得很有底气,因为这道题我亲手讲过。2025 年 11 月 12 日,机房,三个数字的重排求差,我在课堂上当堂手敲,半小时一遍过。拆位,排序,大减小,do-while 循环,每一步打印一行。那份代码的题面里有一句话,我当年抄题的时候没有多想,这一夜才看清它的分量。题面说,序号从 1 开始,直到 495 出现在等号右边为止。这句话意味着,如果输入的数就是 495,程序也要做一次重排求差,打印出 954 减 459 等于 495,然后才许停。我已经到家了,还得再走一步。这话是谁定的,题目的作者。为什么这么定,为了让循环的出口有个统一的判据。这一夜的最后我们要回到这句话,它比看上去深得多。
495 说完了,现在勘探。你也许以为,两位数有一个更小的洞,三位 495,四位 6174,五位数该有一个更大的。勘探的结果,数字王国的地下完全不是这么长的。两位数没有洞。全部两位数重排求差,没有一个是到家不动的,它们全都在一条环形跑道上转圈。跑道有五个位置,像这样。
90-09=81
81-18=63
63-36=27
72-27=45
54-45=09
09 再来一遍,90 减 09 还是 81,周而复始。两位数不是掉不进洞,是这条赛道上没有洞口,只有一条五格的环线。三位数有洞,495,最顽固的数要六步,最小的那个顽固分子是 100。四位数有洞,6174。五位数又没有了,而且比两位数更乱,五位数底下不是一个圈,是三个,两个圈各有四个位置,一个圈只有两个。这里我必须停一下,说一句题外话。五个数的圈结构,网上流传的资料有两种说法,两种都带着具体的数,看着都像真的。我两样都跑了一遍,再把五位数全部九万个挨个试了一遍,跑出来的答案是三个圈,两种说法都不全对,它们各自抄了三个圈里的一两个。跑出来的才算数,这一夜又添了一个例证。三个圈长这样。
95553-35559=59994
99954-45999=53955
这是一对,2 步一个来回。另外两个圈各有四步。六个位置的名字我不在正文里排开了,附注里有。到了六位数,家又回来了,而且一来是两个,549945 和 631764,九十万个数分两家投奔,另有一伙住进一个七格的圈。从两位到六位,洞的家底是这么一番景象,没有,有,有,没有,有两个。没有公式预言下一层是什么样,每一位数都是一次新的勘探,挖开才知道。这正是卡普雷卡那一代趣味数学家的日子,没有定理护身,只有一行一行地算。
现在该还第二夜欠的最后一笔了。为什么偏偏是 6174,为什么至多七步。我在前面说过,第一座洞的判决是两百万次勘探跑出来的。第二座洞也一样,这个为什么,不是推导出来的,是清点出来的。程序出场,把 1000 到 9999 的九千个号码全部押进洞口,挨个过堂。判决如下。九千个号码里,有九个是全同数,1111 到 9999,它们一步摔进 0,因为最大的排法减最小的排法等于零。0 也算一个家,自己减自己永远是 0,但那是个平平无奇的家,题目的规则把数字不全同设为门槛,就是为了绕开它。剩下的八千九百九十一个,全部落进 6174,无一漏网。步数的分布是这样的。
| 步数 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| 个数 | 1 | 356 | 519 | 2124 | 1124 | 1379 | 1508 | 1980 |
0 步的那一个,是 6174 自己。七步才到的,有一千九百八十个,我叫它七步军团。军团里号码最小的一个,是 1004。它的过堂记录,一行一行抄给你,这是本夜的画面。
4100-0014=4086
8640-0468=8172
8721-1278=7443
7443-3447=3996
9963-3699=6264
6642-2466=4176
7641-1467=6174
七步。从 1004 到 6174,一步没有多,一步没有少。第二夜的习题一让你数过一个四位数的步数,这道题的答案现在发下来,最顽固的数要七步,而这样的数有 1980 个,你可能随手写的一个就在军团里。至多七步这件事本身也经得起再问一句,为什么这么快。粗浅的一层是,重排求差的结果永远是 9 的倍数。大的排法减小的排法,首位和末位一换位置就差出 999 倍,中间两位换位置差出 90 倍,所以每走一步,差数都站在 9 的倍数这一小圈人里,候选的队伍一步比一步短。再往深一层,就要一个圈一个圈地数轨道了,那些留给附注和有兴趣的读者。清点判决不靠这些也站得住,九千个嫌疑人,全过了一遍堂,卷宗在这张表里。
两座洞都看完了,这一夜开头欠下的那笔,现在来结。第二夜我说过一句话,跑起来停不下的,不配叫算法。那句话判的是人写的程序。你的代码,你要负责让它停下来,递归要有出口,循环要有边界,这不是数学的要求,是工程的责任。可是 6174 不是程序。它没有写它自己,它是重排求差这条规则的产物,规则里没有停,它就在家门口永远转圈。数字没有立法权,它连自己的规则都定不了。但有立法权的,是人。你那份机房题的题面就是立法现场,直到 495 出现在等号右边为止。一句话,循环有了出口,连已经到家的 495 都要当着人面再走一步,把这一步走完,程序才许停。数字在洞里安家,是数学的事;什么时候算到了家,是人定的事。
加缪给西西弗斯下的结论,写在那本散文的最后一页。他说,攀登山顶的拼搏本身,就足以充实一颗人心。应当想象西西弗斯是幸福的。原文的说法是 il faut,应当,必须。这不是报告西西弗斯的感受,石头没有感受,这是教人怎么看。数字也一样。123 不知道自己安了家,6174 不知道自己在转圈,幸福和惩罚都是人往上看的。人能做的,比想象还多一点,想象之后,可以立法。给循环立一个停的规则,是每一个写程序的人都要亲手做的事。
洞是数字的家,停是人的立法。西西弗斯的石头还在山上滚,可是每一夜,总有人给新的循环写下出口。
这一夜的程序有三段。第一段走第一座洞,任一串数字,数偶数奇数位数,拼新数,反复,直到 123。
java
public class SisyphusHole {
public static void main(String[] args) {
String[] tests = {"1234567890", "35962", "40", "7", "0000"};
for (String s : tests) {
String cur = s;
int steps = 0;
System.out.print(cur);
while (!cur.equals("123")) {
int even = 0, odd = 0;
for (int i = 0; i < cur.length(); i++) {
int d = cur.charAt(i) - '0';
if (d % 2 == 0) {
even++;
} else {
odd++;
}
}
cur = "" + even + odd + cur.length();
steps++;
System.out.print(" -> " + cur);
}
System.out.println(" (steps: " + steps + ")");
}
}
}
实跑输出,和正文演过的每一串核对。
text
1234567890 -> 5510 -> 134 -> 123 (steps: 3)
35962 -> 235 -> 123 (steps: 2)
40 -> 202 -> 303 -> 123 (steps: 3)
7 -> 011 -> 123 (steps: 2)
0000 -> 404 -> 303 -> 123 (steps: 3)
第二段走第二座洞,重排求差。排序不用库,四个数字两两比较换位,像冒泡那样先把最大的顶到头,再把最小的沉到底,中间两位比一次。三个数字的版本就是当年机房题的六分支,四个数字用五次比较,思路是一样的。
java
public class KaprekarHole {
static int[] digits4(long n) {
int[] d = new int[4];
for (int i = 3; i >= 0; i--) {
d[i] = (int) (n % 10);
n /= 10;
}
return d;
}
static long step(long n) {
int[] d = digits4(n);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3 - i; j++) {
if (d[j] < d[j + 1]) {
int t = d[j];
d[j] = d[j + 1];
d[j + 1] = t;
}
}
}
long big = d[0] * 1000 + d[1] * 100 + d[2] * 10 + d[3];
long small = d[3] * 1000 + d[2] * 100 + d[1] * 10 + d[0];
return big - small;
}
public static void main(String[] args) {
long n = 1004;
int steps = 0;
while (n != 6174) {
long next = step(n);
steps++;
System.out.println("step " + steps + ": " + n + " -> " + next);
n = next;
}
}
}
实跑输出,正文那七行等式的程序版。
text
step 1: 1004 -> 4086
step 2: 4086 -> 8172
step 3: 8172 -> 7443
step 4: 7443 -> 3996
step 5: 3996 -> 6264
step 6: 6264 -> 4176
step 7: 4176 -> 6174
第三段是全量押送,九千个号码挨个过堂,数出步数分布,验出七步军团。
java
public class Night21Census {
public static void main(String[] args) {
int[] dist = new int[10];
int stubborn = 0;
long smallestStubborn = -1;
for (long n = 1000; n <= 9999; n++) {
int[] d = new int[4];
long t = n;
for (int i = 3; i >= 0; i--) {
d[i] = (int) (t % 10);
t /= 10;
}
if (d[0] == d[1] && d[1] == d[2] && d[2] == d[3]) {
continue;
}
long cur = n;
int steps = 0;
while (cur != 6174 && steps < 100) {
cur = KaprekarHole.step(cur);
steps++;
}
dist[steps]++;
if (steps == 7) {
stubborn++;
if (smallestStubborn < 0) {
smallestStubborn = n;
}
}
}
for (int s = 0; s <= 7; s++) {
System.out.println("steps " + s + " : " + dist[s]);
}
System.out.println("7-step legion: " + stubborn + ", smallest: " + smallestStubborn);
}
}
实跑输出。
text
steps 0 : 1
steps 1 : 356
steps 2 : 519
steps 3 : 2124
steps 4 : 1124
steps 5 : 1379
steps 6 : 1508
steps 7 : 1980
7-step legion: 1980, smallest: 1004
① 附录与真伪核对
Ⅰ 卡普雷卡尔,Dattatreya Ramchandra Kaprekar,1905 年 1 月 17 日生于印度马哈拉施特拉邦达哈努,1986 年去世(一说 1988,资料有出入),长期在德夫拉利镇任学校教师,业余研究数论,除 6174 外还发现 Kaprekar 数(如 45,45²=2025,20+25=45)与 self number(以家乡德夫拉利命名)。1949 年发现 6174;1955 年论文「An Interesting Property of the Number 6174」发表于 Scripta Mathematica(各处引用的卷期页码不一致,本书只记年份与刊名);1975 年 12 月马丁·加德纳在 Scientific American「数学游戏」专栏撰文推广。
Ⅱ 五位数的圈结构,本机实跑定谳为三个圈。两个四步圈 74943→62964→71973→83952→74943 与 63954→61974→82962→75933→63954,一个两步圈 53955→59994→53955。全部 89991 个数字不全同的五位数逐一勘探,无一落单。网络资料常见的两种说法(只有一个四步圈、圈为 62964 系与 75933 系之一)均与实跑不符,属传抄不全。
Ⅲ 六位数有两个不动点,549945 与 631764,另有七成员圈 420876→851742→750843→840852→860832→862632→642654→420876。六位数的叙述常见于西山豊(Yutaka Nishiyama)的验证文章,其论文同时给出七步上限的计算机复验。
Ⅳ 前导零的两种拼法。把「偶 2 奇 0 位 2」拼成 202(保留中间的 0)或拼成 22(数字式读法),123 洞都收敛。40 走 202 的路三步到家,22 走 22→202 的路四步到家。输入 7 的差别更明显,拼法一走 011 两步到家,拼法二走 11→22→202→303→123 五步到家。殊途同归的原因与正文说的尺子有关,两种拼法写出的新数都满足「偶加奇等于总位数」的约束,受约束的世界就那么大,洞口谁也躲不开。
Ⅴ 封顶论证的实跑口径。第一步落地后,新数三段满足偶数个数加奇数个数等于总位数。程序枚举总位数 1 到 2000 的全部三段组合,共 2003000 个状态,全部收敛于 123,最多三步。一万位的随机数字串,四步到家。
Ⅵ 重排求差必是 9 的倍数的分解。四位数 abcd 降序为最大、升序为最小,两数之差等于 999 乘以首位末位之差加上 90 乘以中间两位之差,两项都含因数 9。这是步步塌缩的粗层原因;完整的轨道分析见西山豊论文。
Ⅶ 45 不是自守数。第二十夜讲过自守数,平方之后尾巴还是自己,如 9376 的平方以 9376 结尾。45 的平方 2025 尾巴不是 45,45 的玩法是劈半相加,20 加 25,两回事。这一族数天下人叫它 Kaprekar 数,恰与 6174 的发现者同姓,一人给两族数留了名。
Ⅷ 加缪结论出处,《西西弗神话》(Le Mythe de Sisyphe,1942)末段,原文 Il faut imaginer Sisyphe heureux,通行中译「应当想象西西弗斯是幸福的」。il faut 表应当与必须,指向看待者的态度而非被看待者的状态。西西弗斯 123 黑洞的首倡者查无出处,中文世界通称流传,本书登记为民间流传,同白鼠题先例。
② 术语对照
Ⅰ 重排求差 把一个数的数字从大到小、从小到大各排一遍再相减的运算,卡普雷卡尔用以发现 6174 的那一套动作,英文称 Kaprekar's routine。
Ⅱ 不动点 对它做一次运算还回到它自己的数。6174 经重排求差仍是 6174,0 减 0 仍是 0,都是不动点。
Ⅲ 循环圈 一串数首尾相接转圈的状态,如两位数的 09→81→63→27→45→09,周期为圈上位置的个数。
③ 今夜习题 三道加一句征对,评论区见。
Ⅰ 第二夜习题一的答案已在正文发下。写程序复现那张步数分布表,九千个号码,看你的八千九百九十一个和我的对不对得上。
Ⅱ 三位排序六分支,当年当堂手敲半小时一遍过。四位的呢。不用数组,不调排序库,手写四数排序,重排求差,随便挑个数跑进 6174,体一次当年的半小时。
Ⅲ 五位数底下是三个圈。写程序把 89991 个五位数全部勘探一遍,找出这三个圈,再去找一份网上的资料对一对,看看错的是它还是你。
Ⅳ 随手写一个十位数,先猜它几步掉进 123,再跑。猜错的,说说你为什么猜大(或者猜小)了。
本书目录导航 上一篇:第二十夜 · 当数字遇见自己 下一篇:第二十二夜 · 数字迷雾 起点:卷首语·算法童话
版权声明:本文为作者原创,受著作权法保护。未经授权禁止转载、搬运、摘编、改编及任何形式的二次创作;个人学习引用请注明作者与原文出处。转载授权请联系作者(CSDN 私信)。侵权必究。