Przeglądaj źródła

[Haskell][19] Adding Solution

Vinicius Teshima 4 miesięcy temu
rodzic
commit
9551cdae04
2 zmienionych plików z 75 dodań i 0 usunięć
  1. 26 0
      haskell/src/0019.hs
  2. 49 0
      haskell/src/Utils.hs

+ 26 - 0
haskell/src/0019.hs

@@ -0,0 +1,26 @@
+{-
+You are given the following information, but you may prefer to do some research for yourself.
+1 Jan 1900 was a Monday.
+Thirty days has September,
+April, June and November.
+All the rest have thirty-one, Saving February alone,
+Which has twenty-eight, rain or shine.
+And on leap years, twenty-nine.
+A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.
+How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?
+-}
+
+import Utils
+
+solution :: Int
+solution = go' sD (iterate weekdayNext (weekdayOfDate sD)) 0
+  where
+    sD = Date 1901  1  1
+    eD = Date 2000 12 31
+    go' :: Date -> [Weekday] -> Int -> Int
+    go' d (x:xs) c
+      | d == eD   = c
+      | otherwise = go' (dateNextDay d) xs (if (x == Sunday && (dateDay d) == 1) then (c+1) else c)
+
+main :: IO ()
+main = putStrLn ("Solution: " ++ show solution)

+ 49 - 0
haskell/src/Utils.hs

@@ -144,3 +144,52 @@ module Utils where
         | d == td   = []
         | otherwise = [x] ++ go' l (d+1) ++ go' r (d+1)
 
+  type Day = Int
+  type Month = Int
+
+  monthNumOfDay :: Year -> Month -> Int
+  monthNumOfDay yyyy 2  = if (yearIsLeap yyyy) then 29 else 28
+  monthNumOfDay _    4  = 30
+  monthNumOfDay _    6  = 30
+  monthNumOfDay _    9  = 30
+  monthNumOfDay _    11 = 30
+  monthNumOfDay _    mm = 31
+
+  type Year = Int
+
+  yearIsLeap :: Year -> Bool
+  yearIsLeap yyyy = (mody 4) && ((not (mody 100)) || (mody 400))
+    where mody = \x -> mod yyyy x == 0
+
+  data Date = Date Year Month Day
+    deriving (Show, Eq)
+
+  dateDay :: Date -> Day
+  dateDay (Date _ _ dd) = dd
+
+  dateNextDay :: Date -> Date
+  dateNextDay (Date yyyy mm dd)
+    | dd == (monthNumOfDay yyyy mm) = dateNextMonth (Date yyyy mm 1)
+    | otherwise                     = (Date yyyy mm (dd+1))
+
+  dateNextMonth :: Date -> Date
+  dateNextMonth (Date yyyy 12 dd) = dateNextYear (Date yyyy 1 dd)
+  dateNextMonth (Date yyyy mm dd) = (Date yyyy (mm+1) dd)
+
+  dateNextYear :: Date -> Date
+  dateNextYear (Date yyyy mm dd) = (Date (yyyy+1) mm dd)
+
+  data Weekday = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday
+    deriving (Show, Enum, Eq)
+
+  weekdayNext :: Weekday -> Weekday
+  weekdayNext Sunday = Monday
+  weekdayNext x = succ x
+
+  weekdayOfDate :: Date -> Weekday
+  weekdayOfDate tD = go' (Date 1900 1 1) (iterate weekdayNext Monday)
+    where
+      go' :: Date -> [Weekday] -> Weekday
+      go' d (x:xs)
+        | d == tD   = x
+        | otherwise = go' (dateNextDay d) xs