Map that describes a 2d vector -> 2d vector

Hi all.

Looking for assistance on how to create a function that takes a map of this format, for example:

``````{[1 0] 1
[0 0] 2
[1 1] 3
[0 1] 4}
``````

And returns a 2d vector that looks like, for example:

``````[[2 1]
[4 3]]
``````

So, the 2d vector represents an x,y grid where (0,0) is the upper left corner. The keys for the map are [x y] and the values for the map are the 2d vector values.

I’ve been attempting a solution trying different mixtures of for, reduce, map, assoc-in, update-in, etc. It’s been several days and I am not making progress so I appreciate any assistance. Thanks.

``````(let [in {[1 0] 1
[0 0] 2
[1 1] 3
[0 1] 4}
out [[2 1]
[4 3]]
ensure-index (fn [coll index val]
(let [count (count coll)
needed-count (inc index)]
(if (< count needed-count)
(into coll (repeat (- needed-count count) val))
coll)))]
(= out
(reduce-kv
(fn [acc [y x] v]
(-> acc
(ensure-index x [])
(->> (mapv #(ensure-index % y nil)))
(assoc-in [x y] v)))
[]
in)))
;; => true
``````

Also notice that `x` and `y` are swapped in reducing function, I made it to match your expected output, although I have a feeling it can be wrong. `[0 1]` coordinate should be `4` according to our input map, but `(get-in out [0 1])` returns `1` — looks like axises are wrong in `out`

2 Likes

Thanks for the solution. I haven’t played around much with reduce-kv. Maybe that is the magic sauce needed to solve the problem .

reduce-kv is almost the same as reduce, just a bit more efficient on maps because it avoids constructing map entries by passing key and value as separate arguments to reducing function

Morning @lkcampbell,

bellow is my very boring answer to your question. The main idea is to build from the empty answer `[[nil nil] [nil nil]]` the solution. For that, I use map-indexed to fetch the proper items in the `input`.

I did not put my answer in a standalone function for readability.

cheers!

didier

``````(def input {[1 0] 1
[0 0] 2
[1 1] 3
[0 1] 4})

(defn replace-col [row-index col-index _]
(get input [col-index row-index]))

(defn replace-row [row-index row]
(map-indexed #(replace-col row-index %1 %2) row))

(def  empty-output (repeat 2 (repeat 2 nil)))
(map-indexed replace-row empty-output)``````
1 Like

Thanks for the input. I used your empty grid idea in my original attempts as well but couldn’t quite figure out how to consolidate the changes I made.

I have no experience using map-indexed yet but it looks like a very useful function for this problem. I will play around with it as well. Thanks.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.