I have written a solution in Clojure for the following question:
When starting from the number 1 and adding three numbers on each row a 3x3 matrix is formed as follows:
1 2 3 4 5 6 7 8 9
Starting from the upper left and spiraling inwards in a clockwise direction the following series is obtained:
1 2 3 6 9 8 7 4 5.
Create a method spiral that finds the spiraling series for a \$n\times n\$ matrix.
I created a long and short solution. They are inspired by the following Stack Overflow answer: ruby - Looping in a spiral outside-in
Version with descriptive names:
(ns spiral.core (:require [clojure.core.matrix :as m])) (defn create-numbers-matrix "creates a size x size matrix of numbers from 1 up to and including size." [size] (let [numbers (range 1 (inc (* size size))) partitions (partition size numbers) matrix (m/matrix partitions)] matrix)) (defn get-first-row [m] "gets the first row (index 0) of matrix m." (m/get-row m 0)) (defn delete-first-row [m] "returns matrix with the first row of the matrix m removed." (drop 1 (m/rows m))) (defn transpose [m] "transposes matrix m." (m/transpose m)) (defn reverse-rows [m] "returns matrix m with rows reversed." (m/matrix (reverse m))) (defn rotate-left [m] "rotates the matrix m 90 degrees to the left." (-> m transpose reverse-rows)) (defn rotate-and-chop [m] "repeatedly rotates matrix m 90 degrees and cuts off the top till matrix is empty." (if (empty? m) nil (conj (rotate-and-chop (-> m delete-first-row rotate-left)) (get-first-row m)))) (defn spiral [size] "creates list of values in spiral from grid of size size" (let [numbers-matrix (create-numbers-matrix size)] (flatten (rotate-and-chop numbers-matrix))))
(ns spiral.core (:require [clojure.core.matrix :as m])) (defn spiral-one-liner [size] (flatten ((fn loop [m] (if (empty? m) nil (conj (loop (m/matrix (reverse (m/transpose (drop 1 (m/rows m)))))) (m/get-row m 0)))) (m/matrix (partition size (range 1 (inc (* size size))))))))
The short version is still longer than the Ruby version from the answer (because tail recursions errors appear the
recur syntax can, I believe, not be used).
I would be grateful if someone can take a look and provide some suggestions.