Created
October 1, 2019 19:38
-
-
Save Jwsonic/15d2a8ddc9ebb39f703ac979de325b44 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Spiral do | |
def order(matrix) do | |
bounds = %{ | |
xmin: 0, | |
xmax: matrix |> hd() |> length(), | |
ymin: 0, | |
ymax: length(matrix) | |
} | |
matrix |> next({0, 0}, {1, 0}, bounds, []) |> Enum.reverse() | |
end | |
# Guard clause that checks if we've reached the center of the matrix | |
defguardp is_center?(x, y, matrix) | |
when matrix |> hd() |> length() |> div(2) |> floor() == x and | |
matrix |> length() |> div(2) |> floor() == y | |
# We've reached the center, add it to the result and we're done | |
defp next(matrix, {x, y}, _direction, _bounds, result) when is_center?(x, y, matrix) do | |
[get(matrix, x, y) | result] | |
end | |
# When we get to the right edge, start moving downwards | |
defp next(matrix, {x, y}, _direction, %{xmax: xmax, ymin: ymin} = bounds, result) | |
when x >= xmax do | |
next(matrix, {x - 1, y + 1}, {0, 1}, %{bounds | ymin: ymin + 1}, result) | |
end | |
# When we get to the bottom edge, start moving left | |
defp next(matrix, {x, y}, _direction, %{ymax: ymax, xmax: xmax} = bounds, result) | |
when y >= ymax do | |
next(matrix, {x - 1, y - 1}, {-1, 0}, %{bounds | xmax: xmax - 1}, result) | |
end | |
# When we get to the left edge, start moving up | |
defp next(matrix, {x, y}, _direction, %{xmin: xmin, ymax: ymax} = bounds, result) | |
when x < xmin do | |
next(matrix, {x + 1, y - 1}, {0, -1}, %{bounds | ymax: ymax - 1}, result) | |
end | |
# When we get to the top edge, start moving right | |
defp next(matrix, {x, y}, _direction, %{ymin: ymin, xmin: xmin} = bounds, result) | |
when y < ymin do | |
next(matrix, {x + 1, y + 1}, {1, 0}, %{bounds | xmin: xmin + 1}, result) | |
end | |
# Process other cells normally | |
defp next(matrix, {x, y}, {dx, dy} = direction, bounds, result) do | |
next(matrix, {x + dx, y + dy}, direction, bounds, [get(matrix, x, y) | result]) | |
end | |
# Returns the matrix element at (x, y) | |
defp get(matrix, x, y), do: matrix |> Enum.at(y) |> Enum.at(x) | |
end | |
l = [ | |
[1, 2, 3], | |
[4, 5, 6], | |
[7, 8, 9] | |
] | |
IO.puts("Input: [ | |
[1, 2, 3], | |
[4, 5, 6], | |
[7, 8, 9] | |
]") | |
IO.puts("Output: #{l |> Spiral.order() |> inspect()}") | |
l = [ | |
[1, 2, 3, 4], | |
[5, 6, 7, 8], | |
[9, 10, 11, 12] | |
] | |
IO.puts("Input: [ | |
[1, 2, 3, 4], | |
[5, 6, 7, 8], | |
[9, 10, 11, 12] | |
]") | |
IO.puts("Output: #{l |> Spiral.order() |> inspect()}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment