This is my response to The Weekly Challenge #253.
Input: @words = ("one.two.three","four.five","six")
$separator = "."
Output: "one","two","three","four","five","six"
Example 2:
Input: @words = ("$perl$$", "$$raku$")
$separator = "$"
Output: "perl","raku"
#! /usr/bin/env raku
unit sub MAIN ($separator where $separator.chars == 1,
*@words where @words.elems > 0);
say @words>>.split($separator).[*;*].grep( *.chars ).map( '"' ~ * ~ '"' ).join(",");
[unit] First a (single) separator character on the command line, followed by a slurpy array of (one or more) words.
[say] Split each word (with >>.split($separator)
) on the separator.
This gives us a two dimentional array, which we flatten with [*;*]
.
Then we use grep( *.chars )
to get rid of empty words (i.e. without
length), and map( '"' ~ * ~ '"' )
to wrap each word in quotes. Finally
we apply join(",")
to get a comma separated string of words.
Running it:
$ ./split-strings "." "one.two.three" "four.five" "six"
"one","two","three","four","five","six"
$ ./split-strings "$" "$perl$$" "$$raku$"
"8169","8169raku"
Ooops.
The Shell replaces $$
with the process ID of the shell itself. Using
single quotes instead of double quotes will prevent this replacement.
$ ./split-strings '$' '$perl$$' '$$raku$'
"perl","raku"
m x n
binary matrix i.e. only 0
and 1
where
1
always appear before 0
.
i
is weaker than a row j
if one of the following is true:
1
s in row i
is less than the number of
1
s in row j
1
and i < j
Input: $matrix = [
[1, 1, 0, 0, 0],
[1, 1, 1, 1, 0],
[1, 0, 0, 0, 0],
[1, 1, 0, 0, 0],
[1, 1, 1, 1, 1]
]
Output: (2, 0, 3, 1, 4)
The number of 1s in each row is:
- Row 0: 2
- Row 1: 4
- Row 2: 1
- Row 3: 2
- Row 4: 5
Example 2:
Input: $matrix = [
[1, 0, 0, 0],
[1, 1, 1, 1],
[1, 0, 0, 0],
[1, 0, 0, 0]
]
Output: (0, 2, 3, 1)
The number of 1s in each row is:
- Row 0: 1
- Row 1: 4
- Row 2: 1
- Row 3: 1
File: weakest-row
#! /usr/bin/env raku
unit sub MAIN ($string = "1 0 0 0 | 1 1 1 1 | 1 0 0 0 | 1 0 0 0", # [1]
:v(:$verbose));
my $matrix = $string.split("|")>>.words>>.Int>>.Array; # [2]
my @values = $matrix[*;*]; # [3]
die "The rows must have the same size" unless [==] $matrix>>.elems; # [4]
die "0 and 1 only" unless all(@values) ~~ any(0,1); # [5]
die "1 before 0 only" unless $matrix>>.reduce( &infix:«>=» ); # [6]
my @pairs = $matrix>>.sum.pairs; # [7]
my @sorted = @pairs.sort({ $^a.value <=> $^b.value || $^a.key <=> $^b.key });
# [8]
say ":Pairs: { @pairs.raku }" if $verbose;
say ":Sorted: { @sorted.raku }" if $verbose;
say "({ @sorted>>.key.join(", ") })"; # [9]
[1] Note the default matrix. The matrix parsing code was last seen two weeks ago; Lucky Concatenation with Raku (scroll down to #251.2 Lucky Numbers).
[2] Get the matrix (a two dimentional array).
[3] Get the values (a one dimentional array).
[4] The rows in the matrix must have the same size.
[5] The matrix can only contain zeroes and ones.
[6] For each row, ensure that the values from the left are larger than or equal to the next one.
[7] Get the sum (i.e. the number of ones) for each row, and
turn those sums into Pair objects with pairs
- with the index as key,
and the sum as value.
See docs.raku.org/routine/pairs for more information about pairs
.
[8] Sort the array, using the values (the number of ones), and secondary the row number (the former array index).
[9] Print the key part (the row index) of the pairs.
Running it:
$ ./weakest-row "1 1 0 0 0 | 1 1 1 1 0 | 1 0 0 0 0 | 1 1 0 0 0 | 1 1 1 1 1"
(2, 0, 3, 1, 4)
$ ./weakest-row
(0, 2, 3, 1)
Looking good.
With verbose mode:
$ ./weakest-row -v "1 1 0 0 0 | 1 1 1 1 0 | 1 0 0 0 0 | 1 1 0 0 0 | 1 1 1 1 1"
:Pairs: [0 => 2, 1 => 4, 2 => 1, 3 => 2, 4 => 5]
:Sorted: [2 => 1, 0 => 2, 3 => 2, 1 => 4, 4 => 5]
(2, 0, 3, 1, 4)
$ ./weakest-row -v
:Pairs: [0 => 1, 1 => 4, 2 => 1, 3 => 1]
:Sorted: [0 => 1, 2 => 1, 3 => 1, 1 => 4]
(0, 2, 3, 1)
And that's it.