Perlでは
$ perl -E 'say "love" & "mine"' life
Rubyでは
$ irb irb(main):001:0> '愛'.unpack("B*") => ["111001101000010010011011"] irb(main):002:0> '生'.unpack("B*") => ["111001111001010010011111"]
英語にしてみましょうか.
irb(main):003:0> "love".unpack("B*") => ["01101100011011110111011001100101"] irb(main):004:0> "love".split(//).map{|s|s.unpack("B*")}.join(" ") => "01101100 01101111 01110110 01100101" irb(main):005:0> "life".split(//).map{|s|s.unpack("B*")}.join(" ") => "01101100 01101001 01100110 01100101"
ここから何が言えるのかというと,
- '生'のビット列が'愛'のビット列をカバーするのに対し,
- "love"のビット列が"life"のビット列をカバーする
のです.ここで,ビット列xがビット列yを「カバー(網羅)」するというのは,yの任意のビット位置に対して,そのビットが1ならxの同じ位置のビットも1であることとします.もちろん,yのある位置のビットが0のときは,xの同じ位置のビットは1でも0でもかまいません.
ということで,「"love" & 何か == "life"」という関係式が成り立つような,英単語を見つけてみましょう.
各文字は,次のようになります.
- 1文字目は,011011??*1なので,lmnoのいずれか
- 2文字目は,011?1001なので,iyのいずれか
- 3文字目は,0110?11?なので,fgnoのいずれか
- 4文字目は,011??1?1なので,egmouwのいずれか
ここまで情報を得たところで,スクリプトにします.
#!/usr/bin/env ruby # -*- coding: utf-8 -*- # love-to-life.rb class String def &(other) raise unless String === other raise unless bytesize == other.bytesize unpack("C*").zip(other.unpack("C*")).map{|a, b| a & b}.pack("C*") end end love = "love" "lmno".each_char do |a| "iy".each_char do |b| "fgno".each_char do |c| "egmouw".each_char do |d| s = a + b + c + d puts "%s & %s == %s" % [love, s, love & s] end end end end
「"love" & 何か == "life"」を満たす「何か」は,192通りあることを確認しました.
目を通したところ,「何か」がまともな単語になっているのは,
- love & life == life
- love & line == life
- love & mine == life
- love & nine == life
あたりです.しかしこれだけ頑張ってみても,「生 & 死 == 愛」の美しさにはかないません.
ちょうど192通りなのを別の方法で確認
#!/usr/bin/env ruby # -*- coding: utf-8 -*- # love-to-life-bruteforce.rb class String def &(other) raise unless String === other raise unless bytesize == other.bytesize unpack("C*").zip(other.unpack("C*")).map{|a, b| a & b}.pack("C*") end end love = "love" life = "life" abc = "abcdefghijklmnopqrstuvwxyz" abc.each_char do |a| abc.each_char do |b| abc.each_char do |c| abc.each_char do |d| s = a + b + c + d x = love & s if x == life puts "%s & %s == %s" % [love, s, x] end end end end end
どちらのスクリプトも,出力のSHA-1ハッシュ値はf221c835becf4c870fcf80fd7bcf0ef300882052となりました.
(最終更新日時:Tue Apr 3 06:12:51 2012ごろ.「カバー(網羅)」の説明を修正しました.)
*1:英小文字に限定します.ビット列としては,01100001から01111010までです.そのため,011111??というのは考えません.