🎉 Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io 🎉 # dgeiger's solution

## to Matrix in the Delphi Pascal Track

Published at Sep 03 2020 · 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:

``````    1  2  3
|---------
1 | 9  8  7
2 | 5  3  2
3 | 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

## Testing

In order to run the tests for this track, you will need to install DUnitX. Please see the installation instructions for more information.

### Loading Exercises into Delphi

If Delphi is properly installed, and `*.dpr` file types have been associated with Delphi, then double clicking the supplied `*.dpr` file will start Delphi and load the exercise/project. `control + F9` is the keyboard shortcut to compile the project or pressing `F9` will compile and run the project.

Alternatively you may opt to start Delphi and load your project via. the `File` drop down menu.

### When Questions Come Up

We monitor the Pascal-Delphi support room on gitter.im to help you with any questions that might arise.

### Submitting Exercises

Note that, when trying to submit an exercise, make sure the exercise file you're submitting is in the `exercism/delphi/<exerciseName>` directory.

For example, if you're submitting `ubob.pas` for the Bob exercise, the submit command would be something like `exercism submit <path_to_exercism_dir>/delphi/bob/ubob.pas`.

## Source

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

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you may request help from a mentor.

### uMatrixTests.pas

``````unit uMatrixTests;

interface

uses
DUnitX.TestFramework, System.Generics.Collections;

const
CanonicalVersion = '1.1.0.1';

type

[TestFixture]
TMatrixTest = class(TObject)
private
ExpectedRow : TList<integer>;
procedure CompareArrays(Array1, Array2: TArray<integer>);
public
[Setup]
procedure Setup;

[TearDown]
procedure TearDown;

[Test]
//    [Ignore('Comment the "[Ignore]" statement to run the test')]
procedure extract_row_from_one_number_matrix;

[Test]
[Ignore]
procedure can_extract_row;

[Test]
[Ignore]
procedure extract_row_where_numbers_have_different_widths;

[Test]
[Ignore]
procedure can_extract_row_from_non_square_matrix;

[Test]
[Ignore]
procedure extract_column_from_one_number_matrix;

[Test]
[Ignore]
procedure can_extract_column;

[Test]
[Ignore]
procedure can_extract_column_from_non_square_matrix;

[Test]
[Ignore]
procedure extract_column_where_numbers_have_different_widths;
end;

implementation
uses uMatrix;

procedure TMatrixTest.can_extract_column;
var
CUT: TMatrix;
Expected, Actual : TArray<integer>;
i: Integer;
begin
ExpectedRow.AddRange([3, 6, 9]);
Expected := ExpectedRow.ToArray;
CUT := TMatrix.Create('1 2 3\n4 5 6\n7 8 9');
Actual := CUT.column(3);
CompareArrays(Expected, Actual);
end;

procedure TMatrixTest.can_extract_column_from_non_square_matrix;
var
CUT: TMatrix;
Expected, Actual : TArray<integer>;
i: Integer;
begin
ExpectedRow.AddRange([3, 6, 9, 6]);
Expected := ExpectedRow.ToArray;
CUT := TMatrix.Create('1 2 3\n4 5 6\n7 8 9\n8 7 6');
Actual := CUT.column(3);
CompareArrays(Expected, Actual);
end;

procedure TMatrixTest.can_extract_row;
var
CUT: TMatrix;
Expected, Actual : TArray<integer>;
i: Integer;
begin
ExpectedRow.AddRange([3, 4]);
Expected := ExpectedRow.ToArray;
CUT := TMatrix.Create('1 2\n3 4');
Actual := CUT.Row(2);
CompareArrays(Expected, Actual);
end;

procedure TMatrixTest.can_extract_row_from_non_square_matrix;
var
CUT: TMatrix;
Expected, Actual : TArray<integer>;
i: Integer;
begin
ExpectedRow.AddRange([7, 8, 9]);
Expected := ExpectedRow.ToArray;
CUT := TMatrix.Create('1 2 3\n4 5 6\n7 8 9\n8 7 6');
Actual := CUT.Row(3);
CompareArrays(Expected, Actual);
end;

