某FizzBuzzの記事を読んでたら急にFizzBuzzを書きたくなりました。
Rubyです。
eval [<<"".chomp.tr(" - ", "0-9a-f")].pack("H*")
1
2
Fizz
4
Buzz
Fizz
7*** しょうりゃく ***
94
Buzz
Fizz
97
98
Fizz
Buzz
ごく普通のFizzBuzzです。
ただし、上のソースをコピペしても絶対に動きません。
コピペじゃ無理なのでGitHubにアップロードしました。
下のリンクから右クリック等で ファイルを直接ダウンロードして 実行してください。
(下のリンクからでも、コピペじゃたぶん無理です)
あと環境によっても動かないかもしれません。
以下の環境で動作確認しました。
Mac OS X 10.10.2
Ruby 2.2.0p0
説明
予想付くかもですが、空白の部分にソースを書き込んであります。
見えてる部分はヒアドキュメント<<""
で空行までの文字列(空白)を取り出し、元の文字列に直してeval
してるだけです。
一番上のソースは空白の部分を削除してるので、動くわけがありません。
(どうせ見えないし、コピペしても動かないからいいよね。)
スペースってたくさんあるので、ちょっとした文字列なら隠せます。
さっきのソースのeval
をはずしてputs
にすると以下のソースが出てきます。
(1..100).zip(([nil]*2<<:Fizz).cycle,([nil]*4<<:Buzz).cycle){|n,*z|puts z.any?&&z*""||n}
元は以下のようなソースです。
空白が小さいほうがバレにくいので上のように短くしました。
fizz = [nil] * 2 << :Fizz
buzz = [nil] * 4 << :Buzz
(1..100).zip(fizz.cycle, buzz.cycle) do |n, *f|
puts f.any? ? f.join : n
end
空白に変換するには、見えてる部分のソースと逆のことをやるだけ。
src = '(1..100).zip(([nil]*2<<:Fizz).cycle,([nil]*4<<:Buzz).cycle){|n,*z|puts z.any?&&z*""||n}'
hex = src.unpack("H*")[0] # 16進数にする
#=>"28312e2e313030292e7a697028285b6e696c5d2a323c3c3a46697a7a292e6379636c652c285b6e696c5d2a343c3c3a42757a7a292e6379636c65297b7c6e2c2a7a7c70757473207a2e616e793f26267a2a22227c7c6e7d"
spaces = hex.tr("0-9a-f", " - ") # 16種のスペースで置き換える
#=> " "
空白の文字列はコピペじゃうまく扱えなかったりするので、パイプでファイルに書き出すとかしたほうがいいかも。
スペースは通常の半角・全角に加えて、U+2000
〜U+200D
を使いました。
連番なので扱いやすいです。
[*"\u2000".."\u200d"] + [" ", " "]
spaces = [*"\u2000".."\u200d"] + [" ", " "]
spaces.size #=> 16
spaces.uniq.size #=> 16
# 「/\s/」に引っかかるのは普通の半角スペースだけ。
spaces.grep(/\s/)
#=> [" "]
# 「/[[:space:]]/」にはほとんど引っかかる。引っかからないスペースは3つ。
spaces.reject{|s| /[[:space:]]/ === s }.map{|s| s.ord.to_s(16)}
#=> ["200b", "200c", "200d"]
合わせてちょうど16種類なので16進数を表現できます。
文字列を16進数にすれば完全に隠蔽できます。
tr
に渡している文字列は以下のようになってます。
見えないので補足しないと何がなんだかわかりませんね。
spaces = "\u2000" + "-" + "\u200d" + " " + " "
スペースの種類はWikipediaにたくさん。
これらの空白は変数名としても使えたので、頭が痛くなるようなソースはいくらでも書けそうです。
全部試したわけではないですが。
= 1
puts
#=> 1
追記
ってかこれFizzBuzz関係ない。