I have a working program to compute the longest collatz chain in a given range (project euler n°14). I think it works correctly, but is very slow. I tried to look for a better solution, but I can only reduce slightly the evaluated domain. Am I doing something wrong?
The implementation use memoization to avoid computing the same result twice. Is Data.Map bad for general performances?
import Data.Map ((!), member, insert, singleton, assocs, Map)
insertSolution::Integer->(Map Integer Integer)->(Map Integer Integer)
insertSolution n syracMap
| n `member` syracMap = syracMap
|otherwise = let
next = if n `mod` 2 == 0 then n `div` 2 else 3 * n + 1
newMap = insertSolution next syracMap
solution = newMap ! next + 1
in insert n solution newMap
bound = 1::Integer
lower = 999999::Integer
test::[Integer]
test = [lower,lower+2..bound]
values = takeWhile (\(k, v) -> k < bound) $ assocs $ foldr insertSolution (singleton 1 1) test
result = foldr (\(k, v) (k', v') -> if v > v' then (k, v) else (k', v')) (1, 1) values
main = putStr $ show $ result
edit
updated function to remove bug. It is still pretty slow on my laptop.
FWIW, here’s my solution:
It’s relatively fast. If you want more speed, consult the Haskell wiki (SPOILER ALERT!!!).