我实施了一个天真的解决方案,用于打印Pascal三角形的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))))))
答案 0 :(得分:8)
(defn pascal []
(iterate (fn [row]
(map +' `(0 ~@row) `(~@row 0)))
[1]))
或者如果你想要最大限度的简洁:
(defn pascal []
(->> [1] (iterate #(map +' `(0 ~@%) `(~@% 0)))))
要扩展这一点:高阶函数透视图是查看原始定义并实现类似:“我实际上只是在初始值上计算函数f
,然后调用{ {1}}再次,然后f
再次......“。这是一个常见的模式,因此定义了一个函数来覆盖您的枯燥细节,让您只需指定f
和初始值。并且因为它返回 lazy 序列,所以您现在不必指定f
:您可以推迟,并使用完整的无限序列,以及您想要的任何终止条件。
例如,也许我不想要第一行n
,我只想找到第一行,其总和是一个完美的正方形。然后我可以n
,而不必担心(first (filter (comp perfect-square? sum) (pascal)))
我需要预先选择多大(假设明确定义n
和perfect-square?
)。
感谢大家的改进:我需要使用sum
而不仅仅是+'
,以便在超过+
时不会溢出。
答案 1 :(得分:5)
(defn next-row [row]
(concat [1] (map +' row (drop 1 row)) [1]))
(defn pascals-triangle [n]
(take n (iterate next-row '(1))))
答案 2 :(得分:1)
不像其他人那样简洁,但这是我的:)
(defn A []
(iterate
(comp (partial map (partial reduce +))
(partial partition-all 2 1) (partial cons 0))
[1]))