Question: I'm working on an f# solution to [this problem](https://projecteuler.net/problem=14) where I need to find the generator element above 1,000,000 with the longest generated sequence
I use a tail-recursive function that memoizes the previous results to speed up the calculation. This is my current implementation.

```
let memoize f = 
        let cache = new Dictionary<_,_>(1000000)
        (fun x ->
            match cache.TryGetValue x with
            | true, v -> 
                v
            | _ -> let v = f x
                   cache.Add(x, v)
                   v)

let rec memSequence =
        memoize (fun generator s ->
            if generator = 1 then s + 1
            else
                let state = s+1
                if even generator then memSequence(generator/2) state
                else memSequence(3*generator + 1) state   )

let problem14 =
        Array.init 999999 (fun idx -> (idx+1, (memSequence (idx+1) 0))) |> Array.maxBy snd |> fst

```

It seems to work well until want to calculate the lengths of the sequences generated by the first 100,000 numbers but it slows down significantly over that. In fact, for 120,000 it doesn't seem to terminate. I had a feeling that it might be due to the Dictionary I use, but I read that this shouldn't be the case. Could you point out why this may be potentially inefficient?

Answer: 
I think the underlying question may have been *How to combine a memoizing function with a potentially costly calculating function that takes more than one argument?*.
In this case, that second argument isn't needed. There's nothing inherently wrong with memoizing 2168612 elements (the size of the dictionary after the calculation).

Beware of overflow, since at 113383 the sequence surpasses `System.Int32.MaxValue`. A solution might thus look like this:

```
let memoRec f =
    let d = new System.Collections.Generic.Dictionary<_,_>()
    let rec g x =
        match d.TryGetValue x with
        | true, res -> res
        | _ -> let res = f g x in d.Add(x, res); res
    g

let collatzLong =
    memoRec (fun f n ->
        if n <= 1L then 0
        else 1 + f (if n % 2L = 0L then n / 2L else n * 3L + 1L) )

{0L .. 999999L}
|> Seq.map (fun i -> i, collatzLong i)
|> Seq.maxBy snd
|> fst

```
You're on the right track, but there's one thing very wrong in how you implement your memoization. 

Your memoize function takes a function of one argument and returns a memoized version of it. When you use it in `memSequence` however, you give it a curried, two argument function. What then happens is that the memoize takes the function and saves down the result of partially applying it for the first argument only, i.e. it stores the closure resulting from applying the function to `generator`, and than proceeds to call those closures on `s`. 

This means that your memoization effectively doesn't do anything - add some print statements in your memoize function and you'll see that you're still doing full recursion.