4

次の条件が見つかり、リストされた結果が返されるまで値を生成するだけのシーケンスを作成しようとしています。

ケースヘッド=

  • 0-戻り値{:origin [0を除くすべてが生成されます]:pattern 0}
  • 1-{:origin nil:pattern[all-generated-values]}を返します
  • 繰り返し値-{:origin [values-before-repeat]:pattern [values-after-repeat]

{{

; n = int
; x = int
; hist - all generated values

; Keeps the head below x 
(defn trim-head [head x]
  (loop [head head]
    (if (> head x)
      (recur (- head x))
      head)))

; Generates the next head
(defn next-head [head x n]
  (trim-head (* head n) x))

(defn row [x n]
   (iterate #(next-head % x n) n))

; Generates a whole row - 
; Rows are a max of x - 1.
(take (- x 1) (row 11 3))

行の終わりに達する前に停止するケースの例:

[9 8 4 5 6 7 4 ]-「4」が繰り返されるので、停止します。前を原点として返し、残りをパターンとして返します。

{:origin [9 8] :pattern [4 5 6 7]}

[4 5 6 1]-「1」が見つかったのでSTOPなので、すべてをパターンとして返します

{:origin nil :pattern [4 5 6 1]}

[ 30 ]-「0」が見つかったので停止します

{:origin [3] :pattern [0]}

:それ以外の場合、シーケンスがx-1の長さに達した場合:

{:origin [all values generated] :pattern nil}

問題

繰り返し値が見つかった時点でグループを分割するためにpartition-byを使用して成功しましたが、これを怠惰に実行したいと思います。take-while、condp、またはforループの:while句を使用して、繰り返しが見つかったときにパーティション化する条件を作成する方法はありますか?

いくつかの試み

(take 2 (partition-by #(= 1 %) (row 11 4)))

(for [p (partition-by #(stop-match? %) head) (iterate #(next-head % x n) n)
        :while (or (not= (last p) (or 1 0 n) (nil? (rest p))]
  {:origin (first p) :pattern (concat (second p) (last p))}))

#アップデート

私が本当にやりたいのは、値が繰り返されているかどうかを調べ、インデックスを使用せずにseqを分割することです。それは可能ですか?このようなもの -

{{

(defn row [x n]
  (loop [hist [n]
         head (gen-next-head (first hist) x n)
         steps 1]
    (if (>= (- x 1) steps)
      (case head
        0 {:origin [hist] :pattern [0]}
        1 {:origin nil :pattern (conj hist head)}
        ; Speculative from here on out 
        (let [p (partition-by #(apply distinct? %) (conj hist head))]
          (if-not (nil? (next p)) ; One partition if no repeats.
            {:origin (first p) :pattern (concat (second p) (nth 3 p))}
            (recur (conj hist head) (gen-next-head head x n) (inc steps)))))
      {:origin hist :pattern nil})))

}

4

2 に答える 2

1

私が本当にやりたいことは、値が繰り返されているかどうかを調べ、インデックスを使用せずに seq を分割することです。それは可能ですか?

更新された要件をすぐに実装しました。この場合、 よりも のsplit-with方が望ましいでしょうpartition-by

;;; find out if a value has repeated, but considering zero and one.
(defn- generate
  "Returns a vector of [duplicate-value values-until-duplicate].
   duplicate-value might be zero or one."
  [s]
  (->> [s [] #{0 1}]
       (iterate (fn [[[head & more] generated idx]]
                  [more (conj generated head) (conj idx head)]))
       (take-while (comp seq first))
       (drop-while (fn [[[head & _] _ idx]]
                     (nil? (idx head))))
       first
       ((juxt ffirst second))))

;;; partition the seq without using the index.
(defn partition-by-duplicate
  [s]
  (let [[pivot generated-values] (generate s)]
    (cond (= 0 pivot) {:origin generated-values, :pattern [0]}
          (= 1 pivot) {:origin nil, :pattern (conj generated-values 1)}
          pivot (->> generated-values
                     (split-with (partial not= pivot))
                     (interleave [:pattern :origin])
                     (apply hash-map))
          :else {:origin s, :pattern nil})))

例:

user> (map generate [[9 8 2 4 5 6 7 4] [4 5 6 1] [3 0]])
([4 [9 8 2 4 5 6 7]]
 [1 [4 5 6]]
 [0 [3]])

user> (map partition-by-duplicate [[9 8 2 4 5 6 7 4] [4 5 6 1] [3 0]])
({:pattern (9 8 2), :origin (4 5 6 7)}
 {:origin nil, :pattern [4 5 6 1]}
 {:origin [3], :pattern [0]})
于 2012-10-28T05:55:57.033 に答える
1

新しい要素を遅延して消費することはできますが、パターンとして使用するにはすべての古い要素にしがみつく必要があるため、シーケンスのようなものでは、(iterate inc 2)使用可能なすべてのメモリを消費する必要があります。さらに、for一度に 1 つの要素しか表示できないため、このタスクには適していません。ただし、ループ/再帰として記述するのは少し面倒ですが、難しくありません。シーケンスが繰り返し、1、または 0 の前に終了した場合に何を返すかを指定しなかったので、推測しました。

また、最初の出力例は間違っています。4 ではなく 1 で停止する必要があるため、入力を調整しました。ただし、それとは別に、よくある質問があります。問題を明確に特定し、何に問題があり、何を試したかを説明してくれてありがとう。

(defn trim-head [coll]                                                      
  (loop [so-far [], indexes {}, index 0, coll (seq coll)]                   
    (if-not coll                                                            
      {:origin nil, :pattern so-far} ;; ?? not specified in question        
      (let [x (first coll), xs (rest coll)]                                 
        (if (contains? indexes x)                                           
          {:origin (subvec so-far 0 (indexes x))                            
           :pattern (subvec so-far (indexes x))}                            
          (case x                                                           
            0 {:origin so-far, :pattern [x]}                                
            1 {:origin nil, :pattern (conj so-far x)}                       
            (recur (conj so-far x) (assoc indexes x index) (inc index) (seq xs))))))))

user> (map trim-head [[9 8 2 4 5 6 7 4] [4 5 6 1] [3 0]])                       
({:origin [9 8 2], :pattern [4 5 6 7]}
 {:origin nil, :pattern [4 5 6 1]} 
 {:origin [3], :pattern [0]})
于 2012-10-26T05:06:23.323 に答える