Clojure从Java翻译

Clojure从Java翻译,clojure,Clojure,我开始学习Clojure,并决定在HackerRank上做一些项目是一个很好的方法。我发现我的Clojure解决方案非常慢。我认为这是因为我仍然在思考,或者只是对Clojure的运作方式了解不够。我写的最新问题解决方案是零II。这是我的Java代码 import java.io.BufferedReader; import java.io.InputStreamReader; public class Solution { private static final int MAX_NU

我开始学习Clojure,并决定在HackerRank上做一些项目是一个很好的方法。我发现我的Clojure解决方案非常慢。我认为这是因为我仍然在思考,或者只是对Clojure的运作方式了解不够。我写的最新问题解决方案是零II。这是我的Java代码

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Solution {
    private static final int MAX_NUMBER = 1000000;
    private static final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

    public static int[] precompute() {
        int[] values = new int[MAX_NUMBER];

        values[0] = 0;
        values[1] = 1;

        for (int i = 1; i < MAX_NUMBER; i += 1) {
            if ((values[i] == 0) || (values[i] > (values[i - 1] + 1))) {
                values[i] = (values[i - 1] + 1);
            }

            for (int j = 1; j <= i && (i * j) < MAX_NUMBER; j += 1) {
                int mult = i * j;

                if ((values[mult] == 0) || (values[mult] > (values[i] + 1))) {
                    values[mult] = values[i] + 1;
                }
            }
        }

        return values;
    }

    public static void main(String[] args) throws Exception {
        int numQueries = Integer.parseInt(reader.readLine());

        int[] values = Solution.precompute();

        for (int loop = 0; loop < numQueries; loop += 1) {
            int query = Integer.parseInt(reader.readLine());
            System.out.println(values[query]);
        }
    }
}
导入java.io.BufferedReader;
导入java.io.InputStreamReader;
公共类解决方案{
私有静态最终整数最大值=1000000;
私有静态最终BufferedReader reader=新的BufferedReader(新的InputStreamReader(System.in));
公共静态int[]预计算(){
int[]值=新int[MAX_NUMBER];
数值[0]=0;
数值[1]=1;
对于(int i=1;i(值[i-1]+1))){
值[i]=(值[i-1]+1);
}
对于(int j=1;j(值[i]+1))){
数值[mult]=数值[i]+1;
}
}
}
返回值;
}
公共静态void main(字符串[]args)引发异常{
int-numquerys=Integer.parseInt(reader.readLine());
int[]value=Solution.precompute();
for(int-loop=0;loop
我的Clojure实现是

(def MAX-NUMBER 1000000)

(defn set-i [out i]
(cond
    (= 0 i) (assoc out i 0)
    (= 1 i) (assoc out i 1)
    (or (= 0 (out i))
        (> (out i) (inc (out (dec i)))))
    (assoc out i (inc (out (dec i))))
    :else out))

(defn set-j [out i j]
(let [mult (* i j)]
    (if (or (= 0 (out mult)) (> (out mult) (inc (out i))))
    (assoc out mult (inc (out i)))
    out)))

;--------------------------------------------------
; Precompute the values for all possible inputs
;--------------------------------------------------
(defn precompute []
(loop [i 0 out (vec (repeat MAX-NUMBER 0))]

    (if (< i MAX-NUMBER)
    (recur (inc i) (loop [j 1 new-out (set-i out i)]
                    (if (and (<= j i) (< (* i j) MAX-NUMBER))
                        (recur (inc j) (set-j new-out i j))
                        new-out)))
    out)))

;--------------------------------------------------
; Read the number of queries
;--------------------------------------------------
(def num-queries (Integer/parseInt (read-line)))

;--------------------------------------------------
; Precompute the solutions
;--------------------------------------------------
(def values (precompute))

;--------------------------------------------------
; Read and process each query
;--------------------------------------------------
(loop [iter 0]
(if (< iter num-queries)
    (do
    (println (values (Integer/parseInt (read-line))))
    (recur (inc iter)))))
(def最大数量1000000)
(第i组定义[第i组]
(续)
(=0 i)(关联输出i 0)
(=1 i)(助理执行官1)
(或(=0(出i))
(>(out i)(inc)(out(dec i((dec i)))))
(第一部门助理(包括第一部门助理)
:否则请退出)
(定义设置-j[输出i j]
(让[mult(*i j)]
(如果(或(=0(out mult))(>(out mult)(inc(out i)))
(外部多部门助理(公司(外部一)))
(出)
;--------------------------------------------------
; 预计算所有可能输入的值
;--------------------------------------------------
(defn预计算[]
(循环[i 0输出(vec(重复最大编号0))]
(如果((如果(和(我将对您的代码进行一些转换(这可能稍微超出您最初的要求)
然后回答你更具体的问题

我知道差不多是两年后了,但在遇到你的问题并花了太多时间和你争论之后 HackerRank及其时间限制,我想我会发布一个答案。在人力资源环境和 时间限制让我们成为更好的Clojure程序员?我没有学到这个问题的答案。但我将分享我学到的东西

我发现你的算法有一个稍微精简的版本。它仍然有两个循环,但是更新只在一个月内发生一次 内部循环和许多条件在
min
函数中处理。以下是我对它的改编:

(defn compute
  "Returns a vector of down-to-zero counts for all numbers from 0 to m."
  [m]
  (loop [i 2 out (vec (range (inc m)))]
    (if (<= i m)
      (recur (inc i)
             (loop [j 1 out out]
               (let [ij (* i j)]
                 (if (and (<= j i) (<= ij m))
                   (recur (inc j) 
                          (assoc out ij (min (out ij)               ;; current value
                                             (inc (out (dec ij)))   ;; steps from value just below
                                             (inc (out i)))))       ;; steps from a factor
                   out))))
      out)))

你是如何运行你的代码的?你是在使用
lein
,将.clj文件传递给
clojure
还是其他方式?我只是想补充:我没有看问题陈述,但是你在使用
loop/recur
进行迭代。clojure更喜欢
进行
reduce
map
。还有更多的方法如果你想寻找clojure性能提示,NG喜欢类型提示。
(vec(repeat 1e6 0))
非常昂贵。它正在创建一个充满0的百万元素向量。这在我欠时钟的手机上只需要整整一秒钟。
(int array 1e6 0)
另一方面需要14毫秒。如果你真的需要存储那么多数据,数组可能是更好的选择。不过,我看不出你的代码中有任何过于低效的地方。不过我会说,如果你把它发布在code Review上,如果你愿意的话,我会在明天对它进行审查。看起来我可以在一些地方这样做提出建议。从我读到的一些东西来看,我得到的印象是循环/recur的性能比reduce好。它基本上是一个嵌套的循环,设置了[I],然后对于j,似乎应该使用map,但我看不出如何让map设置多个值,或者如何链接它,以便生成的向量具有正确的条目。
(ns down-to-zero-int-array)

(set! *warn-on-reflection* true)

(defn compute
  "Returns a vector of down-to-zero counts for all numbers from 0 to m."
  ^ints [m]
  (let [out ^ints (int-array (inc m) (range (inc m)))]
    (doseq [i (range 2 (inc m)) j (range 1 (inc i)) :let [ij (* i j)] :while (<= ij m)]
      (aset out ij (min (aget out ij)
                        (inc (aget out (dec ij)))
                        (inc (aget out i)))))
    out))

(let [tokens ^java.io.StreamTokenizer 
      (doto (java.io.StreamTokenizer. (java.io.BufferedReader. *in*))
        (.parseNumbers))]
  (defn next-int []
    "Read next integer from input. As fast as `read-line` for a single value, 
     and _much_ faster than `read-line`+`split` for multiple values on same line."
    (.nextToken tokens)
    (int (.-nval tokens))))

(def MAX 1000000)

(let [q (next-int)
      down-to-zero (compute MAX)]
  (doseq [n (repeatedly q next-int)]
    (println (aget down-to-zero n))))