Как заменить Java, вложенный в циклы в Clojure? - PullRequest
12 голосов
/ 04 февраля 2012

Я создал очень простой пример вложенного цикла и пытаюсь написать эквивалентный код Clojure.Я пытался сделать это с помощью понимания списка, но не могу получить тот же ответ.Любая помощь приветствуется.

public class Toy {

    public static void main(String[] args) {
        int maxMod = 0;
        for (int i=0;i<1000;i++) {
            for (int j=i;j<1000;j++) {
                if ((i * j) % 13 == 0 && i % 7 == 0) maxMod = i * j;
            }
        }
        System.out.println(maxMod);
    }
}

Ответы [ 3 ]

22 голосов
/ 04 февраля 2012

Вот решение для понимания списка:

(last 
  (for [i (range 1000) 
        j (range 1000)
        :let [n (* i j)] 
        :when (and (= (mod n 13) 0) 
                   (= (mod i 7) 0))] 
    n))
7 голосов
/ 04 февраля 2012

В общем, вы хотите использовать какую-то последовательность операций (например, ответ dnolen). Однако, если вам нужно сделать что-то, что не может быть выражено в некоторой комбинации функций последовательности, использование макроса loop также работает. Для этой точной проблемы, ответ dnolen лучше, чем что-либо, использующее loop, но для наглядности, вот как бы вы написали его с loop.

(loop [i 0
       max-mod 0]
  (if (>= i 1000)
    (println max-mod)
    (recur (inc i)
           (loop [j 0
                  max-mod max-mod]
             (if (>= j 1000)
               max-mod
               (recur (inc j)
                      (if (and (= (mod (* i j) 13) 0)
                               (= (mod 1 7) 0))
                        (* i j)
                        max-mod)))))))

Это почти точный перевод вашего кода. Тем не менее, это, очевидно, некрасиво, поэтому решение, использующее for (или другие подобные функции), всегда предпочтительнее.

1 голос
/ 07 февраля 2012

Понимания списков создают списки из других списков, но в качестве результата вы хотите использовать только одно значение. Вы можете создать входные значения (i и j) с использованием списка, а затем использовать reduce, чтобы получить одно значение из списка:

(reduce (fn [max-mod [i j]]
          (if (and (zero? (mod (* i j) 13))
                   (zero? (mod i 7)))
            (* i j)
            max-mod))
        0
        (for [i (range 1000) j (range 1000)]
             [i j]))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...