문제

I implemented a naive solution for printing a Pascal's Triangle of N depth which I'll include below. My question is, in what ways could this be improved to make it more idiomatic? I feel like there are a number of things that seem overly verbose or awkward, for example, this if block feels unnatural: (if (zero? (+ a b)) 1 (+ a b)). Any feedback is appreciated, thank you!

(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))))))
도움이 되었습니까?

해결책

(defn pascal []
  (iterate (fn [row]
             (map +' `(0 ~@row) `(~@row 0)))
           [1]))

Or if you're going for maximum concision:

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

To expand on this: the higher-order-function perspective is to look at your original definition and realize something like: "I'm actually just computing a function f on an initial value, and then calling f again, and then f again...". That's a common pattern, and so there's a function defined to cover the boring details for you, letting you just specify f and the initial value. And because it returns a lazy sequence, you don't have to specify n now: you can defer that, and work with the full infinite sequence, with whatever terminating condition you want.

For example, perhaps I don't want the first n rows, I just want to find the first row whose sum is a perfect square. Then I can just (first (filter (comp perfect-square? sum) (pascal))), without having to worry about how large an n I'll need to choose up front (assuming the obvious definitions of perfect-square? and sum).

Thanks to fogus for an improvement: I need to use +' rather than just + so that this doesn't overflow when it gets past Long/MAX_VALUE.

다른 팁

(defn next-row [row]
  (concat [1] (map +' row (drop 1 row)) [1]))

(defn pascals-triangle [n]
  (take n  (iterate next-row '(1))))

Not as terse as the others, but here's mine:)

(defn A [] 
  (iterate 
    (comp (partial map (partial reduce +)) 
      (partial partition-all 2 1) (partial cons 0))
        [1]))
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top