#(take %
(map first
(iterate (fn [[i1 i2]]
[i2 (+ i1 i2)])
[1 1])))
This is a function to generate fib seq in clojure.
I don't understand this part:
(fn [[i1 i2]]
[i2 (+ i1 i2)])
[1 1])
from [i1 i2] to [i2 (+ i1 i2)].
how does make this sequence keep growing? seems to me it is always 2 elements.
need help. thanks!
the function
(fn [[i1 i2]]
[i2 (+ i1 i2)])
takes in one step of the sequence and produces the next step in the process. So each call produces one more step in the sequence. This is an intermediate solution where every step has two elements in it. The first element is the answer thus far, and the second one provides enough context to produce the next step. so the output would look like:
user> (take 5
(iterate (fn [[i1 i2]]
[i2 (+ i1 i2)])
[1 1]))
([1 1] [1 2] [2 3] [3 5] [5 8])
Then a later stage takes this entire sequence and removes the extra information leaving only the answers from each step.
user> (map first
(take 5
(iterate (fn [[i1 i2]]
[i2 (+ i1 i2)])
[1 1])))
(1 1 2 3 5)
This is a great application of breaking a problem down into seperable parts and then composing these parts to form the final answer.
The function passed to iterate is
(fn [[i1 i2]]
[i2 (+ i1 i2)])
All the function does is generate the next term in the sequence given a previous one (using pattern-matching to assign the names i1 and i2 to the members of the passed-in vector).
iterate takes two arguments, the function that generates the next term in the sequence, and the starting value for the sequence. The function iterate is in charge of generating the lazy sequence.
For an easier example (without the pattern-matching), you could generate a lazy sequence of positive integers with
(iterate inc 0)
You are quite right. The function ...
(fn [[i1 i2]] [i2 (+ i1 i2)])
... does produce one pair of numbers from another. For example,
((fn [[i1 i2]] [i2 (+ i1 i2)]) [6 19])
; [19 25]
Its iterate that produces the sequence, by repeatedly applying the function. This yields a sequence of pairs:
(iterate (fn [[i1 i2]] [i2 (+' i1 i2)]) [1 1])
;([1 1] [1 2] [2 3] [3 5] [5 8] [8 13] [13 21] ...)
The first or the second elements of these pairs form a Fibonacci sequence,
depending where you want to start. To get the former, we just wrap the above in (map first ...):
(map first (iterate (fn [[i1 i2]] [i2 (+' i1 i2)]) [1 1]))
;(1 1 2 3 5 8 13 21 ...)
If you're familiar with the ->> threading macro, you might find it easier to read as
(->> [1 1]
(iterate (fn [[i1 i2]] [i2 (+ i1 i2)]))
(map first))
;(1 1 2 3 5 8 13 21 ...)
Related
I have two sequences, which can be vector or list. Now I want to return a sequence whose elements are not in common to the two sequences.
Here is an example:
(removedupl [1 2 3 4] [2 4 5 6]) = [1 3 5 6]
(removeddpl [] [1 2 3 4]) = [1 2 3 4]
I am pretty puzzled now. This is my code:
(defn remove-dupl [seq1 seq2]
(loop [a seq1 b seq2]
(if (not= (first a) (first b))
(recur a (rest b)))))
But I don't know what to do next.
I encourage you to think about this problem in terms of set operations
(defn extrasection [& ss]
(clojure.set/difference
(apply clojure.set/union ss)
(apply clojure.set/intersection ss)))
Such a formulation assumes that the inputs are sets.
(extrasection #{1 2 3 4} #{2 4 5 6})
=> #{1 6 3 5}
Which is easily achieved by calling the (set ...) function on lists, sequences, or vectors.
Even if you prefer to stick with a sequence oriented solution, keep in mind that searching both sequences is an O(n*n) task if you scan both sequences [unless they are sorted]. Sets can be constructed in one pass, and lookup is very fast. Checking for duplicates is an O(nlogn) task using a set.
I'm still new to Clojure but I think the functional mindset is more into composing functions than actually doing it "by hand", so I propose the following solution:
(defn remove-dupl [seq1 seq2]
(concat
(remove #(some #{%} seq1) seq2)
(remove #(some #{%} seq2) seq1)))
EDIT: I think it is better if we define that remove part as a local function and reuse it:
(defn remove-dupl [seq1 seq2]
(let [removing (fn [x y] (remove #(some #{%} x) y))]
(concat (removing seq1 seq2) (removing seq2 seq1))))
EDIT2: As commented by TimothyPratley
(defn remove-dupl [seq1 seq2]
(let [removing (fn [x y] (remove (set x) y))]
(concat (removing seq1 seq2) (removing seq2 seq1))))
There are several problems with your code.
It doesn't test for the end of either sequence argument.
It steps through b but not a.
It implicitly returns nil when any two sequences have the same
first element.
You want to remove the common elements from the concatenated sequences. You have to work out the common elements first, otherwise you don't know what to remove. So ...
We use
clojure.set/intersection to find the common elements,
concat to stitch the collections together.
remove to remove (1) from (2).
vec to convert to a vector.
Thus
(defn removedupl [coll1 coll2]
(let [common (clojure.set/intersection (set coll1) (set coll2))]
(vec (remove common (concat coll1 coll2)))))
... which gives
(removedupl [1 2 3 4] [2 4 5 6]) ; [1 3 5 6]
(removedupl [] [1 2 3 4]) ; [1 2 3 4]
... as required.
I am trying to generate a relatively small (1296 elements) list of vectors essentially enumerating 4 base 6 digits from [0 0 0 0] to [5 5 5 5]
[0 0 0 0], [1 0 0 0] ... [5 0 0 0], [0 1 0 0] ... [5 5 5 5]
Currently what I have is:
(letfn [(next-v [v]
(let [active-index (some (fn [[i e]] (when (> 5 e) i))
(map-indexed vector v))]
(map-indexed #(cond
(> active-index %1) 0
(= active-index %1) (inc %2)
:else %2)
v)))]
(last (take 1290 (iterate next-v [0 0 0 0]))))
This works but it eventually blows the stack.
What am I doing here that causes the StackOverflowError?
How can I structure my code so that it is "safe"?
Is there a better way of doing what I am trying to do?
The way I would solve this is:
(def my-range
(for [i (range 0 6)
j (range 0 6)
x (range 0 6)
y (range 0 6)]
[i j x y]))
(nth my-range 1295) ;;=> [5 5 5 5]
Generalized:
(defn combine [coll]
(for [i (range 6)
j coll]
(conj j i)))
(combine (map list (range 6)))
(combine (combine (map list (range 6))))
(combine (combine (combine (map list (range 6)))))
(def result (nth (iterate combine (map list (range 6))) 3))
This is due to lazyiness in the iterated function body. Notice that the result returned by the first call of next-v is passed to next-v again, before being evaluated (because its a lazy seq), then next-v returns again an unevaluated lazy-seq which will again be passed to it.
When you realize the final lazy seq, to produce the first element all the chained seqs have to be realized to get through to your initial [0 0 0 0]. This will blow the stack.
Stuart Sierra wrote a nice article on this with more examples: http://stuartsierra.com/2015/04/26/clojure-donts-concat
You could simply wrap the map-indexed call in the let body in a vec.
Finding a more generic algorithm to your problem is recommended though.
I would like to partition a seq, based on a seq of values
(partition-by-seq [3 5] [1 2 3 4 5 6])
((1 2 3)(4 5)(6))
The first input is a seq of split points.
The second input is a seq i would like to partition.
So, that the first list will be partitioned at the value 3 (1 2 3) and the second partition will be (4 5) where 5 is the next split point.
another example:
(partition-by-seq [3] [2 3 4 5])
result: ((2 3)(4 5))
(partition-by-seq [2 5] [2 3 5 6])
result: ((2)(3 5)(6))
given: the first seq (split points) is always a subset of the second input seq.
I came up with this solution which is lazy and quite (IMO) straightforward.
(defn part-seq [splitters coll]
(lazy-seq
(when-let [s (seq coll)]
(if-let [split-point (first splitters)]
; build seq until first splitter
(let [run (cons (first s) (take-while #(<= % split-point) (next s)))]
; build the lazy seq of partitions recursively
(cons run
(part-seq (rest splitters) (drop (count run) s))))
; just return one partition if there is no splitter
(list coll)))))
If the split points are all in the sequence:
(part-seq [3 5 8] [0 1 2 3 4 5 6 7 8 9])
;;=> ((0 1 2 3) (4 5) (6 7 8) (9))
If some split points are not in the sequence
(part-seq [3 5 8] [0 1 2 4 5 6 8 9])
;;=> ((0 1 2) (4 5) (6 8) (9))
Example with some infinite sequences for the splitters and the sequence to split.
(take 5 (part-seq (iterate (partial + 3) 5) (range)))
;;=> ((0 1 2 3 4 5) (6 7 8) (9 10 11) (12 13 14) (15 16 17))
the sequence to be partitioned is a splittee and the elements of split-points (aka. splitter) marks the last element of a partition.
from your example:
splittee: [1 2 3 4 5 6]
splitter: [3 5]
result: ((1 2 3)(4 5)(6))
Because the resulting partitions is always a increasing integer sequence and increasing integer sequence of x can be defined as start <= x < end, the splitter elements can be transformed into end of a sequence according to the definition.
so, from [3 5], we want to find subsequences ended with 4 and 6.
then by adding the start, the splitter can be transformed into sequences of [start end]. The start and end of the splittee is also used.
so, the splitter [3 5] then becomes:
[[1 4] [4 6] [6 7]]
splitter transformation could be done like this
(->> (concat [(first splittee)]
(mapcat (juxt inc inc) splitter)
[(inc (last splittee))])
(partition 2)
there is a nice symmetry between transformed splitter and the desired result.
[[1 4] [4 6] [6 7]]
((1 2 3) (4 5) (6))
then the problem becomes how to extract subsequences inside splittee that is ranged by [start end] inside transformed splitter
clojure has subseq function that can be used to find a subsequence inside ordered sequence by start and end criteria. I can just map the subseq of splittee for each elements of transformed-splitter
(map (fn [[x y]]
(subseq (apply sorted-set splittee) <= x < y))
transformed-splitter)
by combining the steps above, my answer is:
(defn partition-by-seq
[splitter splittee]
(->> (concat [(first splittee)]
(mapcat (juxt inc inc) splitter)
[(inc (last splittee))])
(partition 2)
(map (fn [[x y]]
(subseq (apply sorted-set splittee) <= x < y)))))
This is the solution i came up with.
(def a [1 2 3 4 5 6])
(def p [2 4 5])
(defn partition-by-seq [s input]
(loop [i 0
t input
v (transient [])]
(if (< i (count s))
(let [x (split-with #(<= % (nth s i)) t)]
(recur (inc i) (first (rest x)) (conj! v (first x))))
(do
(conj! v t)
(filter #(not= (count %) 0) (persistent! v))))))
(partition-by-seq p a)
I'm writing a clojure function like:
(defn area [n locs]
(let [a1 (first locs)]
(vrp (rest locs))))
I basically want to input like: (area 3 '([1 2] [3 5] [3 1] [4 2])) But when I do that it gives me an error saying Wrong number of args (1) passed. But I'm passing two arguments.
What I actually want to do with this function is that whatever value of n is inputted (say 3 is inputted), then a1 should store [1 2], a2 should store [3 5], a3 should store ([3 1] [4 2]). What should I add in the function to get that?
clojue's build in split-at function is very close to solving this. It splits a sequence "at" a given point. So if we first split the data apart and then wrap the second half in a list and concatenate it back together again it should solve this problem:
user> (let [[start & end] (split-at 2 sample-data)]
(concat start end))
([1 2] [3 5] ([3 1] [4 2]))
the & before end in let causes the last item to be rolled up in a list. It's equivalent to:
user> (let [[start end] (split-at 2 sample-data)]
(concat start (list end)))
([1 2] [3 5] ([3 1] [4 2]))
If I recklessly assume you have some function called vrp that needs data in this form then you could finish your function with something like this:
(defn area [n locs]
(let [[start end] (split-at (dec n) sample-data)
a (concat start (list end))]
(apply vrp a)))
Though please forgive me to making wild guesses as to the nature of vrp, I could be totally off base here.
I have used the following expression to retrieve the index of the smallest number in a vector. However, I would like to avoid the use of .indexOf (for efficiency reasons and maybe numeric precision, although I guess the numbers are implicitly converted to strings).
(.indexOf [1 2 3 4 0 5]
(reduce #(if (< %1 %2) %1 %2) [1 2 3 4 0 5] ))
Would it be possible to do it differently using reduce?
user=> (first (apply min-key second (map-indexed vector [1 2 4 0 5])))
3
I'd suggest using loop/recur if you want to do this efficiently, perhaps something like the following:
(defn min-index [v]
(let [length (count v)]
(loop [minimum (v 0)
min-index 0
i 1]
(if (< i length)
(let [value (v i)]
(if (< value minimum)
(recur value i (inc i))
(recur minimum min-index (inc i))))
min-index))))
The idea is to iterate across the whole vector, keeping track of the minimum and the index of the minimum value found so far at each point.
You can also use reduce:
(def v [1 2 3 4 0 5])
(second (reduce (fn [[curr-min min-idx curr-idx] val]
(if (< val curr-min)
[val curr-idx (inc curr-idx)]
[curr-min min-idx (inc curr-idx)])) [(first v) 0 0] v)) ;; => 4
The result of reduce is actually a three-element vector consisting of the minimum value, its index, and an index tracker (which is not important), respectively. And it traverses the collection once.
The initial value provided to reduce is basically the first element of the collection.
I know the question is old, but it is here for posterity's sake.
Following up on #Alex Taggart's answer, using thread-last macro:
user=> (->> [1 2 4 0 5]
(map-indexed vector) ; [[0 1] [1 2] [2 4] [3 0] [4 5]]
(apply min-key second) ; [3 0]
first)
3