Tetris in anagol
kskさんに大敗。
kskさんのコードがやってることとやってることがほとんど同じはずのボクのコードがこんなにも長いのはどうしてだろーわー。
やってることはお互いに、
- "#"を四つ見つけて、それをスペースに置き換える
- さらにそこからN文字先のスペースを"#"にかえる
- "#"だけで構成されている行を消すという
まあつまりそういうことなんですが。向こうのほうがうまいなー。
入力をひとつの文字列として$_に代入したあとで、最初の二つをeval部分で処理しています。
eval"sub /#(.{%d}) /m,' \\1#';"%"x\x83A"[~/#//4]*4
~/#//4は、「($_ =~ /#/)/4」で、最初の#のある位置を4で割ってます。これは各サンプルに対して[0,2,1]を返します。
"x\x83A"は、各サンプルで#を落とす「距離」が埋め込んであって、120,131,65が入ってます。一行の長さ×行数-1で、11*11-1,11*12-1,11*6-1です。
たとえば最初のインプットなら、結局は…
sub /#(.{120}) /m,' \\1#' sub /#(.{120}) /m,' \\1#' sub /#(.{120}) /m,' \\1#' sub /#(.{120}) /m,' \\1#'
となって、4つの#に対して#の落下が処理されるわけです賢いなー賢いなー。
次は#だけで構成されている行を消して、消した分だけ足さないといけません。こいつはgrepがやってます。
gsub(/ #+$/m){puts" "*10}
正規表現で#だけの行を見つけて、そのたびにputs" "*10してるわけですが、putsの返すnilがto_sによって""になるので、置換されてまあうまいこと消えるという。
あとは落下と消去の操作をされた$_をprintで出力するだけ。
うーんsubの置換だけで落としちゃうのがポイントだったんだなー。