import Data.Time.Calendar (Day, fromGregorianValid)
import Data.List.Split (chunksOf)
import Data.List (unfoldr)
import Data.Tuple (swap)
import Data.Bool (bool)
import Data.Maybe (mapMaybe)

palinDates :: [Day]
palinDates = mapMaybe palinDay [2021 .. 9999]

palinDay :: Integer -> Maybe Day
palinDay y = fromGregorianValid y m d
  where
    [m, d] = unDigits <$> chunksOf 2 (reversedDecimalDigits (fromInteger y))

reversedDecimalDigits :: Int -> [Int]
reversedDecimalDigits =
  unfoldr ((flip bool Nothing . Just . swap . flip quotRem 10) <*> (0 ==))

unDigits :: [Int] -> Int
unDigits = foldl ((+) . (10 *)) 0

main :: IO ()
main = do
  let n = length palinDates
  putStrLn $ "Count of palindromic dates [2021..9999]: " ++ show n
  putStrLn "\nFirst 15:"
  mapM_ print $ take 15 palinDates
  putStrLn "\nLast 15:"
  mapM_ print $ take 15 (drop (n - 15) palinDates)