オフラインでリアルタイムに「どう書く」をやるイベント第二回
http://atnd.org/events/30900
の、参考問題
http://qiita.com/items/9d80de41903775296ca6
の解答例。rubyで。
#!ruby
#encoding:utf-8
def bitrot( q )
len=q.to_i
bits=q.split(':')[1].to_i(16)
offset=(len&1)*3
rotated_bits=(0...len*len).map{ |pos|
y,x=pos.divmod(len)
bits[(len-x-1)*len+y+offset]<<(pos+offset)
}.inject( &:| )
"%d:%0*x"%[len,(len*len+offset)/4,rotated_bits]
end
DATA.each{ |line|
q,expected=line.chomp.split(/\s+→\s+/)
r=bitrot q
puts(("%s → %s"%[q,r])+(r==expected ? '' : '**NG**'))
}
__END__
3:5b8 → 3:de0
1:8 → 1:8
2:8 → 2:4
2:4 → 2:1
2:1 → 2:2
3:5d0 → 3:5d0
4:1234 → 4:0865
5:22a2a20 → 5:22a2a20
5:1234567 → 5:25b0540
6:123456789 → 6:09cc196a6
7:123456789abcd → 7:f1a206734b258
7:fffffffffffff → 7:ffffffffffff8
7:fdfbf7efdfbf0 → 7:ffffffffffc00
8:123456789abcdef1 → 8:f0ccaaff78665580
9:112233445566778899aab → 9:b23da9011d22daf005d40
ruby なので、多倍長整数がそのまま使える。
divmod を初めて使った。役に立つのはこういうシチュエーションだよね、と思う。
ややトリッキーな offset=(len&1)*3
は、余る bit の数の計算。
紙の上で計算してみると、一辺の長さが偶数なら余らず、奇数なら3bit 余る。
ということで、len%2==0 ? 0 : 3
でもいいんだけど、ちょっとゴルフな気分で。