2013/10/28

ボウリングのスコアを計算するスクリプトをHaskellで書いてみた

某日某所にてボウリングのスコアを計算するプログラミングフィッシュボウルが行われていたのですが、 都合が付かずに参加できなくてくやしい思いをしたので、同じ課題をHaskellで書いてみました。

問題

ボウリングのスコアシートの上の部分が与えられたときに、その最終スコアを計算せよ。

入力

  • ボウリングのスコアシートの上の部分を示す文字列

20文字程度長さのの文字列で、入力として可能な文字は次の通りです。

  • - はガター
  • / はスペア
  • X はストライク
  • 19 は倒したピン数

出力

ゲームのスコアを表す整数

入出力例

  • 入力「’XXXXXXXXXXXX’」は全ストライクなので、出力は「300」
  • 入力「9-9-9-9-9-9-9-9-9-9-」は全フレームで「1投目で9本倒すが2投目はガター」なので、出力は「90」

なお、ボウリングのスコア計算法は数多くのサイトで紹介されているので、ここでは割愛します。自分では次のページを参照しました。

Haskelltの回答例

  • スペアの処理にちょっと手間がかかります
  • それによって最終フレームがややこしくなりました
  • フレームごとに分けるとストライクのボーナスである次の2投分の計算がややこしくなるので避けたほうがよいです
score' :: Int -> Char -> Int
score' _ '-' = 0
score' b '/' = 10 - b
score' _ 'X' = 10
score' _ '1' = 1
score' _ '2' = 2
score' _ '3' = 3
score' _ '4' = 4
score' _ '5' = 5
score' _ '6' = 6
score' _ '7' = 7
score' _ '8' = 8
score' _ '9' = 9
score = score' 0
calc :: Int -> [Char] -> Int
calc 10 ('X':'X':x:[]) = 20 + (score x)
calc 10 ('X':x:y:[]) = 10 + (score x) + (score y)
calc 10 (x:'/':y:[]) = 10 + (score y)
calc 10 (x:y:[]) = (score x) + (score y)
calc f ('X':xs) = 10 + b1 + b2 + (calc (f+1) xs)
where b1 = score (head xs)
b2 = score' b1 (head (tail xs))
calc f (x:'/':xs) = 10 + b1 + (calc (f+1) xs)
where b1 = score (head xs)
calc f (x:y:xs) = t1 + t2 + (calc (f+1) xs)
where t1 = score x
t2 = score' t1 y
printTest (testCase, result) = do
putStrLn $ (if (calc 1 testCase) == result then "CLEAR" else "FAIL") ++ " " ++ testCase
testCases = [
("9-9-9-9-9-9-9-9-9-9-", 90),
("X54----------------", 28),
("1/5-----------------", 20),
("1/5-2/-/8-----------", 56),
("------XX----------", 30),
("------XXX--------", 60),
("XXXXXXXXXXXX", 300),
("--------------------", 0),
("-------------------/5", 15),
("------------------X54", 19),
("5/5/5/5/5/5/5/5/5/5/5", 150)
]
test = mapM_ printTest testCases
main = test
view raw bowling.hs hosted with ❤ by GitHub

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。