I have a list of vectors like this:
([4 0] [4 2] [2 1] [4 1])
How can i increment the first element of every vector by a certain value X ?
desired output:
([5 0] [5 2] [3 1] [5 1])
This is my current approach, but i think i could be much simpler:
(defn shiftVector [oldVector number]
(map vector
(map #(+ (first %) number) oldVector )
(map #(second %) oldVector))
)
Since vectors are associative on their indices, probably the simplest approach is:
(defn shift-vector [v n]
(map #(update % 0 + n) v))
(shift-vector [[4 0] [4 2] [2 1] [4 1]] 1)
;=> ([5 0] [5 2] [3 1] [5 1])
This works with any length vectors in the list (except empty vectors but then you couldn't increment those anyway).
Extract the first element, increment it, then put everything back into a new vector:
(defn inc-first [col]
(map #(into [] (flatten (conj [] (inc (first %)) (rest %)))) col))
Tests:
user=> (inc-first '([4 0] [4 2] [2 1] [4 1]))
([5 0] [5 2] [3 1] [5 1])
user=> (inc-first '([4 0 0] [4 2 2] [2 1 1] [4 1 1]))
([5 0 0] [5 2 2] [3 1 1] [5 1 1])
user=> (inc-first '([4 4 4 4] [4 2 2 2] [2 2 3 4] [4 1 0 -1]))
([5 4 4 4] [5 2 2 2] [3 2 3 4] [5 1 0 -1])
Use map.
;this solution works only for vectors of size 2
(defn inc-lst [lst x]
(map (fn [e] (vector (+ (first e) x) (second e)))
lst))
(inc-lst '([4 0] [4 2] [2 1] [4 1]) 1)
;more general solution, works for vectors of size >= 1
(defn inc-lst2 [lst x]
(map (fn [e] (apply vector (+ (first e) x) (rest e)))
lst))
(inc-lst2 '([4 0 0] [4 2 2] [2 1 1] [4 1 1]) 1)
(inc-lst2 '([4] [4] [2] [4]) 1)
Related
Is there any easy way to reshape a vector into an array in which the "filling" is by row?
More specifically, suppose I have a vector
v = collect(1:8)
reshape "fills" the resulting array by column:
reshape(v, (2,2,2))
2x2x2 Array{Int64,3}:
[:, :, 1] =
1 3
2 4
[:, :, 2] =
5 7
6 8
But I want to get:
a = Array{Int}(2,2,2)
a[:, :, 1] = [1 2; 3 4]
a[:, :, 2] = [5 6; 7 8]
a
2x2x2 Array{Int64,3}:
[:, :, 1] =
1 2
3 4
[:, :, 2] =
5 6
7 8
This would be a nice option to add to reshape.
mapslices(transpose,reshape(v, (2,2,2)),[1,2])
The keyword you were missing is "transpose". The rest I just took from the docs
Julia allows me to do elementwise binary operators on arrays/matrices with .:
[1 2 3] .+ [3 2 1]
[1 2 3] .> [3 2 1]
Is there a standard way to apply an arbitrary function f elementwise to a pair of arrays?
If you just want to apply a binary function to each pair of values from two lists, you can use map:
f(x,y) = 2x - y^2
julia> map(f, [1, 2, 3], [3, 2, 1])
3-element Array{Int64,1}:
-7
0
5
The .+ and .> operators also have the additional behavior that singleton dimensions are broadcast, like so:
julia> [1, 2, 3] .+ [-1 -2 -3]
3x3 Array{Int64,2}:
0 -1 -2
1 0 -1
2 1 0
julia> rand(3,4) .+ [1, 2, 3]
3x4 Array{Float64,2}:
1.73798 1.84132 1.12923 1.30192
2.10961 2.17835 2.52779 2.3028
3.16457 3.04659 3.67604 3.08869
julia> rand(3,4) .+ [1 2 3 4]
3x4 Array{Float64,2}:
1.40294 2.31384 3.34001 4.60027
1.13289 2.99275 3.50606 4.51049
1.31486 2.7585 3.64655 4.59647
If you also want this kind of behavior, you can use the broadcast function:
julia> broadcast(f, [1 2 3], [3, 2, 1])
3x3 Array{Int64,2}:
-7 -5 -3
-2 0 2
1 3 5
Take integer partition problem for example, I can write the following code to output all partitions of a positive integer n:
(defn foo
([n] (foo n n []))
([n k buf]
(if (zero? n)
(println buf)
(doseq [i (range 1 (inc (min n k)))]
(foo (- n i) i (conj buf i))))))
Then (foo 5) outputs:
[1 1 1 1 1]
[2 1 1 1]
[2 2 1]
[3 1 1]
[3 2]
[4 1]
[5]
The question is how could I write a function bar which generates a lazy-seq containing such results? For example, I want (bar 5) generates ([1 1 1 1 1] [2 1 1 1] [2 2 1] [3 1 1] [3 2] [4 1] [5]).
Here is a roughly equivalent function generating the partitions as a sequence of sequences:
(defn bar
([n] (bar n n))
([n k]
(if (zero? n)
[[]]
(for [i (range 1 (inc (min n k))), tail (bar (- n i) i)]
(cons i tail)))))
For example,
(bar 5)
; ((1 1 1 1 1) (2 1 1 1) (2 2 1) (3 1 1) (3 2) (4 1) (5))
How lazy is bar?
for is lazy.
to make it lazier, wrap the body in a lazy-seq.
I have my doubts about the above.
The function recurses to depth n.
Wrapping the body in lazy-seq I suspect just stacks up lazy
sequences, producing just as deep a recursive call stack on accessing the
first element.
Besides, the same tails are repeatedly computed; the more so since (bar n k) is the same for all k >= n.
If performance of this function is a specific concern, there are iterative algorithms with constant time per step. As #CharlesDuffy's comment implies, these can be re-jigged to produce lazy sequences.
Why gaze into the crystal ball when you can read the book?
The standard namespace clojure.math.combinatorics, hosted here, contains a partition function that produces a lazy sequence of the partitions of any sequence of objects - fast. Integer partition is where we count the elements of each partition of identical objects. They come out in reverse lexicographic order.
For example
(map #(map count %) (combo/partitions (repeat 5 :whatever)))
;((5) (4 1) (3 2) (3 1 1) (2 2 1) (2 1 1 1) (1 1 1 1 1))
No doubt the code can be stripped down to deal with just this case.
Here is recursive solution. There are some ways to optimize it and code is not the best.
(defn partitions [n]
(loop [m n
res [(init-step n m)]]
(let [l (last res)]
(if (= m 1)
res
(if (last-step? (last res))
(recur (- m 1) (vec (conj res (init-step n (- m 1)))))
(recur m (next-step res)))))))
(defn init-step [n m]
(if (= n m)
[n]
(loop [res [m (- n m)]]
(let [l (last res)
f (first res)]
(if (<= l f)
res
(recur (vec (conj (vec (butlast res)) f (- l f)))))))))
(defn next-step [res]
(let [input-vec (last res)
cnt (count input-vec)
i (.indexOf input-vec 1)
j (if (> i -1) (- i 1) (- cnt 1))
m (- cnt j)
new-vec (conj (vec (take j input-vec)) (- (input-vec j) 1))]
(conj res (vec (concat new-vec (repeat m 1))))))
(defn last-step? [input-vec]
(if
(or (nil? input-vec)
(= (count input-vec) 1)
(= (input-vec 1) 1)) true
false))
(partitions 10)
#=> [[10] [9 1] [8 2] [8 1 1] [7 3] [7 2 1] [7 1 1 1] [6 4] [6 3 1] [6 2 1 1] [6 1 1 1 1] [5 5] [5 4 1] [5 3 1 1] [5 2 1 1 1] [5 1 1 1 1 1] [4 4 2] [4 4 1 1] [4 3 1 1 1] [4 2 1 1 1 1] [4 1 1 1 1 1 1] [3 3 3 1] [3 3 2 1 1] [3 3 1 1 1 1] [3 2 1 1 1 1 1] [3 1 1 1 1 1 1 1] [2 2 2 2 2] [2 2 2 2 1 1] [2 2 2 1 1 1 1] [2 2 1 1 1 1 1 1] [2 1 1 1 1 1 1 1 1] [1 1 1 1 1 1 1 1 1 1]]
I'd like to understand the idiomatic way with which to operate over collections of different sizes in clojure. Is there a way I can tell the function 'map' to pad the rest of a collection with some default value?
As an example, suppose I have 3 vectors:
(def x [1 2 3 4])
(def y [1 2 3 4 5])
(def z [1 2 3 4 5 6 7])
(map + x y z) ; yields (3 6 9 12)
In this case, how can I pad x and y with zeroes and have this yield:
(3 6 9 12 10 6 7)
map doesn't do it itself, but you can use a combination of concat and repeat to obtain the desired result:
(def x [1 2 3 4])
(def y [1 2 3 4 5])
(def z [1 2 3 4 5 6 7])
(map +
(concat x (repeat 0))
(concat y (repeat 0))
z) ; => (3 6 9 12 10 6 7)
Here's the API documentation for concat, and for repeat.
And here's a sketch of how you could abstract this away a bit, so you don't need to know which of the collections is longest. (In the snippet above, if you concat all the collections to (repeat 0) you'll have an infinite sequence).
(defn map-longest
[f default & colls]
(lazy-seq
(when (some seq colls)
(cons
(apply f (map #(if (seq %) (first %) default) colls))
(apply map-longest f default (map rest colls))))))
(map-longest +
0
[1 2 3 4]
[1 2 3 4 5]
[1 2 3 4 5 6 7]) ; => (3 6 9 12 10 6 7)
You can see a couple other approaches as answers to this previous question on Stack Overflow.
You can merge vector of maps with variable lengths by the following function:
(defn merge-maps
[& args]
(let [max-count (apply max (map #(count %1) args))
items (map #(take max-count (concat %1 (repeat nil))) args)]
(apply map merge items)))
This function makes the solution more generalized and can take any length of vector of maps.
(map vector [1 2 3] [4 5])
will give:
([1 4] [2 5])
Here 3 is discarded.
What if I want to pad those too short seqs to the largest length automatically?
e.g.
What's the idiomatic way if I want to get
([1 4] [2 5] [3 nil])
(defn map-all [f & colls]
(lazy-seq
(when (some seq colls)
(cons (apply f (map first colls))
(apply map-all f (map rest colls))))))
(map-all vector [1 2 3] [4 5])
;=> ([1 4] [2 5] [3 nil])