Skip to content

Instantly share code, notes, and snippets.

@shoooe
Created April 14, 2014 20:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save shoooe/10679793 to your computer and use it in GitHub Desktop.
Save shoooe/10679793 to your computer and use it in GitHub Desktop.
Solution to the Round 1A of Google's Code Jam (http://goo.gl/yX6J8).
import Data.List.Split (splitOn)
import Control.Monad ((>=>))
newtype Circle = Circle { circleRadius :: Double } deriving (Eq, Show)
newtype Paint = Paint { remainingMl :: Double } deriving (Eq, Show)
data Ring = Ring { ringRadius :: Double
, ringThickness :: Double
} deriving (Eq, Show)
-- circle area
circleArea :: Circle -> Double
circleArea (Circle r) = (r ** 2)
-- area of a ring
ringArea :: Ring -> Double
ringArea (Ring ra th) = (circleArea $ Circle ra) - (circleArea $ Circle (ra - th))
-- returns the next ring after the one passed
nextRing :: Ring -> Ring
nextRing (Ring r t) = Ring (r + t) t
-- with the given paint, tries to draw that ring and returns
-- the remaining paint or nothing
drawRing :: Paint -> Ring -> Maybe Paint
drawRing (Paint ml) r = if (rp >= 0) then Just (Paint rp) else Nothing
where rp = ml - a
a = ringArea r
-- returns the number of rings that can be drawn with
-- that amount of paint and given that the next ring to draw is
-- the one given
ringsPerPaint :: Paint -> Ring -> Int -> Int
ringsPerPaint t r c =
case (drawRing t r) of
Nothing -> 0
Just p -> ringsPerPaint p nr (c + 1)
where nr = (nextRing . nextRing) r
-- awaits for some input and process it into
-- a tuple of index, paint and starting ring
readInput :: Int -> IO (Int, Paint, Ring)
readInput i = do
ln <- getLine
let ls = splitOn " " ln
r = ((read $ head ls) :: Double)
t = ((read $ last ls) :: Double)
return (i, Paint t, Ring (r + 1) 1)
-- prints out the results
processOutput :: (Int, Paint, Ring) -> String
processOutput (i, p, r) = ("Case #" ++ (show i) ++ ": " ++ (show $ ringsPerPaint p r 0))
main :: IO ()
main = do
gn <- getLine
let n = (read gn :: Int)
ls <- mapM (fmap processOutput . readInput) [1..n]
mapM_ putStrLn ls
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment