代码表现不佳的clojure表现

时间:2015-06-14 16:40:44

标签: clojure

我已经完成了关于hackerrank的this问题,我的解决方案通过了大多数测试用例,但对于11个测试用例中的4个来说速度不够快。

我的解决方案如下:

(ns scratch.core
  (require [clojure.string :as str :only (split-lines join split)]))

(defn ascii [char]
  (int (.charAt (str char) 0)))

(defn process [text]
  (let [parts (split-at (int (Math/floor (/ (count text) 2))) text)
        left (first parts)
        right (if (> (count (last parts)) (count (first parts)))
                (rest (last parts))
                (last parts))]

    (reduce (fn [acc i]
              (let [a (ascii (nth left i))
                    b (ascii (nth (reverse right) i))]
                (if (> a b)
                  (+ acc (- a b))
                  (+ acc (- b a))))
              ) 0 (range (count left)))))

(defn print-result [[x & xs]]
  (prn x)
  (if (seq xs)
    (recur xs)))

(let [input (slurp "/Users/paulcowan/Downloads/input10.txt")
      inputs (str/split-lines input)
      length (read-string (first inputs))
      texts (rest inputs)]
  (time (print-result (map process texts))))

任何人都可以给我任何关于我应该注意什么的建议,以加快速度吗?

使用递归而不是减少会更快或者这条线很昂贵:

right (if (> (count (last parts)) (count (first parts)))
                (rest (last parts))
                (last parts))

因为我得了两次计数。

1 个答案:

答案 0 :(得分:4)

你在reduce的每次迭代中都冗余地调用reverse:

user=> (let [c [1 2 3]
             noisey-reverse #(doto (reverse %) println)]
         (reduce (fn [acc e] (conj acc (noisey-reverse c) e))
                 []
                 [:a :b :c]))
(3 2 1)
(3 2 1)
(3 2 1)
[(3 2 1) :a (3 2 1) :b (3 2 1) :c]

反转值可以在包含let中计算,然后只需要计算一次。

此外,由于parts的定义方式,您每次调用nth时都会进行线性时间查询。最好将部件放在矢量中并进行索引查找。事实上,您不需要反转部件,并且可以根据矢量的计数进行算术运算,以找到要查找的项目。