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 
                  then (x: seed, related, newLych)
                  else (seed, x: related, newLych) 
           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."