たらいまわし問題(遅延評価編)
前エントリーで「scalaの遅延評価は限定的scalaなので無理かも」と書いたけれど嘘でした。
Scala開眼の引数の遅延評価渡しを参考にしたらできました。
以下がソース。
package tarai import java.util.Calendar import scala.collection.mutable.Map object Main { def main(args: Array[String]): Unit = { val tm1 = Calendar.getInstance().getTimeInMillis println("result", taraiC(20, 10, 5)) val tm2 = Calendar.getInstance().getTimeInMillis println("time", tm2 - tm1) println("result", taraiL(20, 10, 5)) val tm3 = Calendar.getInstance().getTimeInMillis println("time", tm3 - tm2) } // たらいまわし(キャッシュ使用) var cache = Map.empty[Tuple3[Int, Int, Int], Int] def taraiC(x:Int, y:Int, z:Int): Int = { if (cache.contains((x,y,z))) cache((x,y,z)) else { val result = if (x <= y) y else taraiC(taraiC(x - 1, y, z), taraiC(y - 1, z, x), taraiC(z - 1, x, y)) cache((x,y,z)) = result result } } // たらいまわし(遅延評価) def taraiL(x: => Int, y: => Int, z: => Int): Int = { if (x <= y) y else taraiL(taraiL(x - 1, y, z), taraiL(y - 1, z, x), taraiL(z - 1, x, y)) } }
taraiLは遅延評価をしています。
このコードで、前エントリーのキャッシュを使った場合(taraiC)とどちらが速いか比較したのですが、自分の環境ではキャッシュ版が125ms,遅延評価版が16msでした。
しかし、taraiLをtaraiCより先に実行するようにしたら、キャッシュ版が15ms,遅延評価版が125msで逆転しました。
色々試したらprintlnの処理が初回時に時間がかかるようなので、mainの先頭にprintln("",0)を挿入すると、処理順序によらずtaraiCが16ms,taraiLが0msで処理をしました。