Reputation: 7996
I'm working on exercise 7 on https://iloveponies.github.io/120-hour-epic-sax-marathon/one-function-to-rule-them-all.html. I've got a solution, but because the expected output is a list, I've had to add a 'reverse' to some of my outputs. This seems a bit hacky.
Here's my code:
(defn insert [sorted-seq n]
(loop [output ()
my-seq sorted-seq]
(cond
(nil? (first my-seq))
(conj output n)
(nil? (first (rest my-seq)))
(reverse (conj output (first my-seq) n))
:else
(if (> (first (rest my-seq)) n (first my-seq))
(reverse (apply conj output (first my-seq) n (rest my-seq)))
(recur (conj output (first my-seq)) (rest my-seq))))))
(insert [] 2) ;=> (2)
(insert [1 3 4] 2) ;=> (1 2 3 4)
(insert [1] 2) ;=> (1 2)
Is there a better way of writing this that will be more efficient, and not require reversing the outputs? Also, the first 2 conditions seem clunky. Is there a better way?
Upvotes: 3
Views: 364
Reputation: 13483
You can do this quite simply with a list provided you are prepared to employ proper recursion:
(defn insert [ss n]
(if (empty? ss)
(list n)
(let [[x & xs] ss]
(if (< n x)
(cons n ss)
(cons x (insert xs n))))))
lazy-seq
if you want it to work on long
sequences without blowing the stack.Upvotes: 0
Reputation: 36777
@A.Webb's solution is the one you're looking for, but leaving this for the future visitors.
I think you overcomplicated the problem slightly.
The general idea is this:
You can combine 1 and 2 using split-with, which splits the sequence in two parts: one where a predicate is true, and the other where it is false.
So, speaking clojure:
(defn insert [coll n]
(let [[l r] (split-with #(< % n) coll)]
(concat l [n] r))
Upvotes: 3
Reputation: 26446
I think the point of the exercise is to work with recursion, not necessarily to produce the most idiomatic code. You can avoid the reversing by using a data structure that does conj
to the right, a vector.
(defn insert [sorted-seq n]
(loop [s sorted-seq, a []]
(cond
(empty? s) (conj a n)
(< (first s) n) (recur (rest s) (conj a (first s)))
:else (apply conj a n s))))
Upvotes: 2