然后这个问题下面还有个评论,让我看到了另外一种打开方式:
你能指定打印出 hello world,那么理论上我也能指定打出其他的单词。
比如这个老哥就打了一个短语:the quick browny fox jumps over a lazy dog.
如果从字面上直译过来,那么就是“敏捷的棕色狐狸跨过懒狗”,好像也是狗屁不通的样子。
但是,你知道的,我的 English 水平是比较 high 的,一眼就看出这个短语在这里肯定不简单。
于是查了一下:
你看学沙雕技术的时候还顺便丰富了自己的英语技能,一举多得,这一会还不得在文末给我点个赞、点个“在看”啥的?
看完这个老哥的 quick brown fox 示例之后,我又有一点新想法了。
既然它能把所有的字母都打出来,那我是不是也能把我想要的特定的短语也打出来呢?
比如 i am fine thank you and you 这样的东西。
而查找指定单词对应的 seed 这样的功能的代码,在这个问题的回答中,已经有“好事之人”帮我们写出来了。
我就直接粘过来,你也可以直接拿去就用:
public static long generateSeed(String goal, long start, long finish) { char[] input = goal.toCharArray(); char[] pool = new char[input.length]; label: for (long seed = start; seed < finish; seed++) { Random random = new Random(seed); for (int i = 0; i < input.length; i++) pool[i] = (char) (random.nextInt(27) + '`'); if (random.nextInt(27) == 0) { for (int i = 0; i < input.length; i++) { if (input[i] != pool[i]) continue label; } return seed; } } throw new NoSuchElementException("Sorry :/"); }
那么我要找前面提到的短语,就很简单了:
而且运行的时候我明显感觉到,在搜索“thank”这个单词的时候,花了很多时间。
为什么?
我给你讲一个故事啊,只有一句话,你肯定听过:
只要时间足够漫长,猴子都能敲出一部《莎士比亚》。
我们这里 generateSeed 方法,就相当于这个猴子。而 thank 这个单词,就是《莎士比亚》。
在 generateSeed 方法里面,通过 26 个字母不断的排列组合,总是能排列出 “thank” 的,只是时间长短而已。
单词越长,需要的时间就越长。
比如我来个 congratulations,这么长的单词,我从 00:05 分,跑了 23 个小时都还没跑出来:
源码
你以为我要带你读源码?
不是的,我主要带你吃瓜。
首先,看一下的 Random 无参构造函数:
好家伙,原来也是套个了个“无参”的壳而已,实际上还是自己搞了一个 seed,然后调用了有参构造方法。
只是它构建的时候加入了“System.nanoTime()”这个变量,让 seed 看起来随机了一点而已。
等等,前面不是还有一个“seedUniquifier”方法吗?
这个方法是这样的:
好家伙,看到第一眼的时候我头都大了,这里面有两个“魔法数”啊:
181783497276652981L
8682522807148012L
这玩意也看不懂啊?
遇事不决,stackoverflow。
一搜就能找到这个地方:
论文中提到的数是这样的: