August 19, 2018

Just Juxt #5: Replicate a Sequence (4clojure #33)

Calvin the frog

Write a function which replicates each element of a sequence a variable number of times.

Here's a live testing area for you to play with. See if you can solve it with juxt. Then check out the answer below!

(ns live.test
  (:require [cljs.test :refer-macros [deftest is testing run-tests]]))
  
(defn replicate [s n]
  )

(deftest replicate-test
  (is (= (replicate [1 2 3] 2) '(1 1 2 2 3 3)))
  (is (= (replicate [:a :b] 4) '(:a :a :a :a :b :b :b :b)))
  (is (= (replicate [4 5 6] 1) '(4 5 6)))
  (is (= (replicate [[1 2] [3 4]] 2) '([1 2] [1 2] [3 4] [3 4])))
  (is (= (replicate [44 33] 2) [44 44 33 33])))
  
(run-tests)

Here's the most common solution:

(defn replicate [s n]
  (mapcat (partial repeat n) s))
  
(run-tests)

And here's the juxt-ification:

(defn replicate [s n]
  (mapcat (apply juxt (repeat n identity)) s))
  
(run-tests)

To get a closer look, let's plug in the args from our first test case:

(mapcat (apply juxt (repeat 2 identity)) [1 2 3])

This example is deceptively more clever than the ones we've done so far, because we are using apply juxt. Try to wrap your head around that for a second. We're applying a fn, which takes a set of fns, and applies that.

This can be better understood in the context of yesterday's example, to duplicate a seq:

(mapcat (juxt identity identity) [1 2 3])

What we are doing now is using repeat to determine how many identitys are passed to juxt. Here it is with 3:

(mapcat (juxt identity identity identity) [1 2 3])

Which is equivalent to:

(mapcat (apply juxt (repeat 3 identity)) [1 2 3])

The reason we need to use apply is that repeat returns a seq, but juxt is asking for functions.

I think it's great how these problems build upon each other. Duplication is a special case of replication.

Tune in tomorrow and we'll see what other dials we can add to our transmogrifier. Until then, I hope your day becomes juxted with many wonderful things!

Tags: coding exercises KLIPSE 4clojure Cryogen juxt