Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
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-----


  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