简体   繁体   English

为什么我的Clojure代码运行这么慢?

[英]Why is my Clojure code running so slowly?

Below is my answer for 4clojure Problem 108 以下是我对4clojure 问题108的回答

I'm able to pass the first three tests but the last test times out. 我能够通过前三个测试,但最后一个测试超时。 The code runs really, really slowly on this last test. 在最后的测试中,代码运行非常缓慢。 What exactly is causing this? 到底是什么原因造成的?

((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))

You are gathering the next value from every input on every iteration (recur (mapv rest coll) m') 您正在从每次迭代的每个输入中收集下一个值(recur (mapv rest coll) m')

One of your inputs generates values extremely slowly, and accellarates to very high values very quickly: (filter #(zero? (bit-and % (dec %))) (range)) . 您的输入之一将非常缓慢地生成值,并且非常快地将其加速到非常高的值:( (filter #(zero? (bit-and % (dec %))) (range))

Your code is spending most of its time discovering powers of two by incrementing by one and testing the bits. 您的代码大部分时间都是通过递增1并测试位来发现2的幂。

You don't need a map of all inputs with counts of occurrences. 您不需要包含发生次数的所有输入的映射。 You don't need to find the next value for items that are not the lowest found so far. 您无需为到目前为止尚未找到的最低项目找到下一个值。 I won't post a solution since it is an exercise, but eliminating the lowest non matched value on each iteration should be a start. 我不会发布解决方案,因为这是一个练习,但是消除每次迭代中的最低不匹配值应该是一个开始。

In addition to the other good answers here, you're doing a bunch of math, but all numbers are boxed as objects rather than being used as primitives. 除了这里的其他好答案之外,您还在做一堆数学运算,但是所有数字都装箱为对象,而不是用作基本体。 Many tips for doing this better here . 许多技巧这样做的更好这里

This is a really inefficient way of counting powers of 2: 这是计算2的幂的一种非常低效的方式:

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

This is essentially counting from 0 to infinity, testing each number along the way to see if it's a power of two. 这实际上是从0到无穷大计数,并一路测试每个数字是否为2的幂。 The further you get into the sequence, the more expensive each call to rest is. 您进入序列的时间越长,每个rest电话就越昂贵。

Given that it's the test input, and you can't change it, I think you need to re-think your approach. 鉴于它是测试输入,并且您无法更改,我认为您需要重新考虑您的方法。 Rather than calling (mapv rest coll) , you probably only want to call rest on the sequence with the smallest first value. 而不是调用(mapv rest coll) ,您可能只想在第一个值最小的序列上调用rest

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM