content: module Main where
  
  import Data.List
  
  procLychrel :: Integer -> [Integer]
  procLychrel a = a : pl a
    where
      pl n =
          let s = n + reverseInteger n
               in if isPalindrome s
                    then [s]
                    else s : pl s
  
  isPalindrome :: Integer -> Bool
  isPalindrome n =
    let s = show n
    in (s == reverse s)
  
  isLychrel :: Integer -> Bool
  isLychrel = not . null . drop 500 . procLychrel
  
  reverseInteger :: Integer -> Integer
  reverseInteger = read . reverse . show
  
  seedAndRelated :: (Int, [Integer], [Integer], Int)
  seedAndRelated =
    let (seed, related, _) = foldl sar ([], [], []) [1 .. 10000]
        lseed = length seed
        lrelated = length related
        totalCount = lseed + lrelated
        pal = filter isPalindrome $ seed ++ related
    in (totalCount, pal, seed, lrelated)
    where
      sar (seed, related, lych) x =
        let s = procLychrel x
            sIsLychrel = not . null . drop 500 $ s
            (isIn, isOut) = partition (`elem` lych) . take 501 $ s
            newLych = lych ++ isOut
        in if sIsLychrel
             then if null isIn -- seed lychrel number
                    then (x : seed, related, newLych)
                    else (seed, x : related, newLych) -- related lychrel number
             else (seed, related, lych)
  
  main = do
    let (totalCount, palindromicLychrel, lychrelSeeds, relatedCount) = seedAndRelated
    putStrLn $ "[1..10,000] contains " ++ show totalCount ++ " Lychrel numbers."
    putStrLn $ show palindromicLychrel ++ " are palindromic Lychrel numbers."
    putStrLn $ show lychrelSeeds ++ " are Lychrel seeds."
    putStrLn $ "There are " ++ show relatedCount ++ " related Lychrel numbers."
  