I am working on a Project Euler 14 issue in Clojure. I have what I consider a good algorithm, and I get the correct result, but I try to understand why my function is so slow compared to (as I consider) an equivalent function in Java. Here's my Clojure function to get the Collatz chain length from a given start number:
(defn collatz-length [n] (loop [xn acc 1] (if (= 1 x) acc (recur (if (even? x) (/ x 2) (inc (* 3 x))) (inc acc)))))
And here, my Java function does the same:
public static int collatzLength(long x) { int count = 0; while (x > 1) { if ((x % 2) == 0) { x = x / 2; } else { x = (x * 3) + 1; } count++; } return count; }
To perform these functions, I used the following Clojure code:
(time (dorun (map collatz-length (range 1 1000000))))
And the following Java code:
long starttime = System.currentTimeMillis(); int[] nums = new int[1000000]; for (int i = 0; i < 1000000; i++) { nums[i] = collatzLength(i+1); } System.out.println("Total time (ms) : " + (System.currentTimeMillis() - starttime));
Java code runs at 304 ms on my machine, but Clojure code takes 4220 ms . What causes this bottleneck and how can I improve the performance of my Clojure code?
Kevin source share