not exactly what you want, but if you can live with lists instead of vectors:
(partition (for [x (range 10) y (range 10)] [x y]) 10)
Vectors are better for my use case, because I will frequently be looking things up by index (to get the grid cell at [12 59]
or whatever). But that's definitely compact!
(->> (for [x (range 10) y (range 10)] [x y])
(partition 10)
(mapv (partial into [])))
I guess you could solve this by having one long vector containing (* x y)
elements and do indexing by multiplication?
(def game (into [] (for [x (range 10) y (range 10)] [x y])))
(defn get-in-game [game x y] (get game (+ (* 10 x) y)))
(get-in-game game 4 3)
;=> [4 3]
or if you use a map with keys that are a vector of [x y]
you can have a sparse matrix, or just say a matrix is a function that takes two arguments and returns a value, and internal to that function you can do all kinds of stuff
Well, the final (?) wrinkle is that each cell also needs to be aware of its links with others. I've generalized this as having a set of valid exits, such as #{::n ::nw ::e}
. I'm taking @slipset's excellent suggestion to use a multi-param for
and partition it—I had totally forgotten that you don't need to syntactically nest for
forms.
(defn grid
"Returns a grid of unconnected cells with the supplied number of columns
(i.e. width) and rows (i.e. height)."
[width height]
(->> (for [y (range 0 height) x (range 0 width)] (create-cell x y))
(partition width)
(mapv (partial into []))))
Works like a charm!
And the exit-set works as long as all the cells are on a uniform grid, which they are, at least for now: if you go east from 0, 0 you'll definitely get to 1, 0.
I expect to perform the linkage by passing in an entire grid, wrangling its data a bit with Specter, and getting back an entire grid with that one modification.