Peter
Peter Campbell Smith

Flipping members

Weekly challenge 242 — 6 November 2023

Week 242 - 6 Nov 2023

Task 2

Task — Flip matrix

You are given n x n binary matrix. Write a script to flip the given matrix as follows:
Given:


1 1 0
0 1 1
0 0 1
a) Reverse each row:

0 1 1
1 1 0
1 0 0
b) Invert each member:

1 0 0
0 0 1
0 1 1

Examples


Example 1
Input: @matrix = ([1, 1, 0], [1, 0, 1], [0, 0, 0])
Output: ([1, 0, 0], [0, 1, 0], [1, 1, 1])

Example 2
Input: @matrix = ([1, 1, 0, 0], [1, 0, 0, 1], [0, 1, 1, 1], [1, 0, 1, 0])
Output: ([1, 1, 0, 0], [0, 1, 1, 0], [0, 0, 0, 1], [1, 0, 1, 0])

Analysis

This is a task that requires a bit of thought and then not much code. My solution involves references to arrays of references, which allows a very concise solution but maybe not the most readable one. For someone unfamiliar with Perl a statement such as
@row = @{$_[$j]};
may be rather impenetrable, though all it's doing is assigning the jth row of the input matrix to the array @row - and by the way that's the jth row counting from zero.

For production code which might have to be maintained by someone else I'd probably expand that into several lines unless performance were an issue - which with today's computers it rarely is.

The essence of my solution is this line of code:

$flipped[$j][$_] = 1 - $row[$n - $_] for (0 .. $n);

The use of $n - $_ reverses the order, and the 1 - flips the bits, but again that's not terribly obvious: for example, realising that $_ is the iterating variable in the for loop, and that the left hand side of the assignment is simply an element of a 2-dimensional array.

It's also interesting that printing out the matrix takes almost as much code as creating it, and again the code is probably rather opaque for a Perl newbie.

Try it 

Try running the script with any input:



example: [1, 0, 0], [0, 1, 0], [0, 0, 1]

Script


#!/usr/bin/perl

use v5.16;    # The Weekly Challenge - 2023-11-06
use utf8;     # Week 242 task 2 - Flip matrix
use strict;   # Peter Campbell Smith
use warnings; # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

flip_matrix([1, 1, 0],
            [0, 1, 1],
            [0, 0, 1]);
            
flip_matrix([1, 1, 0, 0], 
            [1, 0, 0, 1], 
            [0, 1, 1, 1], 
            [1, 0, 1, 0]);

flip_matrix([1, 0, 0, 0, 0],
            [0, 1, 0, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 0, 1, 0],
            [0, 0, 0, 0, 1]);

sub flip_matrix {
    
    my ($n, $j, @row, @flipped);
    
    # reverse and flip
    $n = @{$_[0]} - 1;      
    for $j (0 .. $n) {
        @row = @{$_[$j]};
        $flipped[$j][$_] = 1 - $row[$n - $_] for (0 .. $n);
    }
    
    # show input and output
    print_matrix(qq(\nInput:  [), \@_);
    print_matrix(qq(\nOutput: [), \@flipped)
}

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

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

Output


Input:  [1, 1, 0]
        [0, 1, 1]
        [0, 0, 1]

Output: [1, 0, 0]
        [0, 0, 1]
        [0, 1, 1]

Input:  [1, 1, 0, 0]
        [1, 0, 0, 1]
        [0, 1, 1, 1]
        [1, 0, 1, 0]

Output: [1, 1, 0, 0]
        [0, 1, 1, 0]
        [0, 0, 0, 1]
        [1, 0, 1, 0]

Input:  [1, 0, 0, 0, 0]
        [0, 1, 0, 0, 0]
        [0, 0, 1, 0, 0]
        [0, 0, 0, 1, 0]
        [0, 0, 0, 0, 1]

Output: [1, 1, 1, 1, 0]
        [1, 1, 1, 0, 1]
        [1, 1, 0, 1, 1]
        [1, 0, 1, 1, 1]
        [0, 1, 1, 1, 1]