Reputation: 1717
Say I have a list of vectors
([0 0] [1 0] [1 0] [1 0])
I want to be able to add the list of vectors together and record each unique position along the way.
[0 0]
[0 0] + [1 0] = [1 0]
[1 0] + [1 0] = [2 0]
[2 0] + [1 0] = [3 0]
Giving 4 unique positions.
([0 0] [1 0] [2 0] [3 0])
Any idea how I could achieve this in Clojure?
I've tried the following code, but it overflows for large number of vectors :(
(defn add-vectors [vectors]
(let [[a b] vectors]
(vec(map + a b))))
(defn get-positions [dirs positions]
(if (empty? (rest dirs))
(set positions)
(do
(let [next-pos (add-vectors (take 2 dirs))]
(get-directions (conj (rest (rest dirs)) next-pos) (conj positions next-pos))))))
the (conj (rest (rest dirs))
replaces the first element in the next recursive call with the sum of the first two vectors from the last call.
Upvotes: 1
Views: 884
Reputation: 13324
To add two numbers together, you can use the +
function, as you know:
(+ 2 1)
;;=> 3
To add two vectors together, you can use the mapv
function to zip together the two vectors using +
:
(mapv + [1 0] [1 0])
;;=> [2 0]
To perform a left fold of this vector addition across a sequence of vectors, you can use reduce
:
(reduce #(mapv + %1 %2) [[0 0] [1 0] [1 0] [1 0]])
;;=> [3 0]
Or, replacing that function literal with a usage of partial
:
(reduce (partial mapv +) [[0 0] [1 0] [1 0] [1 0]])
;;=> [3 0]
To obtain all the intermediate steps of this left fold, you can use reductions
:
(reductions (partial mapv +) [[0 0] [1 0] [1 0] [1 0]])
;;=> ([0 0] [1 0] [2 0] [3 0])
Finally, to return only the unique elements from this sequence, you can use set
:
(set (reductions (partial mapv +) [[0 0] [1 0] [1 0] [1 0]]))
;;=> #{[0 0] [1 0] [3 0] [2 0]}
Upvotes: 7