exercism/elixir/matrix/matrix.exs

58 lines
1.7 KiB
Elixir

defmodule Matrix do
defstruct matrix: nil
@doc """
Convert an `input` string, with rows separated by newlines and values
separated by single spaces, into a `Matrix` struct.
"""
@spec from_string(input :: String.t()) :: %Matrix{}
def from_string(input) do
input
|> String.split("\n")
|> Enum.map(&String.split(&1, " "))
|> Enum.map(fn row -> Enum.map(row, &String.to_integer/1) end)
end
@doc """
Write the `matrix` out as a string, with rows separated by newlines and
values separated by single spaces.
"""
@spec to_string(matrix :: %Matrix{}) :: String.t()
def to_string(matrix) do
Enum.join(Enum.map(matrix, &Enum.join(&1, " ")), "\n")
end
@doc """
Given a `matrix`, return its rows as a list of lists of integers.
"""
@spec rows(matrix :: %Matrix{}) :: list(list(integer))
def rows(matrix), do: matrix
@doc """
Given a `matrix` and `index`, return the row at `index`.
"""
@spec row(matrix :: %Matrix{}, index :: integer) :: list(integer)
def row([head | _tail], 0), do: head
def row([_head | tail], index), do: row(tail, index - 1)
@doc """
Given a `matrix`, return its columns as a list of lists of integers.
"""
@spec columns(matrix :: %Matrix{}) :: list(list(integer))
def columns(matrix), do: rows(transpose(matrix))
@doc """
Given a `matrix` and `index`, return the column at `index`.
"""
@spec column(matrix :: %Matrix{}, index :: integer) :: list(integer)
def column(matrix, index), do: row(transpose(matrix), index)
@doc """
swap rows and columns of a matrix
inspired by: http://exercism.io/submissions/dc8f7aff89864956b59d6077477ce9ce
"""
defp transpose(matrix) do
Enum.map(List.zip(matrix), &Tuple.to_list/1)
end
end