The Weekly Challenge - 266


TASK #1: Uncommon Words (*)
You are given two sentences, $sentence1 and $sentence2.

Write a script to find all uncommmon words in any order in the given two sentences. Return ('') if none found.

(*) A word is uncommon if it appears exactly once in one of the sentences and doesn’t appear in other sentence.

#!/usr/bin/perl
use strict;
use warnings;
#-------------------------------------------

sub uncommon_word {
	
    my($s1, $s2) = @_;
 
    my %freq;
    my @result;

    $freq{$_}++ foreach(split(/ /, $s1));	
    $freq{$_}++ foreach(split(/ /, $s2));	

    foreach my $k (keys(%freq)) {
      push(@result, "'$k'") if($freq{$k} == 1);
    }
    print("(", join(", ", @result),")", "\n");
}

my ($s1, $s2);

# Example 1
$s1 = "Mango is sweet";
$s2 = "Mango is sour";
uncommon_word($s1, $s2); # Output: ('sweet', 'sour')

# Example 2
$s1 = "Mango Mango";
$s2 = "Orange";
uncommon_word($s1, $s2); # Output: ('Orange')

# Example 3
$s1 = "Mango is Mango";
$s2 = "Orange is Orange";
uncommon_word($s1, $s2); # Output: ()

TASK #2: X Matrix (*)
You are given a square matrix, $matrix.

Write a script to find if the given matrix is 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 are zero.


Here my solution (1) after some explanation about the square matrix:
=begin
Main diagonal matrix:
In an n×n matrix, the main diagonal spans from the top-left corner to the 
bottom-right corner. 
It consists of the elements where the row index and column index are equal.
So, for any given row index, the column index of the element on the 
diagonal would be calculated as follows:

Diagonal Column Index = Row Index

Antidiagonal matrix:
In an n×n matrix, the antidiagonal spans from the top-right corner to the 
bottom-left corner.
It consists of the elements where the sum of the row index and column index
is equal to n-1, where n is the size of the matrix. 
So, for any given row index, the column index of the element on the
antidiagonal would be calculated as follows:

Antidiagonal Column Index = Size of Matrix − 1 − Row Index

So to check if elements of both diagonal and antidiagonal are not equal to 0,
(and if not, return false) you can write:

for my $i (0 .. $size - 1) {
    return 0 if ($matrix->[$i][$i] == 0); # Check main diagonal
    return 0 if ($matrix->[$i][$size - 1 - $i] == 0); # Check antidiagonal
}

where
- $i represents the row index
- $size represents the number of rows or columns.

All other elements matrix
How to access and check all other matrix elements can be derived from the above rules:

- row index not equal to column index
- row index + column index not equal to size matrix - 1
- $matrix->[$i][$j] == 0 where $i for the row index and $j for the column index

So you can write:

for my $i (0 .. $size - 1) {
    for my $j (0 .. $size - 1) {
        # if not on main diagonal or antidiagonal and not equal to 0, return false
        return 0 if ($i != $j && $i + $j != ($size - 1) && $matrix->[$i][$j] != 0); 
    }
}
=cut
Put it all together:
#!/usr/bin/perl
use strict;
use warnings;
#-------------------------------------------

sub is_x_matrix {
    my $matrix = shift;

    my $size = @$matrix;

    # check main diagonal and antidiagonal
    for my $i (0 .. $size - 1) {
        # check main diagonal    
        return 0 if ($matrix->[$i][$i] == 0);                 
        # check antidiagonal
        return 0 if ($matrix->[$i][$size - 1 - $i] == 0);    
    }

    # check all other elements
    for my $i (0 .. $size - 1) {
        for my $j (0 .. $size - 1) {
            return 0 if ($i != $j && $i + $j != ($size - 1) && $matrix->[$i][$j] != 0);
        }
    }

    # it's an X Matrix
    return 1; 
}

# TESTS

my $matrix;

# Example 1
$matrix = [ [1, 0, 0, 2],
            [0, 3, 4, 0],
            [0, 5, 6, 0],
            [7, 0, 0, 1],
          ];
print(is_x_matrix($matrix), "\n"); # Output: 1 (= TRUE)

# Example 2
$matrix = [ [1, 2, 3],
            [4, 5, 6],
            [7, 8, 9],
          ];
print(is_x_matrix($matrix), "\n"); # Output: 0 (= FALSE)

# Example 3
$matrix = [ [1, 0, 2],
            [0, 3, 0],
            [4, 0, 5],
          ];
print(is_x_matrix($matrix), "\n"); # Output: 1 (= TRUE)
(1) Thanks to Packy Anderson for his valuable alternative.