読者です 読者をやめる 読者になる 読者になる

ボールカウント(野球)を Groovy で

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

Yokohama.groovy で、これを解いてみました。
なんか、すげー手続き型っぽくなってしまった。
完成した後、Groovy で解いてた人の洗練されたコード見て、こういうの思い浮かぶようになりたいと思いました。
まだまだですなー。

package doukaku
 
import spock.lang.Specification
import spock.lang.Unroll
 
class BaseballScoreSpeck extends Specification {
    BaseballScore sut;
 
    def setup() {
        sut = new BaseballScore()
    }
 
    @Unroll
    def "ノーカウントからの #input は #result が返る"() {
        expect:
        sut.ballCount(input) == result
 
        where:
        input   |result
        's'     |'010'
        'b'     |'001'
        'f'     |'010'
        'p'     |'100'
        'h'     |'000'
        'ss'    |'010,020'
        'sss'   |'010,020,100'
        'sbss'   |'010,011,021,100'
        'bbbb'  |'001,002,003,000'
        'ssh'   |'010,020,000'
        'bbp'   |'001,002,100'
        'ssf'   |'010,020,020'
        's'  |'010'
        'sss'	|'010,020,100'
        'bbbb'	|'001,002,003,000'
        'ssbbbb'	|'010,020,021,022,023,000'
        'hsbhfhbh'	|'000,010,011,000,010,000,001,000'
        'psbpfpbp'	|'100,110,111,200,210,000,001,100'
        'ppp'	|'100,200,000'
        'ffffs'	|'010,020,020,020,100'
        'ssspfffs'	|'010,020,100,200,210,220,220,000'
        'bbbsfbppp'	|'001,002,003,013,023,000,100,200,000'
        'sssbbbbsbhsbppp'	|'010,020,100,101,102,103,100,110,111,100,110,111,200,000,100'
        'ssffpffssp'	|'010,020,020,020,100,110,120,200,210,000'
 
    }
}
package doukaku
 
class BaseballScore {
    String ballCount(String s) {
        def out = 0
        def strike = 0
        def ball = 0
        def result = []
 
        s.each {
            switch (it) {
                case 's':
                    if (++strike == 3) {
                        strike = ball = 0
                        ++out
                    }
                    break
                case 'b':
                    if (++ball == 4) strike = ball = 0
                    break
                case 'f':
                    if (strike < 2) ++strike
                    break
                case 'p':
                    ++out
                    strike = ball = 0
                    break
                case 'h':
                    strike = ball = 0
                    break
            }
            if (out == 3) out = strike = ball = 0
 
            result << "$out$strike$ball"
        }
        result.join(',')
    }
}