Skip to content

Instantly share code, notes, and snippets.

@gfixler
Last active Aug 29, 2015
Embed
What would you like to do?
import Control.Applicative ((<|>))
type Bonus = Int
data Frame = Roll Int | Frame Int Int | Spare Int | Strike deriving (Show)
badnum :: Int -> Bool
badnum n = n < 0 || n > 10
strike, spare, frame :: [Int] -> Maybe (Frame, Bonus, [Int])
strike (10:a:b:rs) = Just (Strike, a + b, a : b : rs)
strike (10:rs) = Just (Strike, 0, rs)
strike rs = Nothing
spare (a:b:rs) | a + b == 10 = Just (Spare a, case rs of (c:cs) -> c
[] -> 0, rs)
spare rs = Nothing
frame (a:b:rs) | badnum (a+b) = Nothing
| a == 10 = Nothing
| otherwise = Just (Frame a b, 0, rs)
frame _ = Nothing
score1 :: [Int] -> Maybe (Frame, Bonus, [Int])
score1 rs = strike rs <|> spare rs <|> frame rs
scores :: [Int] -> Either String [(Frame, Bonus)]
scores = scores' (Right [])
where scores' acc rs = case score1 rs of
Just (f,b,[]) -> fmap (reverse . ((f,b):)) acc
Just (f,b,rs') -> scores' (fmap ((f,b):) acc) rs'
Nothing -> Left $ "Illegal next roll(s): " ++ show rs
-- example game from https://github.com/hontas/bowling-game-kata
exampleGame = scores [10,9,1,5,5,7,2,10,10,10,9,0,8,2,9,1,10]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment