野球のボールカウント

オフラインリアルタイムどう書く第三回の参考問題 #どう書く #yhpg #勉強会 #Ruby - Qiita

問題

野球のボールカウント・アウトカウントの遷移を計算する。(得点・ランナー・イニング の計算は不要)
ただし、ストライク・ボール・ファウル・ヒット・ピッチャーフライしかない。
細かいルールは下記の通り:

  • ストライクが3つになったらアウトが増え、ストライクとボールがゼロになる。
  • ボールが4つになったらフォアボールになり、ストライクとボールがゼロになる。アウトは増えない。
  • ヒットを打ったらストライクとボールがゼロになる。アウトは増えない。
  • ピッチャーフライを打ったらストライクとボールがゼロになり、アウトが増える。
  • アウトが3つになったら、アウト・ストライク・ボール全てゼロになる。
  • ファウルの場合、もともとストライクが1以下の場合はストライクが増え、ストライクが2の場合には変化なし。
  • 入力は "sbsfbhsshssbbffbbssbs" のように、ひとつながりの文字列として与えられる。
  • s, b, f, h, p がそれぞれ ストライク、ボール、ファウル、ヒット、ピッチャーフライ を意味する。
  • 出力は、アウト・ストライク・ボールの順にカウントをつなげたものをコンマで区切る。例を参照。
  • 不正入力には対処しなくてよい。
  • 最終回を超えることも考慮しなくてよい。

解答

def ballcount(seq):
    hist = []
    o, s, b = (0, 0, 0)
    for act in seq:
        if act == "s": # ストライク
            s += 1
            if s == 3: # スリーストライク
                s = 0
                o += 1
        elif act == "b": # ボール
            b += 1
            if b == 4: # フォアボール
                s = b = 0
        elif act == "h": # ヒット
            s = b = 0
        elif act == "p": # ピッチャーフライ
            s = b = 0
            o += 1
        elif act == "f" and s <= 1: # ファウル
            s += 1

        if o == 3: # スリーアウト
            o = s = b = 0

        hist.append("".join(map(str, [o, s, b])))
    return ",".join(hist)

やり方は
オフラインリアルタイムどう書く第三回の参考問題解答(Ruby) #どう書く #Ruby #勉強会 - Qiita
と同じ。そんなにてらった書き方をしてもしょうがない。

テスト

import nose
from nose.tools import eq_

def test_ballcount():
    eq_(ballcount('s'), '010')
    eq_(ballcount('sss'), '010,020,100')
    eq_(ballcount('bbbb'), '001,002,003,000')
    eq_(ballcount('ssbbbb'), '010,020,021,022,023,000')
    eq_(ballcount('hsbhfhbh'), '000,010,011,000,010,000,001,000')
    eq_(ballcount('psbpfpbp'), '100,110,111,200,210,000,001,100')
    eq_(ballcount('ppp'), '100,200,000')
    eq_(ballcount('ffffs'), '010,020,020,020,100')
    eq_(ballcount('ssspfffs'), '010,020,100,200,210,220,220,000')
    eq_(ballcount('bbbsfbppp'), '001,002,003,013,023,000,100,200,000')
    eq_(ballcount('sssbbbbsbhsbppp'), '010,020,100,101,102,103,100,110,111,100,110,111,200,000,100')
    eq_(ballcount('ssffpffssp'), '010,020,020,020,100,110,120,200,210,000')

if __name__ == "__main__":
    nose.main()