CODE FESTIVALでgolfをして、その勢いで参加した。ruby内で6位取れたのでちょっと嬉しい。

【コードゴルフ】シンプル・ライフゲーム

問題

ライフゲームを実行して出力する問題。codeiqなので、テストケースは公開された3つだけ、実行は(brainfuckの処理系がバグってて個人的に恨みのある)企業版ideone。

提出コード

161byte ruby

n,h,w=(1..3).map{gets.to_i};a=*$<;n.times{a=(0...h).map{|y|(0...w).map{|x|{3=>?*,4=>a[y][x]}[(-3..5).map{|i|a[(y+i/3)%h][(x+i%3-1)%w]}.count ?*]||?.}*''}};puts a

xyを取っているのは縮めれるだろうなあと思っていたが、縮められず。

解説

整形。かなり常識的なコードである。 近傍9マスを眺めて*を数えて連想配列と||で更新。

n,h,w=(1..3).map{gets.to_i};
a=*$<;
n.times{
    a=(0...h).map{|y|
        (0...w).map{|x|
            {3=>?*,4=>a[y][x]}[
                    (-3..5).map{|i|a[(y+i/3)%h][(x+i%3-1)%w]
                }.count ?*
            ]||?.
        }*''
    }
};
puts a

反省とか

simanmanさんの解説を読んでの反省

  • 配列を2重にして正方向への超過をごまかす
    • 負のindexは後ろから数えた値を取れるのは知っていた
    • 考えれば思い付ける方法だった
  • 連想配列でなく配列で更新
    • これも気付くべき
  • Enumerable.count { |item| block }
    • 知らず
    • rubyに慣れてたら推測できそう
    • むしろ何故Enumerable.count(obj)は使えたのだろう
  • n,h,w,*f=*$<;
    • これはやってみたがhwが頻出する状況のためむしろ長くなった
  • gsub(/./)と文字の処理ごとにincrementされる変数
    • gsubに関して、perlで似たようなことしたのに思い付けず

闇の魔法のような技は特にないのだよなあ、という印象。 思い付けるべきだったなあ、と感じるような地味な短縮をきっちり全部やっているように見える。もちろんそのきっちり全部やるというのが難しいのだが。

私はgolfのidiomの知識も足りていないが、発想力といった競技プログラミングと共通するような部分で決定的に負けているようだ。