ESM オフラインリアルタイムどう書くで出題された「行列のできるラーメン屋」という問題を解いてみた。
問題 : https://gist.github.com/mtsmfm/4b8ffb53ffac055f5843
記事 : http://mtsmfm.github.io/2015/10/22/esm-doukaku.html
このページ以外の実装例(気づいた順)は下表のとおり。
私の実装はだいぶスクロールした下の方に書きましたよ。
def try_sit( chairs, cus )
n=cus[0]
pos = 8.times.find{ |x| (x...(x+n)).all?{ |y| chairs[y%8]==0 } }
if pos
(pos...(pos+n)).each{ |x| chairs[x%8]=1 }
cus.shift
end
end
def progress( chairs )
chairs.size.times do |ix|
chairs[ix] = (chairs[ix]+1) % 4 if chairs[ix]!=0
end
end
def solve_impl( chairs, cus )
loop do
try_sit( chairs, cus )
return chairs if cus.empty?
progress(chairs)
end
end
def solve(s)
ch=solve_impl( [0]*8, s.chars.map( &:to_i ) )
ch.map{ |x| x==0 ? 0 : 1 }.join
end
DATA.map do |line|
num, src, expected = line.split( /\s+/ )
actual = solve( src )
ok = actual == expected
puts [num, (ok ? "ok" : "***NG***"), src, expected, actual].join(" ")
ok
end.all?{ |x| puts( x ? "all okay!" : "some failed" ) }
__END__
1 3316 11111110
2 3342153 11111111
テストデータの大半は省略。
30分ぐらいだったと思う。計るの忘れてましたすいません。
副作用のあるメソッドばかりで汚い感じ。これならクラスにしたほうがよかったか。
ソースコード内に 8
とか平気で書いていてすいません。マジカルな感じで。
chars と chairs が見間違えやすくて混乱するかも。
実装としては順当なつもりだけど、どうかなぁ。
C/C++ では当たり前にできる true/false を 1/0 に変換する計算が、ruby だと expr ? 1 : 0
になってしまうのが不満なんだけど、もっといい方法があるのかなぁ。
出力が2進数っぽかったので、ビット演算をして欲しいのかなと思ったんだけど、気にせず普通に計算してみた。
try_sit の中の計算がやや DRY じゃない感じ。検査のためのループと代入のためのループが同じなので、冗長かもしれない。