Search code examples
clojure

Clojure: find repetition


Let's say we have a list of integers: 1, 2, 5, 13, 6, 5, 7 and I want to find the first number that repeats and return a vector of the two indices. In my sample, it's 5 at [2, 5]. What I did so far is loop, but can I do it more elegant, short way?

(defn get-cycle
  [xs]
  (loop [[x & xs_rest] xs, indices {}, i 0]
    (if (nil? x)
      [0 i]  ; Sequence is over before we found a duplicate.
      (if-let [x_index (indices x)]
        [x_index i]
        (recur xs_rest (assoc indices x i) (inc i))))))

No need to return number itself, because I can get it by index and, second, it may be not always there.


Solution

  • An option using list processing, but not significantly more concise:

    (defn get-cycle [xs]
      (first (filter #(number? (first %))
        (reductions
          (fn [[m i] x] (if-let [xat (m x)] [xat i] [(assoc m x i) (inc i)]))
          [(hash-map) 0] xs))))