Clojure перевод с Java - PullRequest
       1

Clojure перевод с Java

0 голосов
/ 02 сентября 2018

Я начинаю изучать Clojure и решил, что выполнение некоторых проектов на HackerRank - хороший способ сделать это. Я обнаружил, что мои решения Clojure ужасно медленные. Я предполагаю, что это потому, что я все еще думаю об этом или просто недостаточно знаю, как работает Clojure. Последней проблемой, для которой я написал решение, был Down To Zero 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]);
        }
    }
}

Моя реализация 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)))))

Java-код выполняется на моей машине примерно за 1/10 секунды, а код Clojure - около 2 секунд. Поскольку это та же машина с той же JVM, это значит, что я делаю что-то не так в Clojure.

Как люди пытаются перевести этот тип кода? Какие ошибки заставляют его работать намного медленнее?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...