Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rotate a list-of-list matrix in Clojure

Tags:

matrix

clojure

I'm new to Clojure and functional programming in general. I'm at a loss in how to handle this in a functional way.

I have the following matrix:

(def matrix [[\a \b \c]
             [\d \e \f]
             [\g \h \i]])

I want to transform it into something like this (rotate counterclockwise):

((\a \d \g)
 (\b \e \h)
 (\c \f \i ))

I've hacked up this bit that gives me the elements in the correct order. If I could collect the data in a string this way I could then split it up with partition. However I'm pretty sure doseq is the wrong path:

(doseq [i [0 1 2]]
  (doseq [row matrix]
    (println (get (vec row) i))))

I've dabbled with nested map calls but keep getting stuck with that. What's the correct way to build up a string in Clojure or handle this in an even better way?

like image 718
Martijn Avatar asked Nov 29 '11 17:11

Martijn


2 Answers

Taking the matrix transposition solution directly from rosettacode:

(vec (apply map vector matrix))

To see what is going on consider:

(map vector [\a \b \c] [\d \e \f] [\g \h \i])

This will work nicely with arbitrary matrix dimensions although it is not good for significant number crunching, for that you would want to consider using a java based matrix manipulation library from Clojure.

like image 125
Alex Stoddard Avatar answered Nov 09 '22 21:11

Alex Stoddard


What you're trying to achieve sounds like transpose. I'd suggest

(apply map list matrix)
; => ((\a \d \g) (\b \e \h) (\c \f \i))

What does it do?

(apply map list '((\a \b \c) (\d \e \f) (\g \h \i)))

is equivalent to

(map list '(\a \b \c) '(\d \e \f) '(\g \h \i))

which takes first elements of each of the three lists, calls list on them, then takes second elements, calls list on them... An returns a sequence of all lists which were generated this way.

A couple more examples of both apply and map can be found on ClojureDocs.

like image 34
Jan Avatar answered Nov 09 '22 23:11

Jan