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 
