Skip to content

Instantly share code, notes, and snippets.

@SimonAlling
Created February 2, 2020 20:23
Show Gist options
  • Save SimonAlling/51de48a9773babab16e25662d8a720a9 to your computer and use it in GitHub Desktop.
Save SimonAlling/51de48a9773babab16e25662d8a720a9 to your computer and use it in GitHub Desktop.
Palindrome dates with only two different digits
{-# LANGUAGE LambdaCase #-}
import Data.List
data Day = Day Int
instance Show Day where
show (Day d) = pad d
data Month = Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec
deriving Enum
instance Show Month where
show = pad . (+1) . fromEnum
type Year = Int
type Date = String
data Direction = Back | Forward
main :: IO ()
main = mapM_ putStrLn . filter (hasMaxUnique 2) . filter isPalindromeDate $ generateDates Forward 1000
generateDates :: Direction -> Year -> [Date]
generateDates d y = f (datesInYear y) ++ generateDates d (y `op` 1)
where
(op, f) = case d of
Back -> ((-), reverse)
Forward -> ((+), id)
numDays :: Year -> Month -> Int
numDays y = \case
Nov -> 30
Apr -> 30
Jun -> 30
Sep -> 30
Feb -> if isLeapYear y then 29 else 28
_ -> 31
days :: Year -> Month -> [Day]
days y m = map Day [1..numDays y m]
date :: Year -> Month -> Day -> Date
date y m d = intercalate "-" [show y, show m, show d]
datesInMonth :: Year -> Month -> [Date]
datesInMonth y m = map (date y m) $ days y m
datesInYear :: Year -> [Date]
datesInYear y = concat . map (datesInMonth y) $ enumFromTo Jan Dec
isPalindromeDate :: Date -> Bool
isPalindromeDate = (\x -> reverse x == x) . withoutHyphens
withoutHyphens :: Date -> String
withoutHyphens = filter (/= '-')
hasMaxUnique :: Int -> Date -> Bool
hasMaxUnique n = (<= n) . length . group . sort . withoutHyphens
isLeapYear :: Year -> Bool
isLeapYear y = (y `multOf` 4 && not (y `multOf` 100)) || y `multOf` 400
where multOf y m = y `mod` m == 0
pad :: Int -> String
pad d = if d < 10 then "0" ++ show d else show d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment