/* Computes the nth Fibonacci number several ways & compares their running times. */ fun main() { val n = 43 testRun("dpSpaceFib", n, ::dpSpaceFib) testRun("dpFib", n, ::dpFib) testRun("memFib", n, ::memFib) testRun("naiveFib", n, ::naiveFib) } /* Test harness. Calls f(n), then prints the result and running time. */ fun testRun(fname: String, n: Int, f: (Int) -> Int) { var result = 0 val exeTime = kotlin.system.measureNanoTime { result = f(n) } println("Running $fname($n) gives $result and it takes $exeTime ns to execute.") } /* Computes the nth Fibonacci number using the recurrence naively. */ fun naiveFib(n: Int): Int = if (n < 2) n else naiveFib(n-1) + naiveFib(n-2) /* Computes the nth Fibonacci number using bottom-up dynamic programming. */ fun dpFib(n: Int): Int { val table = IntArray(n+1) { it } for (i in 2..n) table[i] = table[i-1] + table[i-2] return table[n] } /* Computes the nth Fibonacci number using memoization. */ fun memFib(n: Int): Int { val UNKNOWN = -1 val table = IntArray(n+1) { if (it < 2) it else UNKNOWN } fun accessTable(k: Int): Int { if (table[k] == UNKNOWN) table[k] = accessTable(k-1) + accessTable(k-2) return table[k] } return accessTable(n) } /* Computes the nth Fibonacci number using bottom-up dynamic programming and also using space-saving technique. */ fun dpSpaceFib(n: Int): Int { return when (n) { 0 -> 0 1 -> 1 else -> { var fi = 0 // f_i var fip1 = 1 // f_{i+1} for (i in 2..n) { fip1 += fi fi = fip1 - fi } fip1 } } }