読者です 読者をやめる 読者になる 読者になる

SIN@SAPPOROWORKSの覚書

C#を中心に、夜な夜な試行錯誤したコードの記録です。

ランダム関数による hello world 

stackoverflowの3日の記事でJavaによる「hello workd」なプログラムについて書かれてました。
Why does this code print “hello world”?

[java]
System.out.println(
randomString(-229985452) + " " + randomString(-147909649));

public static String randomString(int i){
Random ran = new Random(i);
StringBuilder sb = new StringBuilder();
for (int n = 0; ; n++){
int k = ran.nextInt(27);
if (k == 0)
break;
sb.append*1;
}
return sb.toString();
}
[/java]

ちょっと???なコードですが、実行してみると確かにhello worldが表示されてます。

記事を読んでみると、すぐに分かりますが、初期化に使用するSeed値で疑似乱数が規則的に現れることを利用して、hello\0とworld\0のパターンになるSeed値を指定しているだけでした。


8  + 96 = 104 --> h
5  + 96 = 101 --> e
12 + 96 = 108 --> l
12 + 96 = 108 --> l
15 + 96 = 111 --> o

23 + 96 = 119 --> w
15 + 96 = 111 --> o
18 + 96 = 114 --> r
12 + 96 = 108 --> l
4  + 96 = 100 --> d

Javaと.NETでは、当然Randomの実装が違いますので、同じコードを実行してみても当然ながら「hello world」にはなりません。

ってことで、.NETのRandomでも同じパターンが無いか検索してみました。


class Program {
    private static void Main(){
        for (var i = Int32.MinValue; i < Int32.MaxValue; i++){
            SearchHello(i);
            SearchWorld(i);
        }
    }
    static void SearchHello(int i){
        //8,5,12,12,15,0を検索する
        Random ran = new Random(i);
        int n = ran.Next(27);
        if (n - 3 != ran.Next(27)) return;
        if (n + 4 != ran.Next(27)) return;
        if (n + 4 != ran.Next(27)) return;
        if (n + 7 != ran.Next(27)) return;
        if (n - 8 == ran.Next(27)){
            Console.WriteLine(string.Format(
                "find [Hello] {0} {1} {2} {3} {4}   {5}"
                , n , n-3,n+4,n+4,n-3,i));
            }
        }
    static void SearchWorld(int i) {
        //23,15,18,12,4,0を検索する
        var ran = new Random(i);
        var n = ran.Next(27);
        if (n - 8 != ran.Next(27)) return;
        if (n - 5 != ran.Next(27)) return;
        if (n - 11 != ran.Next(27)) return;
        if (n - 19 != ran.Next(27)) return;
        if (n - 23 == ran.Next(27)) {
            Console.WriteLine(String.Format(
                "find [World] {0} {1} {2} {3} {4} {5}"
                , n, n - 3, n + 4, n + 4, n - 3, i));
        }
    }
}

結果は、下記のような感じ・・・・


find [World] 26 23 30 30 23 -2055333802
find [World] 24 21 28 28 21 -1992937727 // <=これと
find [Hello] 18 15 22 22 15   -1986525298
find [Hello] 15 12 19 19 12   -1979516206
find [Hello] 16 13 20 20 13   -1976927369
find [Hello] 8 5 12 12 5   -1956515490
find [Hello] 13 10 17 17 10   -1947267267
find [Hello] 19 16 23 23 16   -1935430207
find [Hello] 14 11 18 18 11   -1896172176
find [Hello] 9 6 13 13 6   -1777252898  // <=これを使う
find [Hello] 15 12 19 19 12   -1765415838
find [World] 24 21 28 28 21 -1730331105
find [Hello] 10 7 14 14 7   -1726157807
find [Hello] 16 13 20 20 13   -1714320747
find [World] 24 21 28 28 21 -1681824851

一応パターンが見つかったので、C#版です。

*1:char)('`' + k