Matrix

Matrix

Medium

Instructions

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

New AWK concepts

This is the first exercise where the solution is not a "main" script. The goal is to write a library of functions to be included into other awk programs. There are several interesting new concepts to see in this exercise.

The following sections that are tagged with "(gawk)" are specifically GNU awk extensions.

Reading from a file

In this exercise, you'll be reading data from a file, not from the main input stream. Read about getline in the Gnu awk manual, particularly the Getline/File and Getline/Variable/File forms.

More about arrays

A two-dimensional array might be a way to implement this solution. GNU awk has two ways to represent one:

Include files (gawk)

Notice the @include directive in the test file.
This instructs gawk to read and evaluate the named file.

Namespaces (gawk)

All awk variables are global (except for function parameters which are local to the function). There is a high potential for name collisions, particularly when third-party libraries get included. Namespaces are a way to partition where variables are stored. Notice the @namespace directive in the exercise's files.

The default namespace is named "awk". Having a default namespace allows the programmer to call a builtin awk function from inside a function in a different namespace.

How function parameters are passed

Array parameters are passed by reference. Changes to the array made in the function are visible in the caller.

Non-array parameters are passed by value.

For untyped parameters, it depends on what the function does with them:

  • if the function initializes it as an array, then it becomes a parameter passed by reference,
  • if the function initializes it as a scalar value (a number or a string), then it is not a reference.

Full details are in the manual in Passing Function Arguments by Value Or by Reference.

Local variables

Function scoped (local) variables can be created by using "pass by value" parameters. It is not an error to pass fewer values to a function than the number of listed parameters; the excess parameters are "untyped" until they get used. They are available to be assigned scalar values in the function that are not stored in the global namespace.

  • If you assign a scalar value to a parameter, that is local to the function.
  • If you assign a scalar to a variable not named in the parameter list, that variable is global.

By convention, in the function signature the expected parameters appear first followed by some whitespace and then the local parameters. An example:

function add(a, b,    total) {
    # here, `typeof(total)` is "untyped"
    total = a + b
    # now, `typeof(total)` is "number"
    return total
}

BEGIN {
    sum = add(5, 10)
    print sum             # 15
    print typeof(total)   # untyped, meaning "total" is unused in this scope
}
Edit via GitHub The link opens in a new window or tab
AWK Exercism

Ready to start Matrix?

Sign up to Exercism to learn and master AWK with 70 exercises, and real human mentoring, all for free.