初学者的Clojure尝试破解问题超时

时间:2019-07-09 11:38:13

标签: clojure

我正在hackerrank上尝试以下问题:

https://www.hackerrank.com/challenges/counting-valleys

但是不幸的是,我下面的Clojure代码在许多测试用例上都超时了,我不知道是什么使它如此低效。请宽容。我总共只有2个小时的clojure经验。

declare 
 v_sql varchar2(10000);
 l_table_name varchar2(40) := 'arch_tbl_' 
                             || TO_CHAR( add_months(sysdate,-1),'MON');
BEGIN
 v_sql := 'select .. into ....... from ' || l_table_name || ' .... ';
 execute immediate v_sql;
 commit;
END;

使用5分钟并通过所有测试用例的相同逻辑的简单易用的python实现:

(require '[clojure.string :as str])

; Complete the countingValleys function below.
(defn countingValleys [n s]
    (do 
    (def running 0)
    (defn counter [elem]
    (do
        (cond 
        (= elem "D") (def running (+ running 1))
        (= elem "U")(def running (- running 1))
        )
        running
    )

    )

    (def valley-num 0)

    (defn valley-count [a b]
    (do
        (if (and (= a "U") (= b 0))
        (def valley-num (+ valley-num 1)))
    )
    )

    (def heights (for [elem s] (counter elem)))
    (doseq [[i j] (map vector s heights)]
    (valley-count i j))
    valley-num
    )


)

(def fptr (get (System/getenv) "OUTPUT_PATH"))

(def n (Integer/parseInt (clojure.string/trim (read-line))))

(def s (read-line))

(def result (countingValleys n (str/split s #"")))

(spit fptr (str result "\n") :append true)

3 个答案:

答案 0 :(得分:3)

所以我知道了。效率低下是这样的:

(doseq [[i j] (map vector s heights)]
    (valley-count i j))

可以替换为:

(doall (map valley-count s heights))

,然后所有测试通过。

答案 1 :(得分:0)

代码缓慢是其问题中最少的。您应该使用的工具是

  • 纯函数
  • 序列库
  • 以及速度方面,换能器的前景。

我喜欢您的基本算法:计算 up 运动将您带到海平面的情况。

我们可以这样惯用地表达它:

 (defn countingValleys [n s]
  (let [counter {\D 1, \U -1}
        heights (reductions + (map counter s))
        s-heights (map vector s heights)
        valley-num (count (filter #{[\U 0]} s-heights))]
    valley-num))

...或使用->>线程宏...

(defn countingValleys [_ s]
  (->> s
       (map {\D 1, \U -1})
       (reductions +)
       (map vector s)
       (filter #{[\U 0]})
       (count))) 

这些比您更清晰,更快。


似乎您和HackerRank实际上正在使用ClojureScript。将"U"用作字符串的元素在Clojure中不起作用:您必须使用字符\U

答案 2 :(得分:-1)

Those of us who are JavaScript(Node JS) developers, my solution here works perfectly

// Complete the countingValleys function below.
function countingValleys(n, s) {
  const min = 2;
  const max = 1000000;
  let valleys = 0;
  let isInValley;
  s = (typeof s === 'string') ? s.split('') : s;

  if (s.length >= min && s.length <= max &&
    n === parseInt(n, 0) &&
    n >= min &&
    n <= max &&
    n === s.length) {
    s.map(steps => ((steps === "U") ? 1 : -1))
      .reduce((prev, next) => {
        if (prev < 0 && !isInValley) {
          isInValley = true;
        }
        if ((prev + next) === 0 && isInValley) {
          valleys++;
          isInValley = false;
        }

        return prev + next;
      });

  }
  return valleys;

}