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))))
Short version:
(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 loop
and recur
syntax can, I believe, not be used).
I would be grateful if someone can take a look and provide some suggestions.