Pregunta

En un programa Clojure, tengo una secuencia de números:

(2 3 4 6 8 1)

Quiero encontrar la más larga sub-secuencia en la que los artículos son secuenciales:

(2 3 4)

Estoy asumiendo que implicará (take-while ...) o (reduce ...).

¿Alguna idea?

Aclaración : Necesito la lista inicial más largo de los elementos secuenciales. Mucho más fácil, estoy seguro. Gracias por las soluciones al problema más difícil que inicialmente planteada.

¿Fue útil?

Solución

Si sólo está interesado en la secuencia inicial más largo, que es un 1-liner:

(defn longest-initial-sequence [[x :as s]]
  (take-while identity (map #(#{%1} %2) s (iterate inc x))))

Otros consejos

Teniendo en cuenta la Observación de la OP en la cuestión - que cambia por completo el juego! - esto puede ser escrita de manera muy sencilla:

(let [doubletons (partition 2 1 [1 2 3 5 6])
      increment? (fn increment? [[x y]]
                   (== (inc x) y))]
  (cons (ffirst doubletons)
        (map second (take-while increment? doubletons))))

;; returns (1 2 3)

Tenga en cuenta que esto es realmente perezoso. Espero que no se aferran a la cabeza de doubletons gracias a los locales de compensación. Otra versión:

(cons (first [1 2 3 5 6])
      (map second (take-while increment? (partition 2 1 [1 2 3 5 6]))))

La versión original de la pregunta es más divertido, sin embargo! :-) Una solución súper fácil de que podría ser construido utilizando el anterior, pero por supuesto que sería significativamente menos eficiente que el uso de reduce. Voy a ver si tengo algo sustancialmente diferente de soluciones de dnolen zmila de e - y aún así razonablemente performant - añadir a esa parte de este hilo después. (No es muy probable, supongo.)

respuesta a la original:

(defn conj-if-sequential
  ([] [])
  ([a] a)
  ([a b] (let [a (if (vector? a) a [a])]
           (if (= (inc (last a)) b)
             (conj a b)
             a))))

(reduce conj-if-sequential [2 3 4 6 8 1])

Una solución más genérica para los interesados:

(defn sequential-seqs
  ([] [])
  ([a] a)
  ([a b] (let [n (last (last a))]
           (if (and n (= (inc n) b))
             (update-in a [(dec (count a))] conj b)
             (conj a [b])))))

(defn largest
  ([] nil)
  ([a] a)
  ([a b] (if (> (count b) (count a)) b a)))

(reduce largest (reduce sequential-seqs [] [2 3 4 6 8 1 4 5 6 7 8 9 13]))

Creo que esto es mucho mejor.

(defn find-max-seq [lst]
  (let [[f & r] lst, 
        longest-seq (fn [a b] (if (> (count a) (count b)) a b)),
        [last-seq max-seq] (reduce 
                             (fn [ [[prev-num & _ :as cur-seq] max-seq] cur-num ]
                               (if (== (inc prev-num) cur-num) 
                                 [(conj cur-seq cur-num) max-seq]
                                 [(list cur-num) (longest-seq cur-seq max-seq)]
                                 ))
                             [(list f) ()]
                             r)]
    (reverse (longest-seq last-seq max-seq))))

(find-max-seq '(2 3 4 6 8 1))  ; ==> (2 3 4) 
(find-max-seq '(3 2 3 4 6 8 9 10 11)) ; ==> (8 9 10 11)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top