Последовательность "взгляд в будущее"
Пример того, как в будущее можно смотреть в стиле фанк, может выглядеть так:
(def funky-seq
(let [substrate (atom ())]
(letfn [(funk [n] (delay (if (odd? n) n @(nth @substrate (inc n)))))]
(reset! substrate (map funk (range))))
(map deref @substrate)))
user> (take 10 funky-seq)
(1 1 3 3 5 5 7 7 9 9)
(Cookie для тех, кто делает это проще, не нарушая его.: -))
Конечно, если определение значения элемента может включать рассмотрение «будущего» элемента, который сам зависит от дополнительного элемента, который требует вычисления еще более отдаленного элемента ..., катастрофа не может помочь.
Эйлер 14
Фундаментальная проблема со схемой «заглядывания в будущее», которую код из вопроса пытается использовать в стороне, этот подход на самом деле не решает проблему, потому что, если вы решите начать с 1
и идти вверх , вам нужно принять во внимание разветвление: 10
в цепочке Коллатца может быть получен путем применения любого из правил (правило n / 2
, применяемое к 20
или правило 3n + 1
начиная с 3
). Кроме того, если вы хотите построить свои цепочки вверх, вы должны изменить правила и либо умножить на 2
, либо вычесть 1
и разделить на 3
(применяя на каждом шаге то правило, которое дает целое число - или возможно оба, если оба делают).
Конечно, вы можете построить дерево , а не ленивый список, но это не будет похоже на набросок кода в вопросе, и я ожидаю, что вы в конечном итоге запомните вещь .
Вышеприведенное должно быть дополнено замечанием о том, что у вас может быть предположение о том, какое «правило построения цепочки» может генерировать самую длинную цепочку, начиная с 1
, при этом конечная запись остается ниже заданного предела. Если это так, вы, вероятно, должны доказать, что он правильный , а затем реализовать его напрямую (через loop
/ recur
, начиная с 1
); без доказательства вы не сможете утверждать, что решили проблему.