3

以下に含める深さ 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))))))
4

3 に答える 3

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

または、最大限の簡潔さを求めている場合:

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

これを拡張するには: 高階関数の観点は、元の定義を見て、次のようなものを実現するfことfですf。 . これは一般的なパターンなので、退屈な詳細をカバーするために定義された関数がfあり、初期値を指定するだけです。また、遅延シーケンスを返すため、ここで指定する必要はありませんn。それを延期して、任意の終了条件で完全な無限シーケンスを操作できます。

たとえば、おそらく最初の行は必要ありませんn。合計が完全な平方になる最初の行を見つけたいだけです。次に、事前に を選択する必要がある(first (filter (comp perfect-square? sum) (pascal)))大きさについて心配することなく、 を実行できnます ( と の定義が明白であるperfect-square?と仮定しますsum)。

改善のための fogus に感謝+'+ますLong/MAX_VALUE

于 2013-06-28T04:15:09.257 に答える
5
(defn next-row [row]
  (concat [1] (map +' row (drop 1 row)) [1]))

(defn pascals-triangle [n]
  (take n  (iterate next-row '(1))))
于 2013-06-28T04:04:54.233 に答える