From: Peng Zang <peng.zang@gmail.com>
To: "Evan Klitzke" <evan@yelp.com>
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] Help with simple ocaml memoization problem
Date: Tue, 4 Dec 2007 18:49:24 -0500 [thread overview]
Message-ID: <200712041849.29780.peng.zang@gmail.com> (raw)
In-Reply-To: <cfb58d850711282212r64eddad3u713e2eb743526b0a@mail.gmail.com>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Oops. I was looking at this code again, and it actually isn't tail recursive.
Ie. It's still recursing on the stack. For one, I still add 1 after I make
the recursive call and two, wrapping it in a lazy means once the value is
calculated it must go back to memoize it. But, it turns out it doesn't
matter as there's not that many levels of recursion anyways. The value
837799 has a collatz lenght of 525 which means about that number of recursive
calls. I actually think the problem you had before was overflow from using
ints. In any event, here's the code without any laziness to confuse the
issue.
let ( ++ ) = Int64.add;;
let ( ** ) = Int64.mul;;
let ( %% ) = Int64.rem;;
let ( // ) = Int64.div;;
let cache = Hashtbl.create 1000000;;
let cache2 = Hashtbl.create 1000000;;
let collatz = function
| x when x %% 2L = 1L -> 3L ** x ++ 1L
| x -> x // 2L
;;
let rec find_collatz_len x = match x with
| 1L -> 1L
| x when Hashtbl.mem cache x -> Hashtbl.find cache x
| x -> let ans = 1L ++ find_collatz_len (collatz x) in
Hashtbl.add cache x ans;
ans
;;
let lengths = Array.init 999999
(fun x -> let x = Int64.of_int (x + 1) in (x, find_collatz_len x));;
Array.sort (fun (a,b) (c,d) -> compare d b) lengths;;
lengths.(0)
Peng
On Thursday 29 November 2007 01:12:57 am Evan Klitzke wrote:
> On 11/28/07, Peng Zang <peng.zang@gmail.com> wrote:
> > I don't know how to increase the stack size off the top of my head, but
> > in general you want to avoid recursion on the stack anyways. An easy way
> > is to simply make the function tail recursive so the compiler can
> > optimized it into a loop for you. Here's a pretty faithful replication
> > of your python code. Note I use Int64 instead of BigInt as I'm running
> > OCaml 3.09.3.
> >
> > let ( ++ ) = Int64.add;;
> > let ( ** ) = Int64.mul;;
> > let ( %% ) = Int64.rem;;
> > let ( // ) = Int64.div;;
> > let l1 = Int64.of_int 1;;
> > let l2 = Int64.of_int 2;;
> > let l3 = Int64.of_int 3;;
> > let cache = Hashtbl.create 1000000;;
> >
> > let collatz = function
> >
> > | x when x %% l2 = l1 -> l3 ** x ++ l1
> > | x -> x // l2
> >
> > ;;
> > let rec find_collatz_len = function
> >
> > | x when x = l1 -> l1
> > | x when Hashtbl.mem cache x -> Lazy.force (Hashtbl.find cache x)
> > | x -> let ans = lazy (l1 ++ find_collatz_len (collatz x)) in
> >
> > Hashtbl.add cache x ans;
> > Lazy.force ans
> > ;;
> > let lengths = Array.init 999999
> > (fun x -> let x = Int64.of_int (x+1) in (x, find_collatz_len x));;
> > Array.sort (fun (a,b) (c,d) -> compare d b) lengths;;
> > lengths.(0);;
> >
> >
> > The use of laziness here is just so I can put the recursive call in the
> > tail position -- a quick hack because I'm too lazy to spend time making
> > it into a loop myself.
> >
> > There should really be some easy syntax to write BigInts or Int64s
> > directly in the code. Is there some camlp4 that does this somewhere?
> > And it would nice if Int64 operators were predefined in the module.
>
> Thanks Peng. This is much easier to grok than the code that I
> originally wrote! One question that I have is what is the difference
> between the Map and Hashtbl modules? From the documentation they look
> very similar -- why did you use Hashtbl here rather than Map?
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.7 (GNU/Linux)
iD8DBQFHVeeJfIRcEFL/JewRAv64AKC5xEgXeTibAg0BEPNyrFTIMCPprgCgqEYB
UG8FMXoAWBJBzicGk2z3MB8=
=Gw33
-----END PGP SIGNATURE-----
next prev parent reply other threads:[~2007-12-04 23:49 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-11-29 3:17 Evan Klitzke
2007-11-29 5:53 ` [Caml-list] " Peng Zang
2007-11-29 6:12 ` Evan Klitzke
2007-11-29 8:16 ` David Allsopp
2007-11-29 8:11 ` Jon Harrop
2007-11-29 8:58 ` Jean-Christophe Filliâtre
2007-11-29 18:57 ` Jon Harrop
2007-11-29 22:25 ` Jon Harrop
2007-11-30 11:03 ` Jean-Christophe Filliâtre
2007-11-29 8:40 ` Luc Maranget
2007-11-29 8:47 ` Jean-Christophe Filliâtre
2007-12-04 23:49 ` Peng Zang [this message]
2007-11-29 8:08 ` Jon Harrop
2007-11-29 15:59 ` Peng Zang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200712041849.29780.peng.zang@gmail.com \
--to=peng.zang@gmail.com \
--cc=caml-list@inria.fr \
--cc=evan@yelp.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox