Akihito Ikeda

ボウリングのスコア計算プログラムを書いた

posts/2023-01-18diary

最近会社にジョインしたパートナーが研修課題で「ボウリングのスコア計算プログラム」にチャレンジしているらしい。聞くところによるとスコア計算方法には新旧があって、旧ルールが結構複雑らしい。たしかに実際ボウリングしてても投げた後に前のフレームの点数が確定したりして、なにがなんだかよくわからんもんなあ。でもたぶんその要素があるからよりゲームが盛り上がるんだとは思うけど。ぱっと見でどっちが優勢かわからない感じとかワンチャン逆転あるかもと思わせる感じとか。

とにかく自分も計算方法をよく知らなかったし当然プログラムを書いたことはなかったので、いい機会だからRubyで書いてみた。

旧ルールのミソはこのあたり。

  • スペアだったら次の1投の点を加算する
  • ストライクだったら次の2投の点を加算する
  • 10フレーム目は、1投目がストライクか2投目がスペアなら、3投目が投げられる

確かにこれはむずいなあ〜〜〜。参考回答とかよくありそうな感じにしてもしょうがないので、ニュアンスを込めて書いた。

https://gist.github.com/akht/693f0cbde58e9a754f641a341c125edf

scores = ARGV[0].strip.split(',').flat_map { |p| p == 'X' ? [10, nil] : p.to_i }
frames = scores.each_slice(6).flat_map { |n| n.size.even? ? n.each_slice(2).to_a : [n] }

total = (0..9).inject(0) do |acc, i|
  current_frame, next_frame, after_next_frame = frames.slice(i, 3)
  bonus = [current_frame.first == 10, current_frame.compact.sum == 10].sum { |i| i ? 1 : 0 } # strikeは2投分,spareは1投分
  acc + current_frame.compact.sum + [next_frame, after_next_frame].flatten.compact.take(bonus).sum
end

puts total
❯ ruby bowling.rb 6,3,9,0,0,3,8,2,7,3,X,9,1,8,0,X,6,4,5
139

❯ ruby bowling.rb 0,10,1,5,0,0,0,0,X,X,X,5,1,8,1,0,4
107

❯ ruby bowling.rb X,X,X,X,X,X,X,X,X,X,X,X
300

ほんとにこのプログラムが正しいかわからんので週末ラウンドワンでテストしてきます。

© Akihito Ikeda - Last update 04.03.2024 00:58.