Advertisement
goakley

Bullseye

Apr 27th, 2013
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- Raises a number to an Int power
  2. (^!) :: Num a => a -> Int -> a
  3. (^!) x n = x^n
  4.  
  5. -- Takes the integer square root
  6. squareRoot :: Integer -> Integer
  7. squareRoot 0 = 0
  8. squareRoot 1 = 1
  9. squareRoot n =
  10.    let twopows = iterate (^!2) 2
  11.        (lowerRoot, lowerN) =
  12.           last $ takeWhile ((n>=) . snd) $ zip (1:twopows) twopows
  13.        newtonStep x = div (x + div n x) 2
  14.        iters = iterate newtonStep (squareRoot (div n lowerN) * lowerRoot)
  15.        isRoot r  =  r^!2 <= n && n < (r+1)^!2
  16.    in  head $ dropWhile (not . isRoot) iters
  17.  
  18.  
  19. -- Maps amount of paint and inner circle radius to a ring count
  20. circlesFromPaint :: Integer -> Integer -> Integer
  21. circlesFromPaint p r =
  22.     let underroot = (8*p) + (4*(r*r) - 4*r) + 1
  23.         introot   = squareRoot underroot
  24.         overfour  = introot - 2*r + 1
  25.         divbyfour = div overfour 4
  26.     in divbyfour
  27.  
  28.  
  29. -- Generate strings of the format "Case #n" starting from 1
  30. caseStrs :: [String]
  31. caseStrs = map ((++) "Case #" . show) [1..]
  32.  
  33.  
  34. -- Run the circlesFromPaint equation on a line of input
  35. runLine :: String -> Integer
  36. runLine line =
  37.     let info = fmap read (words line)
  38.         r = info !! 0
  39.         p = info !! 1
  40.     in circlesFromPaint p r
  41.  
  42.  
  43. -- Run the program
  44. main = do
  45.   cases <- getLine
  46.   contents <- getContents
  47.   mapM_ putStrLn (zipWith (\x y -> x ++ " " ++ show y) caseStrs (map runLine (lines contents)))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement