ðŸŽ‰ Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io ðŸŽ‰

angelikatyborska's solution

to Matrix in the Elixir Track

Published at May 01 2021 · 0 comments
Instructions
Test suite
Solution

Note:

This exercise has changed since this solution was written.

Given a string representing a matrix of numbers, return the rows and columns of that matrix.

So given a string with embedded newlines like:

``````9 8 7
5 3 2
6 6 7
``````

representing this matrix:

``````    0  1  2
|---------
0 | 9  8  7
1 | 5  3  2
2 | 6  6  7
``````

your code should be able to spit out:

• A list of the rows, reading each row left-to-right while moving top-to-bottom across the rows,
• A list of the columns, reading each column top-to-bottom while moving from left-to-right.

The rows for our example matrix:

• 9, 8, 7
• 5, 3, 2
• 6, 6, 7

And its columns:

• 9, 5, 6
• 8, 3, 6
• 7, 2, 7

Running tests

Execute the tests with:

``````\$ elixir 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
``````

For more detailed information about the Elixir track, please see the help page.

Source

Warmup to the `saddle-points` warmup. http://jumpstartlab.com

Submitting Incomplete Solutions

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

matrix_test.exs

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

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

defmodule MatrixTest do
use ExUnit.Case

@input "1 2 3\n4 5 6\n7 8 9"

# @tag :pending
test "reading from and writing to string" do
matrix = Matrix.from_string(@input)
assert Matrix.to_string(matrix) == @input
end

@tag :pending
test "rows should return nested lists regardless of internal structure" do
matrix = Matrix.from_string(@input)

assert Matrix.rows(matrix) == [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
end

@tag :pending
test "row should return list at index" do
matrix = Matrix.from_string(@input)

assert Matrix.row(matrix, 0) == [1, 2, 3]
assert Matrix.row(matrix, 1) == [4, 5, 6]
assert Matrix.row(matrix, 2) == [7, 8, 9]
end

@tag :pending
test "columns should return nested lists regardless of internal structure" do
matrix = Matrix.from_string(@input)

assert Matrix.columns(matrix) == [
[1, 4, 7],
[2, 5, 8],
[3, 6, 9]
]
end

@tag :pending
test "column should return list at index" do
matrix = Matrix.from_string(@input)

assert Matrix.column(matrix, 0) == [1, 4, 7]
assert Matrix.column(matrix, 1) == [2, 5, 8]
assert Matrix.column(matrix, 2) == [3, 6, 9]
end
end``````
``````defmodule Matrix do
defstruct matrix: nil

@row_separator "\n"
@column_separator " "

@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
rows =
input
|> String.split(@row_separator)
|> Enum.map(fn row ->
row
|> String.split(@column_separator)
|> Enum.map(&String.to_integer/1)
end)

%Matrix{matrix: rows}
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{matrix: rows}) do
rows
|> Enum.map(fn row ->
row
|> Enum.map(&"#{&1}")
|> Enum.join(@column_separator)
end)
|> Enum.join(@row_separator)
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{matrix: rows}) do
rows
end

@doc """
Given a `matrix` and `index`, return the row at `index`.
"""
@spec row(matrix :: %Matrix{}, index :: integer) :: list(integer)
def row(matrix, index) do
matrix
|> rows()
|> Enum.at(index)
end

@doc """
Given a `matrix`, return its columns as a list of lists of integers.
"""
@spec columns(matrix :: %Matrix{}) :: list(list(integer))
def columns(%Matrix{matrix: rows}) do
rows
|> Enum.zip()
|> Enum.map(&Tuple.to_list/1)
end

@doc """
Given a `matrix` and `index`, return the column at `index`.
"""
@spec column(matrix :: %Matrix{}, index :: integer) :: list(integer)
def column(matrix, index) do
matrix
|> columns()
|> Enum.at(index)
end
end``````