Я решил 45 проблем с 4clojure.com, и я заметил повторяющуюся проблему в том, как я пытаюсь решить некоторые проблемы, используя рекурсию и аккумуляторы.
Я попытаюсь объяснить лучшее, что могу, что я делаю, чтобы в конечном итоге получить верные решения, надеясь, что некоторые Clojurers будут "получать" то, что я не получаю.
Например, проблема 34 просит записать функцию (без использования диапазона), взяв два целых числа в качестве аргументов и создав диапазон (без использования диапазона). Проще говоря, вы делаете (... 1 7) и получаете (1 2 3 4 5 6).
Теперь речь идет не о решении этой конкретной проблемы.
Что делать, если я хочу решить эту проблему с помощью рекурсии и аккумулятора?
Мой процесс мышления выглядит следующим образом:
-
Мне нужно написать функцию, принимающую два аргумента, я начинаю с (fn [x y])
-
Мне нужно будет записаться, и мне нужно будет отслеживать список, я буду использовать накопитель, поэтому я пишу 2-ю функцию внутри первой, которая принимает дополнительный аргумент:
(п [x y]
((fn g [x y acc]...) Икс Y "())
(видимо, я не могу правильно отформатировать этот код Clojure на SO!?)
Здесь я уже не уверен, что делаю это правильно: первая функция должна принимать ровно два целых аргумента (не мой вызов), и я не уверен: если я хочу использовать аккумулятор, могу ли я использовать аккумулятора без создания вложенной функции?
Затем я хочу соединить, но я не могу:
(conj 0 1)
поэтому я делаю странные вещи, чтобы убедиться, что у меня есть последовательность, и в итоге я получаю следующее:
(fn
[x y]
((fn g [x y acc] (if (= x y) y (conj (conj acc (g (inc x) y acc)) x)))
x
y
'()))
Но тогда это произведет это:
(1 (2 (3 4)))
Вместо этого:
(1 2 3 4)
Итак, я в конечном итоге делаю дополнительную сглаживание, и это работает, но это абсолютно некрасиво.
Я начинаю понимать несколько вещей, и в некоторых случаях я даже начинаю "думать" более clojuresque, но у меня есть проблема с написанием решения.
Например, я решил:
- использовать накопитель
- для рекурсии путем увеличения x до достижения y
Но я в конечном итоге с монстрами выше.
Есть много способов решить эту проблему, и, опять же, это не то, что мне нужно.
То, что я за то, как после того, как я решил cons/conj, использовать аккумулятор и рекурсировать, я могу закончить с этим (не написано мной):
#(loop [i %1
acc nil]
(if (<= %2 i)
(reverse acc)
(recur (inc i) (cons i acc))))
Вместо этого:
((fn
f
[x y]
(flatten
((fn
g
[x y acc]
(if (= x y) acc (conj (conj acc (g (inc x) y acc)) x)))
x
y
'())))
1
4)
Я начинаю решать несколько проблем, но я немного разочарован уродливыми решениями, которые я имею в виду...