erlangでたらい回し: memorize編
酒日記 はてな支店 - Erlangでたらい回し を見て、memorize版を書いてみた。
memorize_tarai(X, Y, _Z) when X =< Y -> Y;
memorize_tarai(X, Y, Z) ->
case get({X, Y, Z}) of
undefined -> put({X, Y, Z},
memorize_tarai(
memorize_tarai(X-1, Y, Z),
memorize_tarai(Y-1, Z, X),
memorize_tarai(Z-1, X, Y))),
get({X, Y, Z});
A -> A
end.
プロセスディクショナリを使ってみました。酒日記さんのと同じ測定方法で測定。
bench_memorize_tarai(X, Y, Z) ->
{Time, Ans} = timer:tc(?MODULE, memorize_tarai, [X, Y, Z]),
io:format("tak(~p, ~p, ~p) = ~p : time ~p msec~n", [X, Y, Z, Ans, Time/1000]).
結果は、
4> tarai:bench_memorize_tarai(100,50,0). tak(100, 50, 0) = 100 : time 38.0000 msec
同じ環境で 酒日記 はてな支店 - Erlangでたらい回し 遅延評価版 にあった 遅延評価版も測定してみた。
5> tarai:bench_lazy_tarai(100,50,0). tak(100, 50, 0) = 100 : time 19.0000 msec
memorize版はlazy版より2倍程度遅いという結果がでました。
ただしmemorize版はプロセスディクショナリに保存するため、 インタラクティブシェルで複数回実行する場合、2回目以降では 計算結果が残っているため、下記のような結果となってしまう。
6> tarai:bench_memorize_tarai(100,50,0). tak(100, 50, 0) = 100 : time 1.00000e-3 msec
すげーはやっ。

