Bohtvaroh

Fridays 13' finder

Jul 13th, 2012
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Control.Applicative ((<*>))
  2.  
  3. type Year = Int
  4. type Date = Int
  5.  
  6. data Month     = Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec
  7.                deriving (Bounded, Enum, Eq, Ord, Show)
  8. data DayOfWeek = Sun | Mon | Tue | Wed | Thu | Fri | Sat
  9.                deriving (Bounded, Enum, Eq, Ord, Show)
  10. data Day       = Day Year Month Date DayOfWeek
  11.                deriving (Show)
  12.  
  13. buildFridays13From :: Year -> DayOfWeek -> [Day]
  14. buildFridays13From year dow =
  15.   filter (\(Day _ _ d dof) -> and [d == 13, dof == Fri]) days
  16.   where days = buildFrom year dow
  17.  
  18. buildFrom :: Year -> DayOfWeek -> [Day]
  19. buildFrom year dow = iterate getNextDay (Day year Jan 1 dow)
  20.  
  21. getNextDay :: Day -> Day
  22. getNextDay (Day year month date dayOfWeek) =
  23.   let (_, dof)           = wrapSucc dayOfWeek maxBound minBound
  24.       (dateOverflow, d)  = wrapSucc date (getDaysInMonth year month) 1
  25.       (monthOverflow, m) = if dateOverflow
  26.                            then wrapSucc month maxBound minBound
  27.                            else (False, month)
  28.       y                  = if monthOverflow then succ year else year
  29.   in Day y m d dof
  30.  
  31. wrapSucc :: (Ord a, Enum a) => a -> a -> a -> (Bool, a)
  32. wrapSucc x bound first =
  33.   let overflow = x == bound in (overflow, if overflow then first else succ x)
  34.  
  35. getDaysInMonth :: Year -> Month -> Int
  36. getDaysInMonth year month
  37.   | month == Feb     = if isLeap year then 29 else 28
  38.   | isBigMonth month = 31
  39.   | otherwise        = 30
  40.  
  41. isBigMonth :: Month -> Bool
  42. isBigMonth month
  43.   | month < Aug = even . fromEnum $ month
  44.   | otherwise   = odd  . fromEnum $ month
  45.  
  46. isLeap :: Year -> Bool
  47. isLeap year =
  48.   let (h : t) = [divisible 400, not . divisible 100, divisible 4] <*> [year]
  49.   in h || and t
  50.   where divisible divisor x = x `mod` divisor == 0
Advertisement
Add Comment
Please, Sign In to add comment