August 20, 2018

Just Juxt #6: Rotate a Sequence (4clojure #44)

Ship wheel

Write a function which can rotate a sequence in either direction.

This problem is particularly significant, because it's the one that inspired this blog on the most recent Apropos show!

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 rotate [n s]
  )

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

First, a common answer:

(defn rotate [n s]
  (take (count s) (drop (mod n (count s)) (cycle s))))
  
(run-tests)

Now the juxt-ification - solution courtesy of hypirion:

(defn rotate [n s]
  (apply concat ((juxt drop take) (mod n (count s)) s)))
  
(run-tests)

Here we are juxt-ing with drop and take. Let's plug in our first test case:

(apply concat ((juxt drop take) (mod 2 (count [1 2 3 4 5])) [1 2 3 4 5]))

Here's just the call to drop:

(drop (mod 2 (count [1 2 3 4 5])) [1 2 3 4 5])

And to take:

(take (mod 2 (count [1 2 3 4 5])) [1 2 3 4 5])

Which results in this vector when juxted:

((juxt drop take) (mod 2 (count [1 2 3 4 5])) [1 2 3 4 5])

And then we stick them together:

(apply concat ['(3 4 5) '(1 2)])

I hope you enjoyed today's juxt. See you tomorrow!

Tags: coding exercises KLIPSE 4clojure Cryogen juxt