# You are my only ones... **Challenge 271 solutions in Perl by Matthias Muth** ## 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.
> **Example 1** > Input: $matrix = [ [0, 1], > [1, 0], > ] > Output: 1 > Row 1 and Row 2 have the same number of ones, so return row 1. > **Example 2** > Input: $matrix = [ [0, 0, 0], > [1, 0, 1], > ] > Output: 2 > Row 2 has the maximum ones, so return row 2. > **Example 3** > Input: $matrix = [ [0, 0], > [1, 1], > [0, 0], > ] > Output: 2 > Row 2 have the maximum ones, so return row 2. The most straightforward solution is to - create an array containing the number of ones for each row of the matrix, - find the maximum number of ones in that array (making sure that we get a `0` for an empty array, - find the index of the first entry in the array that is equal to that maximum,
and return it as a row number (adding 1 because the row numbers start with 1). This translates quite easily into Perl code. And there's not even much to say about any possible performance optimizations... ```perl use v5.36; use List::Util qw( max first ); sub maximum_ones( $matrix ) { # Get the number of ones for each row. my @n_ones = map scalar grep( $_ == 1, $_->@* ), $matrix->@*; # Find the highest number of ones. my $max_n_ones = max( @n_ones ); # Return the first row number (1-based, not 0-based!) # that has that highest number of ones. return 1 + first { $n_ones[$_] == $max_n_ones } 0..$#n_ones; } ``` ## 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.
> **Example 1** > Input: @ints = (0, 1, 2, 3, 4, 5, 6, 7, 8) > Output: (0, 1, 2, 4, 8, 3, 5, 6, 7) > 0 = 0 one bits > 1 = 1 one bits > 2 = 1 one bits > 4 = 1 one bits > 8 = 1 one bits > 3 = 2 one bits > 5 = 2 one bits > 6 = 2 one bits > 7 = 3 one bits > **Example 2** > Input: @ints = (1024, 512, 256, 128, 64) > Output: (64, 128, 256, 512, 1024) > All integers in the given array have one 1-bits, so just sort them in ascending order. This task, too, is quite straightforward, once we have solved how to count the one-bits in a number. So let's go for that first.
My preferred solution to count bits is to let `unpack` do the work for me.
The `'%b'` format for `unpack` returns the number of bits in the bit vector we pass in as data (see [here](https://perldoc.perl.org/functions/unpack)). So we turn our number into a bit vector using `pack( 'i', $number )` and let `unpack` do the counting. Once we have a function for that, sorting the input array is simple, using a comparison code block for `sort`.
It compares first the number of bits of the two numbers given in `$a`and `$b`, and if they are equal, it uses the numbers themselves. The well-known Perl idiom using the 'space-ship' operator, which returns `-1`, `0`, or `+1`, and a *logical or* that continues with the next comparison only when needed (the previous one returned a `0`) makes it easy. And that's all! ```perl use v5.36; sub n_bits( $n ) { return unpack "%b*", pack "i", $n; } sub sort_by_1_bits( @ints ) { return sort { n_bits( $a ) <=> n_bits( $b ) || $a <=> $b } @ints; } ``` #### **Thank you for the challenge!**