This is my response to The Weekly Challenge #271.
m x n
binary matrix.
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.
File: maximum-ones
#! /usr/bin/env raku
unit sub MAIN ($string = "0 0 | 1 1 | 0 0", :v(:$verbose)); # [1]
my $matrix = $string.split("|")>>.words>>.Int>>.Array; # [2]
die "The rows must have the same size" unless [==] $matrix>>.elems; # [3]
die "Must contain 0s and 1s only" unless all($matrix[*;*]) ~~ one(0,1); # [4]
my @sum = $matrix>>.sum.pairs # [5]
.sort({ $^b.value <=> $^a.value || $^a.key <=> $^b.key }); # [5a]
say ": index => sums: { @sum.raku } (zero based index)" if $verbose;
say 1 + @sum[0].key; # [6]
[1] Note the default matrix, and the syntax for specifying it as a string.
[2] Convert the matrix-as-a-string thingy to a two dimentional array.
[3] Ensure that all the rows have the same length.
[4] Retrieve all the values and ensure that all of them are oither 0 or 1.
[5] Apply sum
on each row to reduce the rows to a single
value. Then turn the sums into an array of Pair objects with pairs
. The
key is the index from the former array, and the value is the former value
itself. Then we sort this array, on the value part (highest first), and then
if the values are equal on the key (row number; lowest first).
See docs.raku.org/routine/pairs for more information about pairs
.
[6] Get the first result, and add 1 to the index as the challenge uses 1 for the first row (and Raku is zero based).
Running it:
$ ./maximum-ones "0 1 | 1 0"
1
$ ./maximum-ones "0 0 0 | 1 0 1"
2
$ ./maximum-ones
2
Looking good.
With verbose mode:
$ ./maximum-ones -v "0 1 | 1 0"
: index => sums: [0 => 1, 1 => 1] (zero based index)
1
$ ./maximum-ones -v "0 0 0 | 1 0 1"
: index => sums: [1 => 2, 0 => 0] (zero based index)
2
$ ./maximum-ones -v
: index => sums: [1 => 2, 0 => 0, 2 => 0] (zero based index)
2
@ints
.
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
.
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.
The challenge does not say anything about duplicate values, so I have chosen to allow it.
File: sort-by-1-bits
#! /usr/bin/env raku
unit sub MAIN (*@ints where @ints.elems > 0, :v(:$verbose)); # [1]
die "Non-negative integers only" unless all(@ints) ~~ UInt; # [2]
my @binary = @ints.map({ $_.fmt('%b').comb.sum => $_ }) # [3]
.sort({$^a.key <=> $^b.key || $^a.value <=> $^b.value }); # [3a]
@binary.map({ say ": { $_.value } = { $_.key } one bits" }) if $verbose;
say '(', @binary.map( *.value ).join(", "), ')'; # [4]
[1] Ensure at least on element.
[2] They must all be unsigned integers.
[3] {ID:fmt}} The map
part converts the value to binary (with fmt
),
them we split that number into individual characters (with comb
), and
add them all together with sum
- thus giving the number of 1 bits.
That is on the left hand side of the Pair (created with the =>
thing).
The value itself is the value of the pair. Then we sort the pairs.
See docs.raku.org/routine/fmt for more information about fmt
.
[4] Use map
to convert the pair objects into the value part, and pritty
print the result.
Running it:
$ ./sort-by-1-bits 0 1 2 3 4 5 6 7 8
(0, 1, 2, 4, 8, 3, 5, 6, 7)
$ ./sort-by-1-bits 1024 512 256 128 64
(64, 128, 256, 512, 1024)
Looking good.
With verbose mode:
$ ./sort-by-1-bits -v 0 1 2 3 4 5 6 7 8
: 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
(0, 1, 2, 4, 8, 3, 5, 6, 7)
$ ./sort-by-1-bits -v 1024 512 256 128 64
: 64 = 1 one bits
: 128 = 1 one bits
: 256 = 1 one bits
: 512 = 1 one bits
: 1024 = 1 one bits
(64, 128, 256, 512, 1024)
And that's it.