HackerRank比较Triplets Clojure

时间:2018-02-15 20:17:37

标签: clojure

我无法解释为什么原子引用不保留inc的值。

1)如何纠正这个? 2)为什么在调试模式下它似乎给出了正确的值?

我知道这可能不是最佳解决方案,但想要理解为什么它不起作用。

你的任务是通过比较a0与b0,a1与b1和a2与b2来找到他们的比较点。

如果a大于b,那么Alice将获得积分。 如果a小于b,则Bob获得积分。 如果a等于b,那么两个人都不会得到一个点。

(defn compare-the-triplets
  [alice bob]
  (let [alice-score (atom 0)
        bob-score (atom 0)]
    (for [i (range 3)]
      (let [a (get alice i)
            b (get bob i)]
        (cond
          (> a b) (swap! alice-score inc)
          (< a b) (swap! bob-score inc))
        )) [@alice-score @bob-score]))

(compare-the-triplets [5 6 7] [3 6 10])

当我运行它时,它为Atom返回0和0。我觉得这可能不是最好的答案,但它真的很烦人为什么调试工作并获得正确值的原子,但然后他们没有正确返回。

使用let和for的范围一定不正确。

2 个答案:

答案 0 :(得分:5)

这是冒险进入审查领域,但我认为应该强调原子在这里不是正确的工具。没有任何副作用泄漏,但是它们的使用不必要地使所有东西膨胀,并且违背了常见的功能实践。

由于这基本上只是一种减少,我认为这是最好的。你有一个集合(或者在这种情况下,有两个),需要积累一个值(或者再次,在这种情况下,两个)。无论何时出现这种情况,都应该想到reduce

(defn compare-the-triplets2 [alice bob]
  (reduce (fn [scores [al bo]]
            ; If the condition on the left is true, update either the 0th or 1st score
            (cond-> scores
              (> al bo) (update 0 inc)
              (< al bo) (update 1 inc)))

          ; Both start with a score of 0
          [0 0]

          ; Zip alice and bob together, then reduce over the zipped collection
          (map vector alice bob)))

关系可能会使事情复杂化,但cond->处理得很好。不幸的是,cond->并不像cond那样短路,所以效率会略低一些。除非这被证明是时间关键代码,否则时差应该是可以忽略不计的。

请注意update的使用情况,以及它与您使用swap!的相似程度。在这种情况下,我使用0和1来指示向量累加器中的哪个得分递增。

答案 1 :(得分:1)

你是对的!

产生懒惰序列:http://clojuredocs.org/clojure.core/for

请参阅文档中使用dorun,或使用doseq代替for。