Problem14(3) -64bit-
30分プログラム、その280。osiireさんのアドバイスを試してみる。
知ってるとは思うけど、64bitCPUならOCamlのintは63bitまで使えますよ。
bigint使わなくても解けたりしない?
iMac G5だから64ビットのはずなんだけどなぁ、と思いつつ調べてみると、コンパイル時にオプションを指定してやらないとダメらしい。
http://jijixi.azito.com/cgi-bin/diary/index.rb?date=20070518#p04
しょうがないので、ソースコードからビルドし直した。
$ ./configure -cc "gcc -arch ppc64" $ make world $ make opt $ make install
Sys.word_sizeもちゃんと64になっている。なぜかバージョン番号が表示されない。特に支障はないので放置でいいかな。
$ ocaml Objective Caml version # Sys.word_size;; - : int = 64
この64bit版OCamlで動かしたら、あっさり解けた。64ビットすごい。
使い方
$ ocamlopt problem14.ml -o p14 $ file p14 p14: Mach-O 64-bit executable ppc64 $ time ./p14 collatz(837799) = 525 ./p14 8.10s user 0.30s system 82% cpu 10.198 total
ソースコード
前に書いたコードとほぼ同じ。
let ($) f g x = f (g x) let (@@) f g = f g let even n = (n mod 2) = 0 let table = Hashtbl.create 10 let collatz n = let rec loop n r = if Hashtbl.mem table n then begin flush stdout; (Hashtbl.find table n) + r end else if n = 1 then r+1 else if n < 0 then failwith "overflow" else if even n then loop (n/2) (1+r) else loop (3*n+1) (1+r) in let r = loop n 0 in Hashtbl.replace table n r; r let range a b = let rec f r a b = if a = b then r else f (a::r) (a+1) b in f [] a b let solve _ = let f ((_,count) as x) m = let count' = collatz m in if count < count' then (m,count') else x in List.fold_left f (0,0) @@ range 500_000 1_000_000;; let _ = if not !Sys.interactive then begin let (x,f) = solve () in Printf.printf "collatz(%d) = %d\n" x f end
参考
- 過去の30分プログラム
- Problem 14 - PukiWiki
- 過去のバージョン
- Problem14(1) - 力づく - みずぴー日記 - 力づくでチャレンジしたバージョン
- Problem14(2) -動的計画法- - みずぴー日記 - ハッシュテーブルによる動的計画法の導入
- Problem14(2) -BigInt- - みずぴー日記 - BigIntによるオーバーフローの防止
- Problem14(4) -Numモジュール- - みずぴー日記 - Numsの利用