-- Collatz sequence. See rosettacode.org/wiki/Hailstone_sequence#Haskell import Data.List (maximumBy) import Data.Ord (comparing) main :: IO () main = putStrLn $ "Collatz sequence for 27: " ++ (show.hailstone $ 27) ++ "\n" ++ "The number " ++ (show longestChain) ++" has the longest hailstone sequence" ++" for any number less then 100000. " ++"The sequence has length " ++ (show.length.hailstone $ longestChain) hailstone :: Integer -> [Integer] hailstone = takeWhile (/=1) . (iterate collatz) where collatz n = if even n then n `div` 2 else 3*n+1 longestChain :: Integer longestChain = maximumOn (length.hailstone) [1..100000] {- -- The more obvious way of is not much slower. longestChain' = fst $ maximumBy (comparing snd) $ map pairUp [1..100000] where pairUp i = (i, (length.hailstone) i) -} {- The "Schwartzian Transform" https://en.wikipedia.org/wiki/Schwartzian_transform avoid recomputing the keys of comparison. Haskell has a 'sortOn' to go with its 'sortBy', but as of yet there is no 'maximumOn'. -} {- sortBy :: (a -> a -> Ordering) -> [a] -> [a] maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a sortOn :: Ord b => (a -> b) -> [a] -> [a] sortOn f = map snd . sortBy (comparing fst) . map (\x -> let y = f x in y `seq` (y, x)) -} -- New feature request #15566: https://ghc.haskell.org/trac/ghc/ticket/15566 maximumOn :: Ord b => (a -> b) -> [a] -> a maximumOn f = snd . maximumBy (comparing fst) . map (\x -> let y = f x in y `seq` (y, x)) -- ------------For GNU Emacs ------------ -- Local Variables: -- compile-command: "ghc -Wall -O2 hail2.hs" -- End: