Instantly share code, notes, and snippets.

# ericnormand/00 drop-every Puzzle Description.md Last active Mar 17, 2019

Drop every nth element from a sequence

The problem is simple: write a function that takes a number n and a sequence. The function returns a new sequence with every nth element removed.

For example:

```(drop-every 3 [:a :b :c :d :e :f :g])
;=> (:a :b :d :e :g)```

Bonus points for laziness, efficiency, and concision.

Note: These solutions are untested. Testing them is left as an exercise for you.

 (defn drop-every [n coll] (flatten (partition-all (dec n) n coll))) (drop-every 2 (range 1 13)) => (1 3 5 7 9 11) (drop-every 3 (range 1 13)) => (1 2 4 5 7 8 10 11) (drop-every 5 (range 1 13)) => (1 2 3 4 6 7 8 9 11 12)

# PF.tv challenge

Let’s first write a function to check the outputs. Since it’s quite simple, I’ll use the example from the problem definition and a couple of corner cases:

```(defn spy [x] (prn x) x)

(defn seqs-match? [a b]
;; we don't care about size because the input might be an infinite seq
(every? (partial apply =) (zipmap a b)))

(defn check-fn [f]
(doseq [{:keys [testcase expected]} [{:testcase [3 [:a :b :c :d :e :f :g]], :expected [:a :b :d :e :g]}
{:testcase [3 [:a :b :c :d :e :f :g :h :i]], :expected [:a :b :d :e :g :h]}
{:testcase [3 [:a :b]], :expected [:a :b]}
{:testcase [3 (range)], :expected [0 1 3 4 6 7 9 10 12]}
{:testcase [3 []], :expected []}]
:let [actual (apply f testcase)]]
(if (seqs-match? actual expected)
(println "Match!")
(do (println "Mismatch :(")
(println (str "  Expected: " (pr-str expected)))
(println (str "  Actual  : " (pr-str actual)))))))```

The simplest way I could think of was indexing the collection and filtering it:

```(defn drop-every-simple [n coll]
(->> coll
(map-indexed (fn [index v] [(mod (inc index) n) v]))
(filter (complement #(-> % first zero?)))
(map second)))

(check-fn drop-every-simple)```

We can also write an arity to return an xform for it:

```(defn drop-every
([n]
(comp
(map-indexed (fn [index v]  [(mod (inc index) n) v]))
(filter (complement #(-> % first zero?)))
(map second)))
([n coll]
(sequence (drop-every n) coll)))

(check-fn drop-every)```
 (defn drop-every [n s] (mapcat (partial take (dec n)) (partition n s)))
 (defn drop-every [n values] (flatten (map #(take (- n 1) %) (partition-all n values))))
 (defn drop-every [n seq] (let [seq-indexed (map-indexed #(vec [%1 %2]) seq)] (for [[index val] seq-indexed :when (or (< (inc index) n) (not (= 0 (mod (inc index) n))))] val)))
 (defn drop-every [n coll] (->> coll (partition-all (dec n) n) flatten)) (drop-every 3 [:a :b :c :d :e :f :g]) ;; => (:a :b :d :e :g)
 (defn drop-every-nth [n coll] (lazy-seq (when-let [vals (seq coll)] (concat (take (dec n) coll) (drop-every-nth n (drop n coll))))))
 (defn drop-every [nth coll] (keep-indexed #(when (< 0 (rem (inc %1) nth)) %2) coll))
 (defn drop-every [n xs] (->> xs (map vector (range)) (map (fn [[a b]] [(inc a) b])) (filter (fn [[a b]] (not= 0 (mod a n)))) (map (fn [[a b]] b))))
 (defn drop-every ([n] {:pre [(pos-int? n)]} (fn [rf] (let [iv (volatile! n)] (fn ([] (rf)) ([result] (rf result)) ([result input] (if (zero? (vswap! iv unchecked-dec)) (do (vreset! iv n) result) (rf result input))))))) ([n coll] (sequence (drop-every n) coll)) )
 (defn drop-every [n coll] (->> coll (cons :dummy-1st-element) (partition-all n) (mapcat rest)))
 (defn drop-every [n coll] (apply concat (partition-all (dec n) n coll)))