August 12, 2018

4clojure 132 - Insert between two items

Write a function that takes a two-argument predicate, a value, and a collection; and returns a new collection where the value is inserted between every two items that satisfy the predicate.

(ns live.test
  (:require [cljs.test :refer-macros [deftest is run-tests]]))

(defn insert-between [p b [f s :as coll]]
  (lazy-seq
    (when f
      (if (and s (p f s))
        (cons f (cons b (insert-between p b (rest coll))))
        (cons f (insert-between p b (rest coll)))))))

(deftest test-132
  (is (= '(1 :less 6 :less 7 4 3) (insert-between < :less [1 6 7 4 3])))
  (is (= '(2) (insert-between > :more [2])))
  (is (= [0 1 :x 2 :x 3 :x 4]  (insert-between #(and (pos? %) (< % %2)) :x (range 5))))
  (is (empty? (insert-between > :more ())))
  (is (= [0 1 :same 1 2 3 :same 5 8 13 :same 21]
   (take 12 (->> [0 1]
                 (iterate (fn [[a b]] [b (+ a b)]))
                 (map first) ; fibonacci numbers
                 (insert-between (fn [a b] ; both even or both odd
                       (= (mod a 2) (mod b 2)))
                     :same))))))
                     
(run-tests)  
Tags: coding exercises KLIPSE 4clojure Clojure