procedure TMatrixTest.extract_column_from_one_number_matrix;
var
CUT: TMatrix;
Expected, Actual : TArray<integer>;
i: Integer;
begin
ExpectedRow.AddRange();
Expected := ExpectedRow.ToArray;
CUT := TMatrix.Create('1');
Actual := CUT.column(1);
CompareArrays(Expected, Actual);
end;

procedure TMatrixTest.extract_column_where_numbers_have_different_widths;
var
CUT: TMatrix;
Expected, Actual : TArray<integer>;
i: Integer;
begin
ExpectedRow.AddRange([1903, 3, 4]);
Expected := ExpectedRow.ToArray;
CUT := TMatrix.Create('89 1903 3\n18 3 1\n9 4 800');
Actual := CUT.column(2);
CompareArrays(Expected, Actual);
end;

procedure TMatrixTest.extract_row_from_one_number_matrix;
var
CUT: TMatrix;
Expected, Actual : TArray<integer>;
i: Integer;
begin
ExpectedRow.AddRange();
Expected := ExpectedRow.ToArray;
CUT := TMatrix.Create('1');
Actual := CUT.Row(1);
CompareArrays(Expected, Actual);
end;

procedure TMatrixTest.extract_row_where_numbers_have_different_widths;
var
CUT: TMatrix;
Expected, Actual : TArray<integer>;
i: Integer;
begin
ExpectedRow.AddRange([10, 20]);
Expected := ExpectedRow.ToArray;
CUT := TMatrix.Create('1 2\n10 20');
Actual := CUT.Row(2);
CompareArrays(Expected, Actual);
end;

procedure TMatrixTest.CompareArrays(Array1, Array2: TArray<integer>);
var
i: integer;
begin
Assert.AreEqual(Length(Array1), Length(Array2));
for i := Low(Array1) to High(Array1) do
Assert.AreEqual(Array1[i], Array2[i]);
end;

procedure TMatrixTest.Setup;
begin
ExpectedRow := TList<integer>.Create;
end;

procedure TMatrixTest.TearDown;
begin
ExpectedRow.DisposeOf;
end;

initialization
TDUnitX.RegisterTestFixture(TMatrixTest);
end.``````
``````unit uMatrix;

interface

uses
System.Classes, System.Generics.Collections, System.SysUtils;

type
TMatrix = class
private
FMatrix: TArray<TArray<Integer>>;
FMatrixString: String;
FColumns: Integer;
FRows: Integer;
FRow: Integer;

procedure ExtractRows;
procedure ExtractElements;

public
constructor Create(MatrixString: String);

function Column(ColumnNo: Integer): TArray<Integer>;
function Row(RowNo: Integer): TArray<Integer>;

end;

implementation

{ TMatrix }

function TMatrix.Column(ColumnNo: Integer): TArray<Integer>;
var
Row: Integer;
begin
// Set the length of the result TArray to the number of rows
SetLength(Result, FRows);

// If ColumnNo is outside the range of columms in the matrix (when scaled)
// it can't be processed, so quit.
if (ColumnNo < 1) or (ColumnNo > Length(FMatrix)) then
Exit;

// Now, we need to cycle through the rows
for Row := 0 to FRows - 1 do
// adding the element in the specified column to the result.
Result[Row] := FMatrix[Row, ColumnNo - 1];
end;

constructor TMatrix.Create(MatrixString: String);
begin
// Start of by saving the passed string
FMatrixString := Trim(MatrixString);

// Then extract the elements from the string and insert them into the matrix
ExtractRows;
end;

procedure TMatrix.ExtractElements;
var
Elements: TList<Integer>;
Position: Integer;
ElementString: String;
Column: Integer;
begin
// Create the list of elements found
Elements := TList<Integer>.Create;

// Start with no columns in the row - we'll figure out the size later
FColumns := 0;

// We look for elements until the string is empty
while Length(FMatrixString) > 0 do
begin
// Look for a space between elements
Position := Pos(' ', FMatrixString);

if Position = 0 then
// There was no space, so this is the last element
begin
// Save it's value
ElementString := FMatrixString;

// and empty the string, signaling that we're done here.
FMatrixString := '';
end
else
// We found the gap between two elements
begin
// Save the element's value
ElementString := Copy(FMatrixString, 1, Position - 1);

// Remove the element from the string
Delete(FMatrixString, 1, Position);

// Make sute there aren't any spaces in the front of the string
FMatrixString := Trim(FMatrixString);
end;

// Add the element to the string. In the real world, I'd be checking
// to make sure the element was an integer, but I'm omitting it for
// this exercixe.
Elements.Add(StrToInt(ElementString));

// Add to the column count
Inc(FColumns);
end;

// Set the matrix row's size
SetLength(FMatrix[FRow], FColumns);

// Now it's time to put the elements into the matrix row
for Column := 0 to FColumns - 1 do
begin
// Set the cell to the element value
FMatrix[FRow, Column] := Elements;

// and remove the element value from the list.
Elements.Delete(0);
end;

// Clean up
Elements.Destroy;
end;

procedure TMatrix.ExtractRows;
var
Rows: TStringList;
Position: Integer;
RowString: String;
Index: Integer;
begin
// Create the list of rows found
Rows := TStringList.Create;

// Start with no rows in the matrix - we'll figure out the size later
FRows := 0;

// We look for rows until the string is empty
while Length(FMatrixString) > 0 do
begin
// Look for the new-line sequence between rows
Position := Pos('\', FMatrixString);

// There was no new-line sequence, so this is the last row
if Position = 0 then
begin
// Save it's value
RowString := FMatrixString;

// and empty the string, signaling that we're done here.
FMatrixString := '';
end
else
// There was no new-line sequence, so this is the last element
begin
// Save the row text for later processing
RowString := Copy(FMatrixString, 1, Position - 1);

// and remove it from the string.
Delete(FMatrixString, 1, Position + 1);

// Make sute there aren't any spaces in the front of the string
FMatrixString := Trim(FMatrixString);
end;

// Add the row text to the list of rows
Rows.Add(RowString);

// Increment the row count
Inc(FRows);
end;

// Now that we know how many rows are in the matrix, set it's length
SetLength(FMatrix, FRows);

// Now let's break the rows into columns, and put the cell values in the matrix
for Index := 0 to Rows.Count - 1 do
begin
// Set which row is being processed
FRow := Index;

// Get it's string
FMatrixString := Rows[Index];

// and put the elements into the matrix.
ExtractElements;
end;

// Clean up
Rows.Destroy;
end;

function TMatrix.Row(RowNo: Integer): TArray<Integer>;
var
ColumnNo: Integer;
begin
// Set the length of the result TArray to the number of columns
SetLength(Result, FColumns);

// If RowNo is outside the range of rows in the matrix (when scaled)
// it can't be processed, so quit.
if (RowNo < 1) or (RowNo > Length(FMatrix)) then
Exit;

// Now, we need to cycle through the columns
for ColumnNo := 0 to FColumns - 1 do
// adding the element in the specified row to the result.
Result[ColumnNo] := FMatrix[RowNo - 1, ColumnNo];
end;

end.``````

## Community comments

Find this solution interesting? Ask the author a question to learn more.

### What can you learn from this solution?

A huge amount can be learned from reading other people’s code. This is why we wanted to give exercism users the option of making their solutions public.

Here are some questions to help you reflect on this solution and learn the most from it.

• What compromises have been made?
• Are there new concepts here that you could read more about to improve your understanding?