编辑看来,我发现了Michal注意到的常见瞬态陷阱
我对clojure很新,并且正在尝试解决项目euler:14在功能样式中没有完全计算每个999999个collatz序列。即从10开始的collatz链:
10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
因为这样的长度(10)= 7
如果我然后查看9的collatz链,我应该按照以下步骤进行:
9 -> 28 -> 14 -> 7 -> 22 -> 11 -> 34 -> 17 -> 52 -> 26 -> 13 -> 40 -> 20 -> 10 ***stop since I should have stored length(collatz(10)) somewhere***
我将从中得到那个长度的collatz(9)= 13 + 7
为此,我想要一个collatz链中的每个节点,以存储其相关的collatz长度,并且一旦我看到我踩到同一个地面就会中断。如果我做对了,我希望这应该是线性的(我只需要在范围内看[bound,bound / 2])
我的第一个"尝试(忽略那些没有希望的东西(如反向构建)):
(defn _collatz [n dict]
(cond (contains? dict n) (list n (dict n))
(> n 1) (let [temp (_collatz (if (zero? (mod n 2)) (/ n 2) (+ (* 3 n) 1)) dict)
ret (cons n (cons (inc (second temp)) temp))] ret)
true '(1 1)))
(defn collatz [n & {:keys [dict] :or {dict {}}}]
(conj (apply hash-map (_collatz n dict)) dict))
(defn largest-collatz [bound]
(let [all-chain-lengths ((apply comp (map #(partial collatz % :dict) (range bound (+ (/ bound 2) 2) -1))) {})]
... gave up implementing this bit ...
all-chain-lengths))
这是二次约束(我相信这是因为每次传递走下一些列表,形成一个字典,然后将它连接到我刚刚传入的字典 - 做这个O(n操作O(n)次。我已经放弃了它(例如,返回将与其他dicts结合的dicts等等)因为我认为返回并加入任何集合是n ^ 2 - 我需要创建一个字典并在适当的位置更新它)
我的第二次尝试是:
(defn _collatz2 [n dict]
(cond (not (nil? (get dict n))) (get dict n)
(> n 1) (let [len (inc (_collatz2 (if (zero? (mod n 2)) (/ n 2) (+ (* 3 n) 1))
dict))]
(assoc! dict n len)
(println (str "with n equal to " n ", returning: " len " - n is in dict?? (get dict " n "): " (get dict n)))
len)
true 1))
如果按照以下方式在repl中调用:
(def a (transient {}))
(_collatz2 99 a)
(persistent! a)
得到我:
{2 2,4 3,8 4,16 5,5 6,10 7,20 8,40 9}
我很难过这里发生的事情。调试输出是:
with n equal to 2, returning: 2 - n is in dict?? (get dict 2): 2
with n equal to 4, returning: 3 - n is in dict?? (get dict 4): 3
with n equal to 8, returning: 4 - n is in dict?? (get dict 8): 4
with n equal to 16, returning: 5 - n is in dict?? (get dict 16): 5
with n equal to 5, returning: 6 - n is in dict?? (get dict 5): 6
with n equal to 10, returning: 7 - n is in dict?? (get dict 10): 7
with n equal to 20, returning: 8 - n is in dict?? (get dict 20): 8
with n equal to 40, returning: 9 - n is in dict?? (get dict 40): 9
with n equal to 13, returning: 10 - n is in dict?? (get dict 13):
with n equal to 26, returning: 11 - n is in dict?? (get dict 26):
with n equal to 52, returning: 12 - n is in dict?? (get dict 52):
with n equal to 17, returning: 13 - n is in dict?? (get dict 17):
with n equal to 34, returning: 14 - n is in dict?? (get dict 34):
with n equal to 11, returning: 15 - n is in dict?? (get dict 11):
with n equal to 22, returning: 16 - n is in dict?? (get dict 22):
with n equal to 7, returning: 17 - n is in dict?? (get dict 7):
with n equal to 14, returning: 18 - n is in dict?? (get dict 14):
with n equal to 28, returning: 19 - n is in dict?? (get dict 28):
with n equal to 56, returning: 20 - n is in dict?? (get dict 56):
with n equal to 112, returning: 21 - n is in dict?? (get dict 112):
with n equal to 224, returning: 22 - n is in dict?? (get dict 224):
with n equal to 448, returning: 23 - n is in dict?? (get dict 448):
with n equal to 149, returning: 24 - n is in dict?? (get dict 149):
with n equal to 298, returning: 25 - n is in dict?? (get dict 298):
with n equal to 99, returning: 26 - n is in dict?? (get dict 99):
有人有什么想法吗?