Peter
Peter Campbell Smith

Solo words and a cross matrix

Weekly challenge 266 — 22 April 2024

Week 266 - 22 Apr 2024

Task 2

Task — X matrix

You are given a square matrix, $matrix. Write a script to find if the given matrix is an X Matrix. A square matrix is an X Matrix if all the elements on the main diagonal and antidiagonal are non-zero and everything else is zero.

Examples


Example 1
Input: $matrix = [ [1, 0, 0, 2],
                   [0, 3, 4, 0],
                   [0, 5, 6, 0],
                   [7, 0, 0, 1],
                 ]
Output: true

Example 2
Input: $matrix = [ [1, 2, 3],
                   [4, 5, 6],
                   [7, 8, 9],
                 ]
Output: false

Example 3
Input: $matrix = [ [1, 0, 2],
                   [0, 3, 0],
                   [4, 0, 5],
                 ]
Output: true

Analysis

I can't think of any way to do this other than to examine each element of the matrix in turn. If the element is not what is needed - non-zero for a diagonal element and zero for an off-diagonal element - we can immediately give up and say 'false'.

Otherwise, once we've examined every element and found no problems we can answer 'true'.

A few weeks ago I wrote a subroutine to print a matrix nicely, and it has come in useful once more.

Try it 

Try running the script with any input:



example: [[1, 0, 2], [0, 3, 0], [4, 0, 5]]

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

use v5.26;    # The Weekly Challenge - 2024-04-22
use utf8;     # Week 266 - task 2 - X matrix
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';

x_matrix([ [1, 0, 0, 2],
           [0, 3, 4, 0],
           [0, 5, 6, 0],
           [7, 0, 0, 1] ]);
           
x_matrix([ [0, 2, 0],
           [4, 0, 6],
           [0, 8, 0] ]);
           
x_matrix([ [1, 0, 0, 0, 1],
           [0, 2, 0, 2, 0],
           [0, 0, 3, 0, 0],
           [0, 4, 0, 4, 0],
           [5, 0, 0, 0, 0] ]);
           
x_matrix([ [1, 0, 2],
           [0, 3, 0],
           [4, 0, 5] ]);
                 
sub x_matrix {
    
    my ($matrix, $dimension, $x, $y);
    
    # initialise
    $matrix = shift;
    $dimension = scalar @$matrix - 1;
    print_matrix(qq[Input: ], $matrix);
    
    # loop over matrix elements
    for $x (0 .. $dimension) {
        for $y (0 .. $dimension) {
            
            # conditions that must be met
            next if ($x == $y or $x == $dimension - $y) ?
                $matrix->[$x]->[$y] != 0 : $matrix->[$x]->[$y] == 0;
            
            # ... but they are not
            say qq[Output: false (∵ matrix[$x, $y] == $matrix->[$x]->[$y])];
            return;
        }
    }
    
    # all values are good
    say qq[Output: true];
}

sub print_matrix {
    
    my ($legend, $matrix, $j);

    # format rows of matrix
    ($legend, $matrix) = @_;
    say '';
    for $j (0 .. @$matrix - 1) {
        say qq{$legend [} . join(', ', @{$matrix->[$j]}) . qq(]);
        $legend = ' ' x length($legend);
    }
}

Output


Input:  [1, 0, 0, 2]
        [0, 3, 4, 0]
        [0, 5, 6, 0]
        [7, 0, 0, 1]
Output: true

Input:  [0, 2, 0]
        [4, 0, 6]
        [0, 8, 0]
Output: false (∵ matrix[0, 0] == 0)

Input:  [1, 0, 0, 0, 1]
        [0, 2, 0, 2, 0]
        [0, 0, 3, 0, 0]
        [0, 4, 0, 4, 0]
        [5, 0, 0, 0, 0]
Output: false (∵ matrix[4, 4] == 0)

Input:  [1, 0, 2]
        [0, 3, 0]
        [4, 0, 5]
Output: true