The Weekly Challenge - 271


TASK #1: Maximum Ones
You are given a m x n binary matrix.

Write a script to return the row number containing maximum ones, in case of more than one rows then return smallest row number.

#!/usr/bin/perl
use strict;
use warnings;
use Math::Matrix;

sub row_max_ones {
	
    my ($x) = @_;	
    # a boolean matrix is a matrix whose entries are either 0 or 1
    if ( $x -> is_bool() ) {

        # find() returns the location of each non-zero element in terms of $i and $j.
        # e.g. (0, 0), (0, 2), (1, 0) and (2, 0) are the coordinates of value 1 in Example 4 below
        my($i, $j) = $x -> find();
        
        # count occurrences of each element and save into %count
        my %count;
        
        foreach my $elem (@$i) {
            $count{$elem}++; 
        }    
        
        # alternatively: map { $count{$_}++ } @$i;
        
        # iterate through the hash to find the maximum value
        my ($max_value, $max_row) = (0, 0);
                
        foreach my $row (sort keys(%count)) {

            if ($count{$row} > $max_value) {
                $max_value = $count{$row};
                # assign $row to $max_row only if both $max_value and $row have become new values
                $max_row = $row if ($max_value != 0 && $row != $max_row);
            }
        }

        print("Row maximum ones: ", ($max_row + 1), "\n");

    }        
    else {
        print("Error: no valid matrix!\n");	
    }	
}

# TESTS
my $matrix;

# Example 1
$matrix = [ [0, 1],
            [1, 0],
          ];
row_max_ones(Math::Matrix -> new($matrix)); # Output: 1

# Example 2
$matrix = [ [0, 0, 0],
            [1, 0, 1],
          ];
row_max_ones(Math::Matrix -> new($matrix)); # Output: 2

# Example 3
$matrix = [ [0, 0],
            [1, 1],
            [0, 0],
          ];
row_max_ones(Math::Matrix -> new($matrix)); # Output: 2

# own test cases
my $x;

# Example 4
$x = Math::Matrix -> new([1, 0, 1],
                         [1, 0, 0],
                         [1, 0, 0]);

row_max_ones($x); # Output: 1

# Example 5
$x = Math::Matrix -> new([1, 0, 0],
                         [1, 0, 0],
                         [1, 0, 1]);

row_max_ones($x); # Output: 3

# Example 6
$x = Math::Matrix -> new([1, 0, 0],
                         [1, 0, 1],
                         [1, 0, 1]);

row_max_ones($x); # Output: 2

TASK #2: Sort by 1 bits
You are give an array of integers, @ints.

Write a script to sort the integers in ascending order by the number of 1 bits in their binary representation. In case more than one integers have the same number of 1 bits then sort them in ascending order.
#!/usr/bin/perl
use strict;
use warnings;

# function to count the number of 1 bits in the binary representation
sub count_ones {
    return(my $count = sprintf("%b", @_) =~ tr/1//);
}

sub count_sort_1_bits {
    my @numbers = @_;
    
    # count the number of 1 bits for each number and save to %hash
    my %hash;
    foreach my $number (@numbers) {
        my $ones_count = count_ones($number);
        $hash{$number} = $ones_count;
    }

    # sort keys by their values in ascending order
    my @sorted_keys_asc = sort( { $hash{$a} <=> $hash{$b} or $a <=> $b } (sort keys %hash) );

    # join for the right output
    print("(", join(", ", @sorted_keys_asc), ")\n");
}

# TESTS
my @numbers = (0, 1, 2, 3, 4, 5, 6, 7, 8);
count_sort_1_bits(@numbers); # Output: (0, 1, 2, 4, 8, 3, 5, 6, 7)

@numbers = (1024, 512, 256, 128, 64);
count_sort_1_bits(@numbers); # Output: (64, 128, 256, 512, 1024)

@numbers = (7, 23, 512, 256, 128, 64);
count_sort_1_bits(@numbers); # Output: (64, 128, 256, 512, 7, 23)