問題:http://nabetani.sakura.ne.jp/hena/orde13hextet/
実装リンク集:http://qiita.com/Nabetani/items/50cd05989b6e2812f879
なんかわかりにくい計算になってしまった。
def xy(ch)
shift=[0,1,1,2,2]
%w(a f j o s x).each_cons(2).with_index(0) do |(b, e),y|
return shift[y]+ch.ord - b.ord+y*1i if (b...e)===ch
end
raise "unexpected"
end
def neis(a)
me=xy("l")
"gkpqmh".chars.map do |ch|
xy(ch) - me + a
end
end
def normalize(sig)
Array.new(6){ |ix| sig.map{ |x| x.rotate(ix) }.sort }.min
end
def solve( src )
poses = src.chars.map{ |x| xy(x) }
neimap = poses.map{ |me|
neis(me).each.with_index(0).inject([]){ |acc, (n,ix)|
acc + [poses.include?(n) ? 1 : 0]
}
}
case normalize( neimap ).join.to_i(2)
when 288297; "B"
when 308016; "D"
when 295497; "I"
when 280872; "J"
when 279144; "L"
when 271656; "N"
when 845361; "O"
when 283176; "S"
when 279594; "Y"
when 295569; "Z"
else; "-"
end
end
if $0==__FILE__
DATA.all? do |line|
num, src, expected = line.split(/\s+/)
actual = solve( src )
ok = actual==expected
p [ ok ? "ok" : "**NG**", num, src, expected, actual ]
ok
end.tap{ |all_ok| puts( all_ok ? "everythin is okay" : "SOMETHING WRONG") }
end
__END__
0 glmq B
1 fhoq -
2 lmpr N
3 glmp Y
いつもどおり、テストケースの大半は省略。
case
〜when
がややマジカルだけど、現物合わせでこんな感じ。
マス目の近傍の情報を収集して正規化すれば行けるよね、という実装。
会場で示したものは配列を使っていたけど、複素数に変更してみた。スッキリするね。
この計算で本当に正しいの? 証明できる? と言われるとちょっと自信がないみたいなことを会場では言ったけど、証明可能だと思う。