Guest User

Can Santa Save Christmas? - Haskell

a guest
Dec 31st, 2019
249
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Text.ParserCombinators.ReadP
  2.  
  3. class (Num a) => Time a where
  4.     toSeconds :: a -> Second
  5.     toDays :: a -> Day
  6.     addTimes :: a -> a -> Second
  7.     addTimes x y = toSeconds x + toSeconds y
  8.  
  9. data Day = Day Double
  10.     deriving Show
  11.  
  12. data Hour = Hour Integer
  13.     deriving Show
  14.  
  15. data Minute = Minute Integer
  16.     deriving Show
  17.  
  18. data Second = Second Integer
  19.     deriving Show
  20.  
  21. data CompleteTime = CompleteTime Hour Minute Second
  22.     deriving Show
  23.  
  24. data AllCompleteTimes = AllCompleteTimes [CompleteTime]
  25.  
  26. data CanSantaSaveChristmas = CanSantaSaveChristmas AllCompleteTimes
  27.  
  28. instance Show CanSantaSaveChristmas where
  29.     show (CanSantaSaveChristmas (AllCompleteTimes timeList)) | toDays (foldr (\elem acc -> elem + acc) (CompleteTime (Hour 0) (Minute 0) (Second 0)) timeList) > 1 = "false"
  30.                                                              | otherwise = "true"
  31.  
  32. instance Num Day where
  33.     (Day x) + (Day y) = Day (x + y)
  34.     (Day x) * (Day y) = Day (x * y)
  35.     abs (Day x) = Day (abs x)
  36.     signum (Day x) = Day (signum x)
  37.     fromInteger x = Day (fromInteger x)
  38.     negate (Day x) = Day (negate x)
  39.  
  40. instance Eq Day where
  41.     x == y = case (toSeconds x) of
  42.         Second xs -> case (toSeconds y) of
  43.             Second ys -> xs == ys
  44.  
  45. instance Ord Day where
  46.     x <= y = case (toSeconds x) of
  47.         Second xs -> case (toSeconds y) of
  48.             Second ys -> xs <= ys
  49.  
  50. instance Num Hour where
  51.     (Hour x) + (Hour y) = Hour (x + y)
  52.     (Hour x) * (Hour y) = Hour (x * y)
  53.     abs (Hour x) = Hour (abs x)
  54.     signum (Hour x) = Hour (signum x)
  55.     fromInteger x = Hour (fromInteger x)
  56.     negate (Hour x) = Hour (negate x)
  57.  
  58. instance Num Minute where
  59.     (Minute x) + (Minute y) = Minute (x + y)
  60.     (Minute x) * (Minute y) = Minute (x * y)
  61.     abs (Minute x) = Minute (abs x)
  62.     signum (Minute x) = Minute (signum x)
  63.     fromInteger x = Minute (fromInteger x)
  64.     negate (Minute x) = Minute (negate x)
  65.  
  66. instance Num Second where
  67.     (Second x) + (Second y) = Second (x + y)
  68.     (Second x) * (Second y) = Second (x * y)
  69.     abs (Second x) = Second (abs x)
  70.     signum (Second x) = Second (signum x)
  71.     fromInteger x = Second (fromInteger x)
  72.     negate (Second x) = Second (negate x)
  73.  
  74. addSeconds :: Second -> Second -> (Maybe Minute, Second)
  75. addSeconds x y = case (x + y) of
  76.     Second t | t < 60 -> (Nothing, Second t)
  77.              | otherwise -> (Just (Minute (t `div` 60)), Second (t `mod` 60))
  78.  
  79. addMinutes :: Minute -> Minute -> (Maybe Hour, Minute)
  80. addMinutes x y = case (x + y) of
  81.     Minute t | t < 60 -> (Nothing, Minute t)
  82.              | otherwise -> (Just (Hour (t `div` 60)), Minute (t `mod` 60))
  83.  
  84. instance Num CompleteTime where
  85.     (CompleteTime hrs1 mins1 ss1) + (CompleteTime hrs2 mins2 ss2) = case (addSeconds ss1 ss2) of
  86.         (Nothing, sSum) -> case (addMinutes mins1 mins2) of
  87.             (Nothing, minSum) -> CompleteTime (hrs1 + hrs2) minSum (ss1 + ss2)
  88.             (Just newHours, minSum) -> CompleteTime (hrs1 + hrs2 + newHours) minSum (ss1 + ss2)
  89.         (Just newMins, sSum) -> case (addMinutes mins1 (mins2 + newMins)) of
  90.             (Nothing, minSum) -> CompleteTime (hrs1 + hrs2) minSum sSum
  91.             (Just newHours, minSum) -> CompleteTime (hrs1 + hrs2 + newHours) minSum sSum
  92. -- I CAN'T BE BOTHERED TO IMPLEMENT THE REST OF NUM'S MISSING METHODS FOR COMPLETETIME AAAAAAAA
  93.  
  94. instance Time Day where
  95.     toSeconds (Day x) = Second . round $ 86400 * x
  96.     toDays x = x
  97.  
  98. instance Time Hour where
  99.     toSeconds (Hour x) = Second (3600 * x)
  100.     toDays (Hour x) = Day ((fromIntegral x) / 24.0)
  101.  
  102. instance Time Minute where
  103.     toSeconds (Minute x) = Second (60 * x)
  104.     toDays (Minute x) = Day ((fromIntegral x) / 1440.0)
  105.  
  106. instance Time Second where
  107.     toSeconds x = x
  108.     toDays (Second x) = Day ((fromIntegral x) / 86400.0)
  109.  
  110. instance Time CompleteTime where
  111.     toSeconds (CompleteTime hrs mins ss) = toSeconds hrs + toSeconds mins + toSeconds ss
  112.     toDays (CompleteTime hrs mins ss) = toDays hrs + toDays mins + toDays ss
  113.  
  114. satisfyIsNumber :: Char -> Bool
  115. satisfyIsNumber x = (x >= '0') && (x <= '9')
  116.  
  117. satisfyLessThanSix :: Char -> Bool
  118. satisfyLessThanSix x = (x >= '0' && x < '6')
  119.  
  120. parseSeconds :: ReadP Second
  121. parseSeconds = do
  122.     digit1 <- satisfy satisfyLessThanSix
  123.     digit2 <- satisfy satisfyIsNumber
  124.     return . Second . read $ [digit1, digit2]
  125.  
  126. parseMinutes :: ReadP Minute
  127. parseMinutes = do
  128.     digit1 <- satisfy satisfyLessThanSix
  129.     digit2 <- satisfy satisfyIsNumber
  130.     return . Minute . read $ [digit1, digit2]
  131.  
  132. parseHours2Digit :: ReadP Hour
  133. parseHours2Digit = do
  134.     digit1 <- satisfy satisfyIsNumber
  135.     digit2 <- satisfy satisfyIsNumber
  136.     return . Hour . read $ [digit1, digit2]
  137.  
  138. parseHours1Digit :: ReadP Hour
  139. parseHours1Digit = do
  140.     digit1 <- satisfy satisfyIsNumber
  141.     return . Hour . read $ [digit1]
  142.  
  143. -- want to parse 2 digits if possible, or else 1 digit
  144. parseHours :: ReadP Hour
  145. parseHours = parseHours2Digit <++ parseHours1Digit
  146.  
  147. parseCompleteTime :: ReadP CompleteTime
  148. parseCompleteTime = do
  149.     hrs <- parseHours
  150.     char ':'
  151.     mins <- parseMinutes
  152.     char ':'
  153.     ss <- parseSeconds
  154.     return (CompleteTime hrs mins ss)
  155.  
  156. getAllCompleteTimes :: [String] -> AllCompleteTimes
  157. getAllCompleteTimes strs = AllCompleteTimes (map (\completeTime -> fst . head $ (readP_to_S parseCompleteTime completeTime)) strs)
  158.  
  159. -- pointfree!!!!
  160. can_santa_save_christmas :: [String] -> CanSantaSaveChristmas
  161. can_santa_save_christmas = CanSantaSaveChristmas . getAllCompleteTimes
  162.  
  163. main :: IO ()
  164. main = do
  165.     putStrLn . show $ can_santa_save_christmas ["01:30:00", "02:15:00", "05:00:00"]
  166.     putStrLn . show $ can_santa_save_christmas ["12:00:00", "10:00:00", "2:00:00"]
  167.     putStrLn . show $ can_santa_save_christmas ["12:00:00", "10:00:00", "2:00:00", "00:10:00"]
Advertisement
Add Comment
Please, Sign In to add comment