瞬态地图未按预期更新

时间:2015-10-30 12:56:16

标签: dictionary clojure functional-programming

编辑看来,我发现了Michal注意到的常见瞬态陷阱

我对clojure很新,并且正在尝试解决项目euler:14在功能样式中没有完全计算每个999999个collat​​z序列。即从10开始的collat​​z链:

10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1

因为这样的长度(10)= 7

如果我然后查看9的collat​​z链,我应该按照以下步骤进行:

9 -> 28 -> 14 -> 7 ->  22 -> 11 -> 34 -> 17 -> 52 -> 26 -> 13 -> 40 -> 20 -> 10 ***stop since I should have stored length(collatz(10)) somewhere***

我将从中得到那个长度的collat​​z(9)= 13 + 7

为此,我想要一个collat​​z链中的每个节点,以存储其相关的collat​​z长度,并且一旦我看到我踩到同一个地面就会中断。如果我做对了,我希望这应该是线性的(我只需要在范围内看[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):

有人有什么想法吗?

0 个答案:

没有答案