Skip to content

Instantly share code, notes, and snippets.

@yashigani
Last active December 26, 2015 06:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yashigani/7108582 to your computer and use it in GitHub Desktop.
Save yashigani/7108582 to your computer and use it in GitHub Desktop.
bowling score calculater on Haskell
import System.Environment (getArgs)
import Data.Char (digitToInt)
spare = (==) '/'
strike = (==) 'X'
updateBonus r (b1, b2)
| spare r = (b2 + 1, 0)
| strike r = (b2 + 1, 1)
| otherwise = (b2, 0)
scoreForThrow :: (Char, Int) -> Int
scoreForThrow (result, before)
| result == '-' = 0
| spare result = 10 - before
| strike result = 10
| otherwise = digitToInt result
scoreForThrowWithBonus :: (Char, Int, (Int, Int)) -> Int
scoreForThrowWithBonus (result, before, (b, _)) = sum [score, score * b]
where score = scoreForThrow (result, before)
scoringTotal :: (Char, Int, Int, (Int, Int)) -> (Int, Int, (Int, Int))
scoringTotal (result, total, before, bonus) = (total + this, current, updateBonus result bonus)
where current = scoreForThrow (result, before)
this = scoreForThrowWithBonus (result, before, bonus)
scoring :: String -> Int
scoring result = score
where (score, _, _) = foldl (\(t, b, bonus) r -> scoringTotal (r, t, b, bonus)) (0, 0, (0, 0)) result
resultFor10Frame (t1:ts)
| length (t1:ts) < 4 = (t1:ts)
| t1 == 'X' = resultFor10Frame ts
| otherwise = resultFor10Frame $ drop 2 (t1:ts)
bonusFor10Frame = foldl (\(t, (b1, b2)) r -> (t + scoreForThrow (r, 0) * b1, updateBonus r (b1, b2))) (0, (0, 0))
ajust results = -bonus where (bonus, _) = bonusFor10Frame $ resultFor10Frame results
bowlingScore results = sum $ map ($ results) [scoring, ajust]
{-
main = do
(results:_) <- getArgs
print $ bowlingScore results
-}
printTest (testCase, result) = do
putStrLn $ "test case: " ++ testCase
putStrLn $ if (bowlingScore testCase) == result then "CLEAR" else "FAIL"
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment