thekeele's solution

to Matrix in the Elixir Track

Published at Aug 03 2019 · 0 comments
Instructions
Test suite
Solution

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:

``````\$ mix test
``````

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

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

``````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``````

test_helper.exs

``````ExUnit.start()
ExUnit.configure(exclude: :pending, trace: true)``````
``````defmodule Matrix do
@enforce_keys [:data, :rows, :columns]
defstruct data: [], rows: 0, columns: 0

@spec from_string(input :: String.t()) :: %Matrix{}
def from_string(input) do
rows = input |> String.replace(" ", "") |> String.split("\n")
len = length(rows)
data =
Enum.reduce(rows, [], fn row, acc ->
acc ++
(row |> String.codepoints() |> Enum.map(&String.to_integer/1))
end)

%Matrix{rows: len, columns: len, data: data}
end

@spec to_string(matrix :: %Matrix{}) :: String.t()
def to_string(%Matrix{data: data, rows: rows}) do
last = (length(data) - 1)
for index <- 0..last, into: "" do
num = Enum.at(data, index)
cond do
index == last -> "#{num}"
rem(index + 1, rows) == 0 -> "#{num}\n"
true -> "#{num} "
end
end
end

@spec rows(matrix :: %Matrix{}) :: list(list(integer))
def rows(%Matrix{data: data, rows: rows}) do
Enum.chunk_every(data, rows)
end

@spec row(matrix :: %Matrix{}, index :: integer) :: list(integer)
def row(matrix = %Matrix{}, index) do
matrix |> rows() |> Enum.at(index)
end

@spec columns(matrix :: %Matrix{}) :: list(list(integer))
def columns(%Matrix{data: data, rows: rows, columns: columns}) do
for i <- 0..(rows - 1) do
for j <- 0..(columns - 1),
do: Enum.at(data, ((j * columns) + i))
end
end

@spec column(matrix :: %Matrix{}, index :: integer) :: list(integer)
def column(matrix = %Matrix{}, index) do
matrix |> columns() |> Enum.at(index)
end
end``````