|
| 1 | +data Mode = Servois | Easter |
| 2 | + |
| 3 | +computus :: Mode -> Int -> String |
| 4 | +computus mode year = |
| 5 | + case mode of |
| 6 | + Servois -> |
| 7 | + -- Value for Servois' table |
| 8 | + show $ (21 + d) `mod` 31 |
| 9 | + Easter -> |
| 10 | + -- Determination of the correct month for Easter |
| 11 | + if 22 + d + f > 31 |
| 12 | + then "April " ++ show (d + f - 9) |
| 13 | + else "March " ++ show (22 + d + f) |
| 14 | + where |
| 15 | + a, b, c, d, e, f, k, m, n, p, q :: Int |
| 16 | + -- Year's position on the 19 year metonic cycle |
| 17 | + a = year `mod` 19 |
| 18 | + -- Century index |
| 19 | + k = year `div` 100 |
| 20 | + -- Shift of metonic cycle, add a day offset every 300 years |
| 21 | + p = (13 + 8 * k) `div` 25 |
| 22 | + -- Correction for non-observed leap days |
| 23 | + q = k `div` 4 |
| 24 | + -- Correction to starting point of calculation each century |
| 25 | + m = (15 - p + k - q) `mod` 30 |
| 26 | + -- Number of days from March 21st until the full moon |
| 27 | + d = (19 * a + m) `mod` 30 |
| 28 | + -- Finding the next Sunday |
| 29 | + -- Century-based offset in weekly calculation |
| 30 | + n = (4 + k - q) `mod` 7 |
| 31 | + -- Correction for leap days |
| 32 | + b = year `mod` 4 |
| 33 | + c = year `mod` 7 |
| 34 | + -- Days from d to next Sunday |
| 35 | + e = (2 * b + 4 * c + 6 * d + n) `mod` 7 |
| 36 | + -- Historical corrections for April 26 and 25 |
| 37 | + f = |
| 38 | + if (d == 29 && e == 6) || (d == 28 && e == 6 && a > 10) |
| 39 | + then -1 |
| 40 | + else e |
| 41 | + |
| 42 | +-- Here, we will output the date of the Paschal full moon |
| 43 | +-- (using Servois notation), and Easter for 2020-2030 |
| 44 | +main :: IO () |
| 45 | +main = do |
| 46 | + let years :: [Int] |
| 47 | + years = [2020 .. 2030] |
| 48 | + servoisNumbers, easterDates :: [String] |
| 49 | + servoisNumbers = map (computus Servois) years |
| 50 | + easterDates = map (computus Easter) years |
| 51 | + putStrLn "The following are the dates of the Paschal full moon (using Servois notation) and the date of Easter for 2020-2030 AD:" |
| 52 | + putStrLn "Year\tServois number\tEaster" |
| 53 | + let conc :: Int -> String -> String -> String |
| 54 | + conc y s e = show y ++ "\t" ++ s ++ "\t\t" ++ e |
| 55 | + mapM_ putStrLn $ zipWith3 conc years servoisNumbers easterDates |
0 commit comments