# joaofcosta's solution

## to Spiral Matrix in the Elixir Track

Published at Apr 16 2019 · 0 comments
Instructions
Test suite
Solution

Given the size, return a square matrix of numbers in spiral order.

The matrix should be filled with natural numbers, starting from 1 in the top-left corner, increasing in an inward, clockwise spiral order, like these examples:

###### Spiral matrix of size 3
``````1 2 3
8 9 4
7 6 5
``````
###### Spiral matrix of size 4
`````` 1  2  3 4
12 13 14 5
11 16 15 6
10  9  8 7
``````

## Running tests

Execute the tests with:

``````\$ elixir spiral_matrix_test.exs
``````

### Pending tests

In the test suites, all but the first test have been skipped.

Once you get a test passing, you can unskip the next one by commenting out the relevant `@tag :pending` with a `#` symbol.

For example:

``````# @tag :pending
test "shouting" do
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
end
``````

Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the test suite.

``````# ExUnit.configure exclude: :pending, trace: true
``````

If you're stuck on something, it may help to look at some of the available resources out there where answers might be found.

## Source

Reddit r/dailyprogrammer challenge #320 [Easy] Spiral Ascension. https://www.reddit.com/r/dailyprogrammer/comments/6i60lr/20170619_challenge_320_easy_spiral_ascension/

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### spiral_test.exs

``````if !System.get_env("EXERCISM_TEST_EXAMPLES") do
end

ExUnit.start()
ExUnit.configure(trace: true, exclude: :pending)

defmodule SpiralTest do
use ExUnit.Case

# @tag :pending
test "empty spiral" do
assert Spiral.matrix(0) == []
end

@tag :pending
test "trivial spiral" do
assert Spiral.matrix(1) == [[1]]
end

@tag :pending
test "spiral of side length 2" do
assert Spiral.matrix(2) == [
[1, 2],
[4, 3]
]
end

@tag :pending
test "spiral of side length 3" do
assert Spiral.matrix(3) == [
[1, 2, 3],
[8, 9, 4],
[7, 6, 5]
]
end

@tag :pending
test "spiral of side length 4" do
assert Spiral.matrix(4) == [
[1, 2, 3, 4],
[12, 13, 14, 5],
[11, 16, 15, 6],
[10, 9, 8, 7]
]
end

@tag :pending
test "spiral of size 5" do
assert Spiral.matrix(5) == [
[1, 2, 3, 4, 5],
[16, 17, 18, 19, 6],
[15, 24, 25, 20, 7],
[14, 23, 22, 21, 8],
[13, 12, 11, 10, 9]
]
end
end``````
``````defmodule Spiral do
@doc """
Given the dimension, return a square matrix of numbers in clockwise spiral order.
"""
@spec matrix(dimension :: integer) :: list(list(integer))
def matrix(0), do: []
def matrix(size), do: matrix(size, size)

def matrix(row, col, start \\ 1)
def matrix(row, 0, start), do: [[]]
def matrix(row, col, start) do
tail = col
|> matrix(row - 1, start + col)
|> rotate_right()

[Enum.to_list(start..start + col - 1) | tail]
end

@doc """
Transpose a matrix.
"""
def transpose(matrix), do: matrix |> List.zip() |> Enum.map(&Tuple.to_list/1)

@doc """
Right rotation of a matrix.
"""
def rotate_right(matrix), do: matrix |> transpose() |> Enum.map(&Enum.reverse/1)
end``````