Actually, Collatz sequences are short enough that you don't really need to worry about blowing the stack, so you don't need to bother with tail recursion or continuation passing style and can just write the function naively (note that I've used bigints here instead of uint64s):

1
2
3
4
5
6
let rec collatz = function
| n when n = 1I -> 1
| n -> 1 + collatz (if n%2I = 0I then n/2I else 3I*n+1I)

let count = collatz 2361198062777205778683I

Then, you can use the standard trick for memoizing a recursive function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
open System.Collections.Generic

let memo_rec f =
  let cache = Dictionary<_,_>()
  let rec fn x =
    if not (cache.ContainsKey x) then
      cache.[x] <- f fn x
    cache.[x]
  fn

let collatz = memo_rec (fun cltz -> 
  function
  | n when n = 1I -> 1
  | n -> 1 + cltz (if n%2I = 0I then n/2I else 3I*n+1I))

However, if you want to go ahead and do things the "right way", see Brian's answer to this StackOverflow question.

By on 1/6/2011 2:47 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper