[Haskell-cafe] Programming Chalenges: The 3n+1 problem
Steven Keuchel
steven.keuchel at gmail.com
Thu Apr 14 13:17:30 CEST 2011
Hi Dmitri,
As a reference you might want to take a look at the Project Euler
problem #14 and the corresponding dubious entry in the HaskellWiki:
http://www.haskell.org/haskellwiki/Euler_problems/11_to_20#Problem_14
.
> *** Question: I wonder how to implement cache for this problem in Haskell?
> At the moment, I am not so much interested in the speed of the code, as in
> nice implementation.
a while ago I wondered about the same question: memoization and more
specifically tabulation (DP) in Haskell. After some time I came up
with code which does it IMO in a fairly nice way using an array of
lazy computations which gives you top-down DP for free at the expense
of performance. Another way is to use lazily built tries ala MemoTrie:
http://www.haskell.org/haskellwiki/MemoTrie .
Specific implementation:
> import Data.Array
> import Data.MemoTrie
I write the collatz function using open recursion in order to separate
the recursive function from the memo scheme.
> type Gen a = a -> a
> type Fix a = Gen a -> a
>
> collatzGen :: Gen (Integer -> Integer)
> collatzGen c 1 = 1
> collatzGen c n | even n = 1 + c (div n 2)
> | otherwise = 1 + c (3*n + 1)
We can use plain old Data.Function.fix to get the usual stupid
recursive function or use our custom fixpoint combinators. |fixtab|
for example uses an array to cache the result in the given range. When
the argument is outside of the range the normal recursive scheme is
applied.
> fixtab :: Ix i => (i, i) -> Fix (i -> r)
> fixtab b f = f'
> where a = listArray b [ f f' i | i <- range b ]
> f' i = if inRange b i then a!i else f f' i
Another option is to use the MemoTrie package where we can write a
fixpoint combinator like this:
> fixmemo :: HasTrie i => Fix (i -> r)
> fixmemo f = let m = memo (f m); in m
And of course the final collatz function:
> collatz :: Integer -> Integer
> collatz = fixtab (1,1000000) collatzGen
Cheers,
Steven
More information about the Haskell-Cafe
mailing list