euler/haskell/e019.hs

42 lines
1.2 KiB
Haskell

data Weekday = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday
deriving (Show, Eq, Ord, Enum)
data Month = January | February | March | April | May | June | July | August | September | October | November | December
deriving (Show, Eq, Ord, Enum)
type Day = Int
type Year = Int
data Date = Date Year Month Day Weekday
deriving (Show, Eq, Ord)
nextWeekday :: Weekday -> Weekday
nextWeekday Sunday = Monday
nextWeekday d = succ d
nextMonth :: Month -> Month
nextMonth December = January
nextMonth m = succ m
getDays :: Month -> Year -> Int
getDays m y
| elem m [September, April, June, November] = 30
| m == February = if rem y 4 == 0 && if rem y 100 == 0 && rem y 400 /= 0 then False else True
then 29 else 28
| otherwise = 31
nextDate :: Date -> Date
nextDate (Date y m d wd)
| d < getDays m y = Date y m (d+1) (nextWeekday wd)
| m == December = Date (y+1) January 1 (nextWeekday wd)
| otherwise = Date y (nextMonth m) 1 (nextWeekday wd)
daysTwentieth :: [Date]
daysTwentieth = takeWhile (\(Date y _ _ _) -> y /=2001) (dates start)
where
dates d = d:dates (nextDate d)
start = Date 1901 January 1 Tuesday
e019 = length . filter (\(Date y m d wd) -> d == 1 && wd == Sunday) $ daysTwentieth