Project Euler Problem 19
http://projecteuler.net/index.php?section=problems&id=19
20世紀の月初めの日曜日の数を求める。
0を日曜、6を土曜とする。
main = print $ euler19 euler19 :: Int euler19 = euler19' 1900 1 1 where euler19' y m w = if y == 2001 then 0 else let w' = (firstOfNextMonth y m w) n = nextMonth (y,m) in (if ((w' == 0) && (y /= 1900)) then 1 else 0) + euler19' (fst n) (snd n) w' nextMonth :: (Int, Int) -> (Int,Int) nextMonth (y,m) = if m == 12 then (y+1,1) else (y,m+1) --年->月->月初めの曜日->次の月の月初めの曜日 firstOfNextMonth :: Int -> Int -> Int -> Int firstOfNextMonth y m w | elem m [4,6,9,11] = ((w+30) `mod` 7) | elem m [1,3,5,7,8,10,12] = ((w+31) `mod` 7) | m == 2 = if isLeapYear y then ((w+29) `mod` 7) else ((w+28) `mod` 7) | otherwise = -1 isLeapYear :: Int -> Bool isLeapYear y = ((y `mod` 4) == 0) && not (((y `mod` 400) /= 0) && ((y `mod` 100) == 0))
ツェラーの公式使用ばーじょん
main = print $ length $ filter (\(x,y) -> (zeller x y 1) == 0) [(y,m) | y <- [1901..2000], m <- [1..12]] zeller :: Int -> Int -> Int -> Int zeller y m d = if m < 3 then zeller (y-1) (m+12) d else (y + (y `div` 4) - (y `div` 100) + (y `div` 400) + ((13*m + 8) `div` 5) + d) `mod` 7
1200を7で割っても出るとは不思議ですね。