Hatena::ブログ(Diary)

わさっき RSSフィード

2012年03月29日

[] love & mine == life

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??というのは考えません.