Clojure: العثور على عناصر متسلسلة من تسلسل
سؤال
في برنامج clojure ، لدي سلسلة من الأرقام:
(2 3 4 6 8 1)
أريد أن أجد أطول تسلسل فرعي حيث تكون العناصر متسلسلة:
(2 3 4)
أفترض أنه سيشمل (take-while ...)
أو (reduce ...)
.
أيه أفكار؟
توضيح: أحتاج إلى أطول قائمة أولية للعناصر المتسلسلة. أسهل بكثير ، أنا متأكد. شكرًا على حلول المشكلة الأكثر صعوبة التي طرحتها في البداية.
المحلول
إذا كنت مهتمًا فقط بأطول تسلسل أولي ، فهو عبارة عن 1-liner:
(defn longest-initial-sequence [[x :as s]]
(take-while identity (map #(#{%1} %2) s (iterate inc x))))
نصائح أخرى
مع الأخذ في الاعتبار تعليق البروتوكول الاختياري على السؤال - مما يغير اللعبة تمامًا! - يمكن كتابة هذا بكل بساطة:
(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)
لاحظ أن هذا كسول بالفعل. أتوقع عدم التمسك برأس doubletons
بفضل السكان المحليين المقاصة. نسخة أخرى:
(cons (first [1 2 3 5 6])
(map second (take-while increment? (partition 2 1 [1 2 3 5 6]))))
النسخة الأصلية من السؤال أكثر متعة ، رغم ذلك! :-) يمكن بناء حل فائق البكالوري reduce
. سأرى ما إذا كان لدي أي شيء مختلف اختلافًا كبيرًا عن حلول Zmila's و Dnolen - ومع ذلك لا يزال أداءً معقولًا - لإضافة إلى هذا الجزء من هذا الموضوع لاحقًا. (ليس من المحتمل جدًا ، على ما أعتقد.)
الإجابة على الأصل:
(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])
حل أكثر عاما للمهتمين:
(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]))
أعتقد أن هذا أفضل بكثير.
(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)