Ответ 1
Вот решение для понимания списка:
(last
(for [i (range 1000)
j (range 1000)
:let [n (* i j)]
:when (and (= (mod n 13) 0)
(= (mod i 7) 0))]
n))
Я создал очень простой пример вложенного цикла и изо всех сил пытаюсь написать эквивалентный код 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);
}
}
Вот решение для понимания списка:
(last
(for [i (range 1000)
j (range 1000)
:let [n (* i j)]
:when (and (= (mod n 13) 0)
(= (mod i 7) 0))]
n))
В общем, вы хотите использовать некоторую операцию последовательности (например, dnolen answer). Однако, если вам нужно сделать что-то, что не выражено в некоторой комбинации функций последовательности, также работает макрос 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
(или другие подобные функции), является предпочтительным, когда это возможно.
Сопоставление списков создает списки из других списков, но вы хотите получить только одно значение. Вы можете создать входные значения (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]))