【问题标题】:What's a more idiomatic and concise way of writing Pascal's Triangle with Clojure?用 Clojure 编写帕斯卡三角形的更惯用和简洁的方式是什么?
【发布时间】:2013-06-25 18:25:20
【问题描述】:

我实现了一个简单的解决方案来打印 N 深度的帕斯卡三角形,我将在下面介绍它。我的问题是,可以通过哪些方式对其进行改进以使其更加惯用?我觉得有很多事情看起来过于冗长或尴尬,例如,这个if 块感觉不自然:(if (zero? (+ a b)) 1 (+ a b))。感谢您的任何反馈,谢谢!

(defn add-row [cnt acc]
  (let [prev (last acc)]
    (loop [n 0 row []]
      (if (= n cnt)
        row
        (let [a (nth prev (- n 1) 0)
              b (nth prev n 0)]
          (recur (inc n) (conj row (if (zero? (+ a b)) 1 (+ a b)))))))))


(defn pascals-triangle [n]
  (loop [cnt 1 acc []]
    (if (> cnt n)
      acc
      (recur (inc cnt) (conj acc (add-row cnt acc))))))

【问题讨论】:

    标签: clojure idioms pascals-triangle


    【解决方案1】:
    (defn pascal []
      (iterate (fn [row]
                 (map +' `(0 ~@row) `(~@row 0)))
               [1]))
    

    或者,如果您想要最大程度地简洁:

    (defn pascal []
      (->> [1] (iterate #(map +' `(0 ~@%) `(~@% 0)))))
    

    对此进行扩展:高阶函数的观点是查看您的原始定义并实现如下内容:“我实际上只是在初始值上计算函数f,然后调用f再次,然后f 再次......”。这是一种常见的模式,因此定义了一个函数来为您覆盖无聊的细节,让您只需指定f 和初始值。而且因为它返回一个 lazy 序列,所以您现在不必指定 n:您可以推迟它,并使用完整的无限序列,以及您想要的任何终止条件。

    例如,也许我不想要第一行n,我只想找到总和是完美平方的第一行。然后我可以只使用(first (filter (comp perfect-square? sum) (pascal))),而不必担心我需要预先选择多大的n(假设perfect-square?sum 的定义很明显)。

    感谢fogus 的改进:我需要使用+' 而不仅仅是+,这样它就不会在超过Long/MAX_VALUE 时溢出。

    【讨论】:

    • 您对 unquote-splicing 的使用可能也需要扩展 - 这很酷,但很神奇
    • 这将很快溢出。您可以将1N 添加到种子向量中以避免它,但它看起来不那么漂亮。虽然运行 (take 500 (pascal)) 在滚动时会在输出中显示一些有趣的类似正弦的模式。
    • 好点,笨蛋。我总是忘记在我的数学示例代码中这样做。我个人更喜欢+' 而不是N;我很好奇你是否特别喜欢N,如果是,为什么?
    • 感谢您的解释和漂亮的实现(@Ankur 的类似方法也很棒):我现在对我的方法感到非常愚蠢......
    • 另外,正如@fogus 提到的:(pprint (take 500 (->> '(1) (iterate #(map +' `(0 ~@%) `(~@% 0)))))) 非常好看。
    【解决方案2】:
    (defn next-row [row]
      (concat [1] (map +' row (drop 1 row)) [1]))
    
    (defn pascals-triangle [n]
      (take n  (iterate next-row '(1))))
    

    【讨论】:

    • 可能不会将其命名为next,因为它会影响clojure.core/next
    • @noahlz: 在下一行重命名.. 谢谢
    【解决方案3】:

    不像其他人那么简洁,但这是我的:)

    (defn A [] 
      (iterate 
        (comp (partial map (partial reduce +)) 
          (partial partition-all 2 1) (partial cons 0))
            [1]))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-07
      • 2012-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多