Skip to content

Instantly share code, notes, and snippets.

@Jwsonic
Created October 1, 2019 19:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jwsonic/15d2a8ddc9ebb39f703ac979de325b44 to your computer and use it in GitHub Desktop.
Save Jwsonic/15d2a8ddc9ebb39f703ac979de325b44 to your computer and use it in GitHub Desktop.
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