Frage

In einem Clojure-Programm habe ich eine Folge von Zahlen:

(2 3 4 6 8 1)

Ich mag die längste Untersequenz zu finden, wo die Elemente aufeinanderfolgende:

(2 3 4)

Ich gehe davon aus, dass es (take-while ...) oder (reduce ...) beinhalten wird.

Irgendwelche Ideen?

Klarstellung : Ich brauche die längste erste Liste der sequentiellen Elemente. Viel einfacher, ich bin sicher. Vielen Dank für die Lösungen zu dem schwierigeren Problem, das ich anfangs gestellt.

War es hilfreich?

Lösung

Wenn Sie nur in der längsten Anfangssequenz interessiert sind, es ist ein 1-liner:

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

Andere Tipps

Unter Berücksichtigung Kommentar des OP auf die Frage - was das Spiel komplett verändert! - diese sehr einfach geschrieben werden kann:

(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)

Beachten Sie, dass dies tatsächlich faul. Ich erwarte, dass es nicht auf den Kopf doubletons dank Einheimischen Clearing zu halten. Eine andere Version:

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

Die ursprüngliche Version der Frage ist mehr Spaß, aber! :-) Eine super-einfache Lösung, dass unter Verwendung des oben könnte gebaut, aber das ist natürlich deutlich weniger performant als reduce Verwendung wäre. Ich werde sehen, ob ich etwas wesentlich von zmila die haben und dnolen Lösungen - und doch noch einigermaßen performant - später zu, dass ein Teil dieses Threads hinzuzufügen. (Nicht sehr wahrscheinlich, ich denke.)

Antwort zur Vorlage:

(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])

Eine allgemeine Lösung für die Interessenten:

(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]))

Ich denke, das ist viel besser.

(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)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top