为什么我的Clojure代码运行得如此之慢?

时间:2014-09-11 17:30:21

标签: clojure

以下是我对4clojure Problem 108

的回答

我能够通过前三次测试,但最后一次测试时间结束了。在最后一次测试中,代码运行得非常非常缓慢。究竟是什么造成了这个?

((fn [& coll] (loop [coll coll m {}]
    (do
        (let [ct (count coll)
                ns (mapv first coll)
                m' (reduce #(update-in %1 [%2] (fnil inc 0)) m ns)]
            (println m')
            (if (some #(<= ct %) (mapv m' ns))
                (apply min (map first (filter #(>= (val %) ct) m')))
                (recur (mapv rest coll) m'))))))
 (map #(* % % %) (range)) ;; perfect cubes
 (filter #(zero? (bit-and % (dec %))) (range)) ;; powers of 2
 (iterate inc 20))

3 个答案:

答案 0 :(得分:2)

您正在从每次迭代(recur (mapv rest coll) m')

的每个输入中收集下一个值

您的一个输入非常缓慢地生成值,并且非常快速地加速到非常高的值:(filter #(zero? (bit-and % (dec %))) (range))

您的代码花费大部分时间通过递增1并测试位来发现2的幂。

您不需要具有发生次数的所有输入的地图。您不需要为目前为止找不到的项找到下一个值。我不会发布解决方案,因为它是一个练习,但是在每次迭代中消除最低的非匹配值应该是一个开始。

答案 1 :(得分:2)

除了这里的其他好答案之外,你还做了一堆数学,但是所有的数字都被装箱作为对象,而不是用作原语。有很多提示可以做得更好here

答案 2 :(得分:1)

这是计算2的幂的非常低效的方法:

(filter #(zero? (bit-and % (dec %))) (range))

这基本上是从0到无穷大,从头开始测试每个数字,看看它是否是2的幂。进入序列越远,每次调用rest的费用就越高。

鉴于它是测试输入,你不能改变它,我认为你需要重新思考你的方法。您可能只想在具有最小第一个值的序列上调用(mapv rest coll),而不是调用rest