2

そのようなものを取得するための慣用的な方法は何ですか?

(fn [coll] (function body) [1 0 -1 -1 -1 0 0 0 0 1 1 1 1 1 0 1 -1])
-> [1 1 3 2 1 4 3 2 1 5 4 3 2 1 1 1 1]

こんな風にしかできない。

(fn [coll] 
  (loop [i 0 r []]
    (if (< i (count coll))
      (let [elem (nth coll i)
            cc (loop [j 1]
                 (if (< (+ i j) (dec (count coll)))
                   (let [nelem (nth coll (+ i j))]
                     (if (= elem nelem)
                       (recur (inc j))
                       j))
                   j))]
        (recur (inc i) (conj r cc)))
      r)))
4

4 に答える 4

4

@noisesmith のきちんとした解決策を、私たちが問題だと思っていたものに変更します。

(defn countdown-runs [s]
  (->> s
       (partition-by identity)
       (map count)
       (mapcat #(range % 0 -1))))

例えば、

(countdown-runs [1 0 -1 -1 -1 0 0 0 0 1 1 1 1 1 0 1 -1])
; (1 1 3 2 1 4 3 2 1 5 4 3 2 1 1 1 1)
于 2014-05-17T16:30:32.903 に答える
0

提供されたソリューションをいくつかの方法で整理できます。

  • index の代わりに、iで始まるサブベクトルをi外側のループの引数として使用します。これにより、コードが理解しやすくなります。
  • 簡潔にするために、(v j)代わりにを使用して の番目の要素(nth v j)を取得します。 jv
  • and内側のループの制御構造を単純化するために使用します。
  • (そして - 私たちがそれに取り組んでいる間 -dec繰り返される値で終わるシーケンスの 1 回限りのエラーを引き起こす を削除します。)

これにより、

(defn op-s [v] 
  (loop [v v, r []]
    (if (seq v)
      (let [elem (v 0)
            cc (loop [j 1]
                 (if (and (< j (count v)) (= elem (v j)))
                   (recur (inc j))
                   j))]
        (recur (subvec v 1) (conj r cc)))
      r)))

これはまだ遅くなる可能性があります。長さ n のランの場合、内側のループを約 n 2 /2 回実行します。これをスピードアップできます。実行が見つかったら、遅延バージョンと同様に、その長さからカウントダウンできます。

(defn op-s [v] 
  (loop [v v, r []]
    (if (seq v)
      (let [elem (v 0)
            cc (loop [j 1]
                 (if (and (< j (count v)) (= elem (v j)))
                   (recur (inc j))
                   j))
            rr (loop [r r, i cc] (case i, 0 r, (recur (conj r i) (dec i))))]
        (recur (subvec v cc) rr))
      r)))
于 2014-05-17T17:00:08.130 に答える