在重复时停止并拆分生成的序列 – clojure

我试图创建一个只会生成值的序列,直到找到以下条件并返回列出的结果:

案件头=

> 0 – 返回{:origin [除0以外的所有生成]:模式0}
> 1 – return {: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’如此停止,所以将所有内容作为模式返回

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

[3 0] – 发现’0’停止

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

:否则,如果序列达到x – 1的长度:

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

问题

我已经使用partition-by取得了一些成功,可以在找到重复值的位置拆分组,但是想懒得这么做.我有什么方法可以使用,
或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})))

}

最佳答案 懒惰是不可能的:你可以懒惰地消耗新元素,但你必须挂在所有旧元素上才能将它们用作模式,所以在像(iterate inc 2)这样的序列中你必须消耗所有可用的内存.此外,只有让你一次看一个元素,所以它不适合这个任务.然而,将其写为循环/重复是有点乏味的并不困难.如果序列在重复,1或0之前结束,则没有指定要返回的内容,所以我猜对了.

此外,您的第一个示例输出是错误的:它应该停在1而不是4,所以我调整了您的输入.除此之外,问题还很明确:感谢您明确指出问题,并描述您遇到的问题以及您尝试过的问题.

(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]})
点赞