概要
原著者の許諾を得て翻訳・公開いたします。
- 英語記事: Idiosyncratic Ruby: ½ Kilo of SHA256
- 原文公開日: 2017/01/05
- 著者: Jan Lelis
- サイト: Idiosyncratic Ruby
Ruby: 500バイトで書けるSHA256生成スクリプト(翻訳)
STDIN(標準入力)のSHA 256ハッシュサムを生成できるRubyコードは何バイト(=ASCII文字数)あれば書けるでしょうか?
答え: 500バイト1
q,z=[3,2].map{|t|i=l=1;(2..330).select{i-1<(l*=i)%i+=1}.map{|e|(e**t**-1*X=2**32).to_i&X-=1}}
s=proc{|n,*m|a=0
m.map{|e|a^=n>>e|n<<32-e}
a}
i=$<.read.b<<128
(i+"\0"*(56.-(w=i.size)%64)+[~-w*8].pack('Q>')).gsub(/.{64}/m){w=$&.unpack'N*'
y=z
64.times{|i|i>15&&w[i]=w[i-16]+(s[v=w[i-15],7,18]^v>>3)+w[i-7]+(s[w[i-2],17,19]^w[i-2]>>10)&X
f=y[7]+s[u=y[4],6,11,25]+(u&y[5]^~u&y[6])+q[i]+w[i]
y=[f+s[y[0],2,13,22]+(y[0]&y[1]^y[0]&y[2]^y[1]&y[2])&X]+y
y[4]=y[4]+f&X}
z=z.zip(y).map{|a,b|a+b&X}}
$><<'%.8x'*8%z
上は、とあるコードゴルフコンテスト(現在はありません)に送信されたコードをベースにしており、これよりもさらに短いものも送信されていたので、これをさらに短くすることも可能です。プルリクを探してみてください!
テストスクリプト
上のコードをsha256.rb
というファイルに保存して、同じディレクトリに以下のテストスクリプトを作成します。
# encoding: utf-8
require "digest/sha2"
require "open3"
TEST_SCRIPT = "ruby sha256.rb"
TEST_CASES = [
"Idiosyncrätic Ruby",
"\n",
"",
"a"*6000,
"a"*57
]
TEST_CASES.each{ |test_case|
expected = Digest::SHA256.hexdigest(test_case)
actual = nil
Open3.popen3(TEST_SCRIPT){ |in_, out,|
in_ << test_case
in_.close
actual = out.read
}
if expected == actual
print "."
else
$stderr.puts "Fail:
- Expected: #{expected.inspect}
- Actual: #{actual.inspect}
"
end
}
参考
- Golfing Basics -- Rubyでコードゴルフするときのコツが解説されています
- Anarchy Golf
関連記事
-
上のコードは実際には501バイトですが、
"\0"
を本物のnullバイトに置き換えることもできます。 ↩