Perl Weekly Challenge 242: Flip Matrix

These are some answers to the Week 242, Task 2, of the Perl Weekly Challenge organized by Mohammad S. Anwar.

Spoiler Alert: This weekly challenge deadline is due in a few days from now (on November 12, 2023, at 23:59). This blog post offers some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.

Task 2: Flip Matrix

You are given n x n binary matrix.

Write a script to flip the given matrix as below.

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

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])

Flip Matrix in Raku

The flip-matrix subroutine simply traverses the rows of the input matrix, reverses them and inverts each item of the row. It could easily be done in a single code line, but we kept two lines to better express the two steps of the process.

sub flip-matrix (@input) {
    my @in = @input;
    my @out;
    for @in -> @row {
        my @rev = @row.reverse;
        push @out, map { $_ eq '0' ?? 1 !! 0 }, @rev;
    }
    return @out;
}
for (<1 1 0>, <0 1 1>, <0 0 1>), 
    (<1 1 0>, <1 0 1>, <0 0 0>),
    (<1 1 0 0>, <1 0 0 1>, <0 1 1 1>, <1 0 1 0>)
    -> @test {
    say @test, " => ", flip-matrix @test;  
}

This program displays the following output:

$ raku ./flip-matrix.raku
((1 1 0) (0 1 1) (0 0 1)) => [(1 0 0) (0 0 1) (0 1 1)]
((1 1 0) (1 0 1) (0 0 0)) => [(1 0 0) (0 1 0) (1 1 1)]
((1 1 0 0) (1 0 0 1) (0 1 1 1) (1 0 1 0)) => [(1 1 0 0) (0 1 1 0)
    (0 0 0 1) (1 0 1 0)]

Flip Matrix in Perl

This is a port to Perl of the above Raku program. Again, the flip_matrix subroutine traverses the rows of the input matrix, reverses them and inverts each item of the row. It is slightly more complicated than the Raku version because it is a bit of a pain in the neck to display properly references to nested arrays. This is the reason for which we added a helper subroutine, stringify_matrix, to display both the input and the output matrices.

use strict;
use warnings;
use feature 'say';

sub stringify_matrix {
    my @in = @_;
    my $out = "";
    $out .=  "(@$_) " for @in;
    return $out;
}

sub flip_matrix {
    my @in = @_;
    my @out;
    for my $row (@in) {
        my @rev = reverse @$row;
        push @out, [map { $_ eq '0' ? 1 : 0 } @rev];
    }
    return @out;
}
for my $test ([[<1 1 0>], [<0 1 1>], [<0 0 1>]], 
    [[<1 1 0>], [<1 0 1>], [<0 0 0>]],
    [[<1 1 0 0>], [<1 0 0 1>], [<0 1 1 1>], [<1 0 1 0>]]) {
    print stringify_matrix @$test; 
    say " => ", stringify_matrix flip_matrix @$test;  
}

This program displays the following output:

$ perl ./flip-matrix.pl
(1 1 0) (0 1 1) (0 0 1)  => (1 0 0) (0 0 1) (0 1 1)
(1 1 0) (1 0 1) (0 0 0)  => (1 0 0) (0 1 0) (1 1 1)
(1 1 0 0) (1 0 0 1) (0 1 1 1) (1 0 1 0)  => (1 1 0 0) (0 1 1 0) 
    (0 0 0 1) (1 0 1 0)

Wrapping up

The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on November 19, 2023. And, please, also spread the word about the Perl Weekly Challenge if you can.

Leave a comment

About laurent_r

user-pic I am the author of the "Think Perl 6" book (O'Reilly, 2017) and I blog about the Perl 5 and Raku programming languages.