Skip to content

Instantly share code, notes, and snippets.

@ners
Created May 19, 2019 10:27
Show Gist options
  • Save ners/db9e4c2b2ed706f387a2376536d57520 to your computer and use it in GitHub Desktop.
Save ners/db9e4c2b2ed706f387a2376536d57520 to your computer and use it in GitHub Desktop.
import Control.Parallel.Strategies ( parListChunk, rdeepseq, using )
import Data.List ( any, genericLength, group, sort, sortBy )
import Data.Set ( deleteFindMin, fromList, insert )
digits :: Integer -> [Integer]
digits 0 = [0]
digits n = (n `mod` 10) : if n > 9 then digits (n `div` 10) else []
nextTerm :: Integer -> Integer
nextTerm n = foldl (\acc (a, b) -> acc * 100 + a * 10 + b) 0 gs
where gs = (\g -> (genericLength g, head g)) <$> (group . sort . digits) n
cleanChain :: [Integer] -> Integer -> [Integer]
cleanChain s n | n `elem` s = []
| otherwise = n : cleanChain (n : s) (nextTerm n)
chain :: Integer -> [Integer]
chain = cleanChain []
chainLength :: Integer -> Int
chainLength = length . chain
terms :: Int -> [Integer]
terms n = 0 : concat (pad <$> ts)
where
ts = takeWhile (< 10 ^ n) $ f (fromList [1 .. 9])
pad t = scanl (\x _ -> x * 10) t [length $ digits t .. n - 1]
f s = m : f (foldl (flip insert) s' $ map (10 * m +) [m `mod` 10 .. 9])
where (m, s') = deleteFindMin s
main :: IO ()
main = mapM_ print $ take 5 sorted
where
gt t = (t, chainLength t)
gs = gt <$> terms 10 `using` parListChunk 128 rdeepseq
sorted = sortBy (\(_, a) (_, b) -> compare b a) gs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment