diff options
| author | Mohammad Sajid Anwar <Mohammad.Anwar@yahoo.com> | 2025-09-06 09:56:44 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-06 09:56:44 +0100 |
| commit | c3b746301adc1d6c8b64386ac75d353c28e0ad62 (patch) | |
| tree | 072d76460f073391a5083037ce3559ee3c06be01 | |
| parent | 2a566dd79aad10642ac37c3b92dd976985f77823 (diff) | |
| parent | 8689926595e9c553f50214926fa695b695982123 (diff) | |
| download | perlweeklychallenge-club-c3b746301adc1d6c8b64386ac75d353c28e0ad62.tar.gz perlweeklychallenge-club-c3b746301adc1d6c8b64386ac75d353c28e0ad62.tar.bz2 perlweeklychallenge-club-c3b746301adc1d6c8b64386ac75d353c28e0ad62.zip | |
Merge pull request #12630 from PerlMonk-Athanasius/branch-for-challenge-337
Perl & Raku solutions to Tasks 1 & 2 for Week 337
| -rw-r--r-- | challenge-337/athanasius/perl/ch-1.pl | 194 | ||||
| -rw-r--r-- | challenge-337/athanasius/perl/ch-2.pl | 417 | ||||
| -rw-r--r-- | challenge-337/athanasius/raku/ch-1.raku | 187 | ||||
| -rw-r--r-- | challenge-337/athanasius/raku/ch-2.raku | 405 |
4 files changed, 1203 insertions, 0 deletions
diff --git a/challenge-337/athanasius/perl/ch-1.pl b/challenge-337/athanasius/perl/ch-1.pl new file mode 100644 index 0000000000..c5c8776b87 --- /dev/null +++ b/challenge-337/athanasius/perl/ch-1.pl @@ -0,0 +1,194 @@ +#!perl + +################################################################################ +=comment + +Perl Weekly Challenge 337 +========================= + +TASK #1 +------- +*Smaller Than Current* + +Submitted by: Mohammad Sajid Anwar + +You are given an array of numbers, @num1. + +Write a script to return an array, @num2, where $num2[i] is the count of all +numbers less than or equal to $num1[i]. + +Example 1 + + Input: @num1 = (6, 5, 4, 8) + Output: (2, 1, 0, 3) + + index 0: numbers <= 6 are 5, 4 => 2 + index 1: numbers <= 5 are 4 => 1 + index 2: numbers <= 4, none => 0 + index 3: numbers <= 8 are 6, 5, 4 => 3 + +Example 2 + + Input: @num1 = (7, 7, 7, 7) + Output: (3, 3, 3, 3) + +Example 3 + + Input: @num1 = (5, 4, 3, 2, 1) + Output: (4, 3, 2, 1, 0) + +Example 4 + + Input: @num1 = (-1, 0, 3, -2, 1) + Output: (1, 2, 4, 0, 3) + +Example 5 + + Input: @num1 = (0, 1, 1, 2, 0) + Output: (1, 3, 3, 4, 1) + +=cut +################################################################################ + +#--------------------------------------# +# Copyright © 2025 PerlMonk Athanasius # +#--------------------------------------# + +#=============================================================================== +=comment + +Assumptions +----------- +1. The input numbers are integers. +2. The Task should read: + + Write a script to return an array, @num2, where $num2[i] is the count of + all *other* numbers less than or equal to $num1[i]. + +Interface +--------- +1. If no command-line arguments are given, the test suite is run. Otherwise: +2. A non-empty list of integers is entered on the command-line. + +=cut +#=============================================================================== + +use v5.38.2; # Enables strictures +use warnings; +use Const::Fast; +use Regexp::Common qw( number ); +use Test::More; + +const my $USAGE => <<END; +Usage: + perl $0 [<num1> ...] + perl $0 + + [<num1> ...] A non-empty list of integers +END +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + $| = 1; + print "\nChallenge 337, Task #1: Smaller Than Current (Perl)\n\n"; +} + +#=============================================================================== +MAIN: +#=============================================================================== +{ + if (scalar @ARGV == 0) + { + run_tests(); + } + else + { + my @num1 = @ARGV; + + for (@num1) + { + / ^ $RE{num}{int} $ /x or error( qq["$_" is not a valid integer] ); + } + + printf "Input: \@num1 = (%s)\n", join ', ', @num1; + + my $num2 = smaller_than_current( \@num1 ); + + printf "Output: (%s)\n", join ', ', @$num2; + } +} + +#------------------------------------------------------------------------------- +sub smaller_than_current +#------------------------------------------------------------------------------- +{ + my ($num1) = @_; + my %freq; + ++$freq{$_} for @$num1; + + my @keys = sort { $a <=> $b } keys %freq; + my $sum = 0; + my %cum_freq; + + for my $key (@keys) + { + $sum += $freq{$key}; + $cum_freq{$key} = $sum; + } + + my @num2; + + for my $num (@$num1) + { + push @num2, $cum_freq{$num} - 1; + } + + return \@num2; +} + +#------------------------------------------------------------------------------- +sub run_tests +#------------------------------------------------------------------------------- +{ + print "Running the test suite\n"; + + while (my $line = <DATA>) + { + chomp $line; + + my ($test_name, $num1_str, $expd_str) = split / \| /x, $line; + + for ($test_name, $num1_str, $expd_str) + { + s/ ^ \s+ //x; + s/ \s+ $ //x; + } + + my @num1 = split / \s+ /x, $num1_str; + my $num2 = smaller_than_current( \@num1 ); + my @expd = split / \s+ /x, $expd_str; + + is_deeply $num2, \@expd, $test_name; + } + + done_testing; +} + +#------------------------------------------------------------------------------- +sub error +#------------------------------------------------------------------------------- +{ + my ($message) = @_; + + die "ERROR: $message\n$USAGE"; +} + +################################################################################ + +__DATA__ +Example 1| 6 5 4 8 |2 1 0 3 +Example 2| 7 7 7 7 |3 3 3 3 +Example 3| 5 4 3 2 1|4 3 2 1 0 +Example 4|-1 0 3 -2 1|1 2 4 0 3 +Example 5| 0 1 1 2 0|1 3 3 4 1 diff --git a/challenge-337/athanasius/perl/ch-2.pl b/challenge-337/athanasius/perl/ch-2.pl new file mode 100644 index 0000000000..e9345cf2e0 --- /dev/null +++ b/challenge-337/athanasius/perl/ch-2.pl @@ -0,0 +1,417 @@ +#!perl + +################################################################################ +=comment + +Perl Weekly Challenge 337 +========================= + +TASK #2 +------- +*Odd Matrix* + +Submitted by: Mohammad Sajid Anwar + +You are given row and col, also a list of positions in the matrix. + +Write a script to perform action on each location (0-indexed) as provided in the +list and find out the total odd valued cells. + +For each location (r, c), do both of the following: + + a) Increment by 1 all the cells on row r. + b) Increment by 1 all the cells on column c. + +Example 1 + + Input: $row = 2, $col = 3, @locations = ([0,1],[1,1]) + Output: 6 + + Initial: + [ 0 0 0 ] + [ 0 0 0 ] + + Apply [0,1]: + Increment row 0: + Before After + [ 0 0 0 ] [ 1 1 1 ] + [ 0 0 0 ] [ 0 0 0 ] + Increment col 1: + Before After + [ 1 1 1 ] [ 1 2 1 ] + [ 0 0 0 ] [ 0 1 0 ] + + Apply [1,1]: + Increment row 1: + Before After + [ 1 2 1 ] [ 1 2 1 ] + [ 0 1 0 ] [ 1 2 1 ] + Increment col 1: + Before After + [ 1 2 1 ] [ 1 3 1 ] + [ 1 2 1 ] [ 1 3 1 ] + + Final: + [ 1 3 1 ] + [ 1 3 1 ] + +Example 2 + + Input: $row = 2, $col = 2, @locations = ([1,1],[0,0]) + Output: 0 + + Initial: + [ 0 0 ] + [ 0 0 ] + + Apply [1,1]: + Increment row 1: + Before After + [ 0 0 ] [ 0 0 ] + [ 0 0 ] [ 1 1 ] + Increment col 1: + Before After + [ 0 0 ] [ 0 1 ] + [ 1 1 ] [ 1 2 ] + + Apply [0,0]: + Increment row 0: + Before After + [ 0 1 ] [ 1 2 ] + [ 1 2 ] [ 1 2 ] + Increment col 0: + Before After + [ 1 2 ] [ 2 2 ] + [ 1 2 ] [ 2 2 ] + + Final: + [ 2 2 ] + [ 2 2 ] + +Example 3 + + Input: $row = 3, $col = 3, @locations = ([0,0],[1,2],[2,1]) + Output: 0 + + Initial: + [ 0 0 0 ] + [ 0 0 0 ] + [ 0 0 0 ] + + Apply [0,0]: + Increment row 0: + Before After + [ 0 0 0 ] [ 1 1 1 ] + [ 0 0 0 ] [ 0 0 0 ] + [ 0 0 0 ] [ 0 0 0 ] + Increment col 0: + Before After + [ 1 1 1 ] [ 2 1 1 ] + [ 0 0 0 ] [ 1 0 0 ] + [ 0 0 0 ] [ 1 0 0 ] + + Apply [1,2]: + Increment row 1: + Before After + [ 2 1 1 ] [ 2 1 1 ] + [ 1 0 0 ] [ 2 1 1 ] + [ 1 0 0 ] [ 1 0 0 ] + Increment col 2: + Before After + [ 2 1 1 ] [ 2 1 2 ] + [ 2 1 1 ] [ 2 1 2 ] + [ 1 0 0 ] [ 1 0 1 ] + + Apply [2,1]: + Increment row 2: + Before After + [ 2 1 2 ] [ 2 1 2 ] + [ 2 1 2 ] [ 2 1 2 ] + [ 1 0 1 ] [ 2 1 2 ] + Increment col 1: + Before After + [ 2 1 2 ] [ 2 2 2 ] + [ 2 1 2 ] [ 2 2 2 ] + [ 2 1 2 ] [ 2 2 2 ] + + Final: + [ 2 2 2 ] + [ 2 2 2 ] + [ 2 2 2 ] + +Example 4 + + Input: $row = 1, $col = 5, @locations = ([0,2],[0,4]) + Output: 2 + + Initial: + [ 0 0 0 0 0 ] + + Apply [0,2]: + Increment row 0: + Before After + [ 0 0 0 0 0 ] [ 1 1 1 1 1 ] + Increment col 2: + Before After + [ 1 1 1 1 1 ] [ 1 1 2 1 1 ] + + Apply [0,4]: + Increment row 0: + Before After + [ 1 1 2 1 1 ] [ 2 2 3 2 2 ] + Increment col 4: + Before After + [ 2 2 3 2 2 ] [ 2 2 3 2 3 ] + + Final: + [ 2 2 3 2 3 ] + +Example 5 + + Input: $row = 4, $col = 2, @locations = ([1,0],[3,1],[2,0],[0,1]) + Output: 8 + +Initial: + [ 0 0 ] + [ 0 0 ] + [ 0 0 ] + [ 0 0 ] + + Apply [1,0]: + Increment row 1: + Before After + [ 0 0 ] [ 0 0 ] + [ 0 0 ] [ 1 1 ] + [ 0 0 ] [ 0 0 ] + [ 0 0 ] [ 0 0 ] + Increment col 0: + Before After + [ 0 0 ] [ 1 0 ] + [ 1 1 ] [ 2 1 ] + [ 0 0 ] [ 1 0 ] + [ 0 0 ] [ 1 0 ] + + Apply [3,1]: + Increment row 3: + Before After + [ 1 0 ] [ 1 0 ] + [ 2 1 ] [ 2 1 ] + [ 1 0 ] [ 1 0 ] + [ 1 0 ] [ 2 1 ] + Increment col 1: + Before After + [ 1 0 ] [ 1 1 ] + [ 2 1 ] [ 2 2 ] + [ 1 0 ] [ 1 1 ] + [ 2 1 ] [ 2 2 ] + + Apply [2,0]: + Increment row 2: + Before After + [ 1 1 ] [ 1 1 ] + [ 2 2 ] [ 2 2 ] + [ 1 1 ] [ 2 2 ] + [ 2 2 ] [ 2 2 ] + Increment col 0: + Before After + [ 1 1 ] [ 2 1 ] + [ 2 2 ] [ 3 2 ] + [ 2 2 ] [ 3 2 ] + [ 2 2 ] [ 3 2 ] + + Apply [0,1]: + Increment row 0: + Before After + [ 2 1 ] [ 3 2 ] + [ 3 2 ] [ 3 2 ] + [ 3 2 ] [ 3 2 ] + [ 3 2 ] [ 3 2 ] + Increment col 1: + Before After + [ 3 2 ] [ 3 3 ] + [ 3 2 ] [ 3 3 ] + [ 3 2 ] [ 3 3 ] + [ 3 2 ] [ 3 3 ] + + Final: + [ 3 3 ] + [ 3 3 ] + [ 3 3 ] + [ 3 3 ] + +=cut +################################################################################ + +#--------------------------------------# +# Copyright © 2025 PerlMonk Athanasius # +#--------------------------------------# + +#=============================================================================== +=comment + +Interface +--------- +1. If no command-line arguments are given, the test suite is run. Otherwise: +2. Matrix dimensions (rows and columns) are entered on the command-line, follow- + ed by a list of coordinates describing positions within the matrix. The co- + ordinates are 0-indexed (row, column) integer pairs. + +=cut +#=============================================================================== + +use v5.38.2; # Enables strictures +use warnings; +use Const::Fast; +use List::MoreUtils qw( natatime ); +use Regexp::Common qw( number ); +use Test::More; + +const my $USAGE => <<END; +Usage: + perl $0 <row> <col> [<coords> ...] + perl $0 + + <row> Number of matrix rows + <col> Number of matrix columns + [<coords> ...] A list of matrix coordinate pairs +END + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + $| = 1; + print "\nChallenge 337, Task #2: Odd Matrix (Perl)\n\n"; +} + +#=============================================================================== +MAIN: +#=============================================================================== +{ + my $argc = scalar @ARGV; + + if ($argc == 0) + { + run_tests(); + } + elsif ($argc == 1) + { + error( 'Expected 0 or 2+ command-line arguments, found 1' ); + } + else + { + my ($row, $col, $positions) = parse_input( @ARGV ); + + printf "Input: \$row = $row, \$col = $col, \@locations = (%s)\n", + join ',', map { '[' . join( ',', @$_ ) . ']' } @$positions; + + my $odd = odd_cells( $row, $col, $positions ); + + print "Output: $odd\n"; + } +} + +#------------------------------------------------------------------------------- +sub odd_cells +#------------------------------------------------------------------------------- +{ + my ($row, $col, $positions) = @_; + my @matrix; + push @matrix, [(0) x $col] for 1 .. $row; + + for my $coord (@$positions) + { + ++$matrix[ $coord->[0] ][$_] for 0 .. $col - 1; + ++$matrix[$_][ $coord->[1] ] for 0 .. $row - 1; + } + + my $odd = 0; + + for my $i (0 .. $row - 1) + { + for my $j (0 .. $col - 1) + { + ++$odd unless $matrix[$i][$j] % 2 == 0; + } + } + + return $odd; +} + +#------------------------------------------------------------------------------- +sub parse_input +#------------------------------------------------------------------------------- +{ + my ($row, $col, @coords) = @_; + + for ($row, $col, @coords) + { + / ^ $RE{num}{int} $ /x or error( qq["$_" is not a valid integer] ); + } + + $row > 0 or error( 'Invalid row value' ); + $col > 0 or error( 'Invalid column value' ); + scalar @coords % 2 == 0 or error( 'Odd number of coordinates' ); + + my @positions; + my $it = natatime 2, @coords; + + while (my @c = $it->()) + { + 0 <= $c[0] <= $row or error( 'Invalid row coordinate ' . $c[0] ); + 0 <= $c[1] <= $col or error( 'Invalid column coordinate ' . $c[1] ); + + push @positions, [ @c ]; + } + + return ($row, $col, \@positions); +} + +#------------------------------------------------------------------------------- +sub run_tests +#------------------------------------------------------------------------------- +{ + print "Running the test suite\n"; + + while (my $line = <DATA>) + { + chomp $line; + + my ($test_name, $row, $col, $positions_str, $expected) = + split / \| /x, $line; + + for ($test_name, $row, $col, $positions_str, $expected) + { + s/ ^ \s+ //x; + s/ \s+ $ //x; + } + + my @coordinates = split / \s+ | , /x, $positions_str; + my $positions; + ($row, $col, $positions) = parse_input( $row, $col, @coordinates ); + my $odd = odd_cells( $row, $col, $positions ); + + is $odd, $expected, $test_name; + } + + done_testing; +} + +#------------------------------------------------------------------------------- +sub error +#------------------------------------------------------------------------------- +{ + my ($message) = @_; + + die "ERROR: $message\n$USAGE"; +} + +################################################################################ + +__DATA__ +Example 1|2|3|0,1 1,1 |6 +Example 2|2|2|1,1 0,0 |0 +Example 3|3|3|0,0 1,2 2,1 |0 +Example 4|1|5|0,2 0,4 |2 +Example 5|4|2|1,0 3,1 2,0 0,1|8 +Minimal |1|1| |0 diff --git a/challenge-337/athanasius/raku/ch-1.raku b/challenge-337/athanasius/raku/ch-1.raku new file mode 100644 index 0000000000..acf556d3f8 --- /dev/null +++ b/challenge-337/athanasius/raku/ch-1.raku @@ -0,0 +1,187 @@ +use v6d; + +################################################################################ +=begin comment + +Perl Weekly Challenge 337 +========================= + +TASK #1 +------- +*Smaller Than Current* + +Submitted by: Mohammad Sajid Anwar + +You are given an array of numbers, @num1. + +Write a script to return an array, @num2, where $num2[i] is the count of all +numbers less than or equal to $num1[i]. + +Example 1 + + Input: @num1 = (6, 5, 4, 8) + Output: (2, 1, 0, 3) + + index 0: numbers <= 6 are 5, 4 => 2 + index 1: numbers <= 5 are 4 => 1 + index 2: numbers <= 4, none => 0 + index 3: numbers <= 8 are 6, 5, 4 => 3 + +Example 2 + + Input: @num1 = (7, 7, 7, 7) + Output: (3, 3, 3, 3) + +Example 3 + + Input: @num1 = (5, 4, 3, 2, 1) + Output: (4, 3, 2, 1, 0) + +Example 4 + + Input: @num1 = (-1, 0, 3, -2, 1) + Output: (1, 2, 4, 0, 3) + +Example 5 + + Input: @num1 = (0, 1, 1, 2, 0) + Output: (1, 3, 3, 4, 1) + +=end comment +################################################################################ + +#--------------------------------------# +# Copyright © 2025 PerlMonk Athanasius # +#--------------------------------------# + +#=============================================================================== +=begin comment + +Assumptions +----------- +1. The input numbers are integers. +2. The Task should read: + + Write a script to return an array, @num2, where $num2[i] is the count of + all *other* numbers less than or equal to $num1[i]. + +Interface +--------- +1. If no command-line arguments are given, the test suite is run. Otherwise: +2. A non-empty list of integers is entered on the command-line. +3. If the first integer is negative, it must be preceded by "--" to indicate + that it is not a command-line flag. + +=end comment +#=============================================================================== + +use Test; + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + "\nChallenge 337, Task #1: Smaller Than Current (Raku)\n".put; +} + +#=============================================================================== +multi sub MAIN +( + #| A non-empty list of integers + + *@num1 where { .elems > 0 && .all ~~ Int:D } +) +#=============================================================================== +{ + "Input: \@num1 = (%s)\n".printf: @num1.join: ', '; + + my UInt @num2 = smaller-than-current( @num1 ); + + "Output: (%s)\n"\ .printf: @num2.join: ', '; +} + +#=============================================================================== +multi sub MAIN() # No input: run the test suite +#=============================================================================== +{ + run-tests(); +} + +#------------------------------------------------------------------------------- +sub smaller-than-current( List:D[Int:D] $num1 --> List:D[UInt:D] ) +#------------------------------------------------------------------------------- +{ + my UInt %freq{Int}; + ++%freq{$_} for @$num1; + + my Int @keys = %freq.keys.sort; + my UInt $sum = 0; + my UInt %cum-freq{Int}; + + for @keys -> Int $key + { + $sum += %freq{$key}; + %cum-freq{$key} = $sum; + } + + my UInt @num2; + + for @$num1 -> Int $num + { + @num2.push: %cum-freq{$num} - 1; + } + + return @num2; +} + +#------------------------------------------------------------------------------- +sub run-tests() +#------------------------------------------------------------------------------- +{ + 'Running the test suite'.put; + + for test-data.lines -> Str $line + { + my Str ($test-name, $num1-str, $expd-str) = $line.split: / \| /; + + for $test-name, $num1-str, $expd-str + { + s/ ^ \s+ //; + s/ \s+ $ //; + } + + my Int @num1 = $num1-str.split( / \s+ /, :skip-empty ).map: { .Int }; + my UInt @num2 = smaller-than-current( @num1 ); + my UInt @expd = $expd-str.split( / \s+ /, :skip-empty ).map: { .Int }; + + is-deeply @num2, @expd, $test-name; + } + + done-testing; +} + +#------------------------------------------------------------------------------- +sub USAGE() +#------------------------------------------------------------------------------- +{ + my Str $usage = $*USAGE; + + $usage ~~ s:g/ ($*PROGRAM-NAME) /raku $0/; + + $usage.put; +} + +#------------------------------------------------------------------------------- +sub test-data( --> Str:D ) +#------------------------------------------------------------------------------- +{ + return q:to/END/; + Example 1| 6 5 4 8 |2 1 0 3 + Example 2| 7 7 7 7 |3 3 3 3 + Example 3| 5 4 3 2 1|4 3 2 1 0 + Example 4|-1 0 3 -2 1|1 2 4 0 3 + Example 5| 0 1 1 2 0|1 3 3 4 1 + END +} + +################################################################################ diff --git a/challenge-337/athanasius/raku/ch-2.raku b/challenge-337/athanasius/raku/ch-2.raku new file mode 100644 index 0000000000..f3b1cd77a9 --- /dev/null +++ b/challenge-337/athanasius/raku/ch-2.raku @@ -0,0 +1,405 @@ +use v6d; + +################################################################################ +=begin comment + +Perl Weekly Challenge 337 +========================= + +TASK #2 +------- +*Odd Matrix* + +Submitted by: Mohammad Sajid Anwar + +You are given row and col, also a list of positions in the matrix. + +Write a script to perform action on each location (0-indexed) as provided in the +list and find out the total odd valued cells. + +For each location (r, c), do both of the following: + + a) Increment by 1 all the cells on row r. + b) Increment by 1 all the cells on column c. + +Example 1 + + Input: $row = 2, $col = 3, @locations = ([0,1],[1,1]) + Output: 6 + + Initial: + [ 0 0 0 ] + [ 0 0 0 ] + + Apply [0,1]: + Increment row 0: + Before After + [ 0 0 0 ] [ 1 1 1 ] + [ 0 0 0 ] [ 0 0 0 ] + Increment col 1: + Before After + [ 1 1 1 ] [ 1 2 1 ] + [ 0 0 0 ] [ 0 1 0 ] + + Apply [1,1]: + Increment row 1: + Before After + [ 1 2 1 ] [ 1 2 1 ] + [ 0 1 0 ] [ 1 2 1 ] + Increment col 1: + Before After + [ 1 2 1 ] [ 1 3 1 ] + [ 1 2 1 ] [ 1 3 1 ] + + Final: + [ 1 3 1 ] + [ 1 3 1 ] + +Example 2 + + Input: $row = 2, $col = 2, @locations = ([1,1],[0,0]) + Output: 0 + + Initial: + [ 0 0 ] + [ 0 0 ] + + Apply [1,1]: + Increment row 1: + Before After + [ 0 0 ] [ 0 0 ] + [ 0 0 ] [ 1 1 ] + Increment col 1: + Before After + [ 0 0 ] [ 0 1 ] + [ 1 1 ] [ 1 2 ] + + Apply [0,0]: + Increment row 0: + Before After + [ 0 1 ] [ 1 2 ] + [ 1 2 ] [ 1 2 ] + Increment col 0: + Before After + [ 1 2 ] [ 2 2 ] + [ 1 2 ] [ 2 2 ] + + Final: + [ 2 2 ] + [ 2 2 ] + +Example 3 + + Input: $row = 3, $col = 3, @locations = ([0,0],[1,2],[2,1]) + Output: 0 + + Initial: + [ 0 0 0 ] + [ 0 0 0 ] + [ 0 0 0 ] + + Apply [0,0]: + Increment row 0: + Before After + [ 0 0 0 ] [ 1 1 1 ] + [ 0 0 0 ] [ 0 0 0 ] + [ 0 0 0 ] [ 0 0 0 ] + Increment col 0: + Before After + [ 1 1 1 ] [ 2 1 1 ] + [ 0 0 0 ] [ 1 0 0 ] + [ 0 0 0 ] [ 1 0 0 ] + + Apply [1,2]: + Increment row 1: + Before After + [ 2 1 1 ] [ 2 1 1 ] + [ 1 0 0 ] [ 2 1 1 ] + [ 1 0 0 ] [ 1 0 0 ] + Increment col 2: + Before After + [ 2 1 1 ] [ 2 1 2 ] + [ 2 1 1 ] [ 2 1 2 ] + [ 1 0 0 ] [ 1 0 1 ] + + Apply [2,1]: + Increment row 2: + Before After + [ 2 1 2 ] [ 2 1 2 ] + [ 2 1 2 ] [ 2 1 2 ] + [ 1 0 1 ] [ 2 1 2 ] + Increment col 1: + Before After + [ 2 1 2 ] [ 2 2 2 ] + [ 2 1 2 ] [ 2 2 2 ] + [ 2 1 2 ] [ 2 2 2 ] + + Final: + [ 2 2 2 ] + [ 2 2 2 ] + [ 2 2 2 ] + +Example 4 + + Input: $row = 1, $col = 5, @locations = ([0,2],[0,4]) + Output: 2 + + Initial: + [ 0 0 0 0 0 ] + + Apply [0,2]: + Increment row 0: + Before After + [ 0 0 0 0 0 ] [ 1 1 1 1 1 ] + Increment col 2: + Before After + [ 1 1 1 1 1 ] [ 1 1 2 1 1 ] + + Apply [0,4]: + Increment row 0: + Before After + [ 1 1 2 1 1 ] [ 2 2 3 2 2 ] + Increment col 4: + Before After + [ 2 2 3 2 2 ] [ 2 2 3 2 3 ] + + Final: + [ 2 2 3 2 3 ] + +Example 5 + + Input: $row = 4, $col = 2, @locations = ([1,0],[3,1],[2,0],[0,1]) + Output: 8 + +Initial: + [ 0 0 ] + [ 0 0 ] + [ 0 0 ] + [ 0 0 ] + + Apply [1,0]: + Increment row 1: + Before After + [ 0 0 ] [ 0 0 ] + [ 0 0 ] [ 1 1 ] + [ 0 0 ] [ 0 0 ] + [ 0 0 ] [ 0 0 ] + Increment col 0: + Before After + [ 0 0 ] [ 1 0 ] + [ 1 1 ] [ 2 1 ] + [ 0 0 ] [ 1 0 ] + [ 0 0 ] [ 1 0 ] + + Apply [3,1]: + Increment row 3: + Before After + [ 1 0 ] [ 1 0 ] + [ 2 1 ] [ 2 1 ] + [ 1 0 ] [ 1 0 ] + [ 1 0 ] [ 2 1 ] + Increment col 1: + Before After + [ 1 0 ] [ 1 1 ] + [ 2 1 ] [ 2 2 ] + [ 1 0 ] [ 1 1 ] + [ 2 1 ] [ 2 2 ] + + Apply [2,0]: + Increment row 2: + Before After + [ 1 1 ] [ 1 1 ] + [ 2 2 ] [ 2 2 ] + [ 1 1 ] [ 2 2 ] + [ 2 2 ] [ 2 2 ] + Increment col 0: + Before After + [ 1 1 ] [ 2 1 ] + [ 2 2 ] [ 3 2 ] + [ 2 2 ] [ 3 2 ] + [ 2 2 ] [ 3 2 ] + + Apply [0,1]: + Increment row 0: + Before After + [ 2 1 ] [ 3 2 ] + [ 3 2 ] [ 3 2 ] + [ 3 2 ] [ 3 2 ] + [ 3 2 ] [ 3 2 ] + Increment col 1: + Before After + [ 3 2 ] [ 3 3 ] + [ 3 2 ] [ 3 3 ] + [ 3 2 ] [ 3 3 ] + [ 3 2 ] [ 3 3 ] + + Final: + [ 3 3 ] + [ 3 3 ] + [ 3 3 ] + [ 3 3 ] + +=end comment +################################################################################ + +#--------------------------------------# +# Copyright © 2025 PerlMonk Athanasius # +#--------------------------------------# + +#=============================================================================== +=begin comment + +Interface +--------- +1. If no command-line arguments are given, the test suite is run. Otherwise: +2. Matrix dimensions (rows and columns) are entered on the command-line, follow- + ed by a list of coordinates describing positions within the matrix. The co- + ordinates are 0-indexed (row, column) integer pairs. + +=end comment +#=============================================================================== + +use Test; + +subset Coord of List where (UInt, UInt); +subset Pos of Int where * > 0; + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + "\nChallenge 337, Task #2: Odd Matrix (Raku)\n".put; +} + +#=============================================================================== +multi sub MAIN +( + Pos:D $row, #= Number of matrix rows + Pos:D $col, #= Number of matrix columns + + #| A list of matrix coordinate pairs + + *@coords where { .elems %% 2 && .all ~~ UInt:D } +) +#=============================================================================== +{ + "Input: \$row = $row, \$col = $col, \@locations = (%s)\n".printf: + @coords.rotor( 2 ).map( { '[' ~ .join( ',' ) ~ ']' } ).join: ','; + + my Coord @positions; + + for @coords.rotor( 2 ) -> Coord $coord + { + my UInt ($r, $c) = $coord; + + $row >= $r or error( qq[Row coordinate "$r" too large] ); + $col >= $c or error( qq[Col coordinate "$c" too large] ); + + @positions.push: [$r, $c]; + } + + my UInt $odd = odd-cells( $row, $col, @positions ); + + "Output: $odd".put; +} + +#=============================================================================== +multi sub MAIN() # No input: run the test suite +#=============================================================================== +{ + run-tests(); +} + +#------------------------------------------------------------------------------- +sub odd-cells( UInt:D $row, UInt:D $col, List:D[Coord:D] @positions --> UInt:D ) +#------------------------------------------------------------------------------- +{ + my Array[UInt] @matrix = Array[UInt].new( 0 xx $col ) xx $row; + + for @positions -> Coord $coord + { + ++@matrix[ $coord[ 0 ]; $_ ] for 0 .. $col - 1; + ++@matrix[ $_; $coord[ 1 ] ] for 0 .. $row - 1; + } + + my UInt $odd = 0; + + for 0 .. $row - 1 -> UInt $i + { + for 0 .. $col - 1 -> UInt $j + { + ++$odd unless @matrix[$i; $j] %% 2; + } + } + + return $odd; +} + +#------------------------------------------------------------------------------- +sub run-tests() +#------------------------------------------------------------------------------- +{ + 'Running the test suite'.put; + + for test-data.lines -> Str $line + { + my Str ($test-name, $row, $col, $positions-str, $expected) = + $line.split: / \| /; + + for $test-name, $row, $col, $positions-str, $expected + { + s/ ^ \s+ //; + s/ \s+ $ //; + } + + my Str @pos-strs = $positions-str.split: / \s+ /, :skip-empty; + my Coord @positions = @pos-strs.map: + { + Array[UInt].new: + .split( / \, / ).map: { .Int } + }; + my UInt $odd = odd-cells( $row.Int, $col.Int, @positions ); + + is $odd, $expected.Int, $test-name; + } + + done-testing; +} + +#------------------------------------------------------------------------------- +sub error( Str:D $message ) +#------------------------------------------------------------------------------- +{ + "ERROR: $message".put; + + USAGE(); + + exit 0; +} + +#------------------------------------------------------------------------------- +sub USAGE() +#------------------------------------------------------------------------------- +{ + my Str $usage = $*USAGE; + + $usage ~~ s:g/ ($*PROGRAM-NAME) /raku $0/; + + $usage.put; +} + +#------------------------------------------------------------------------------- +sub test-data( --> Str:D ) +#------------------------------------------------------------------------------- +{ + return q:to/END/; + Example 1|2|3|0,1 1,1 |6 + Example 2|2|2|1,1 0,0 |0 + Example 3|3|3|0,0 1,2 2,1 |0 + Example 4|1|5|0,2 0,4 |2 + Example 5|4|2|1,0 3,1 2,0 0,1|8 + Minimal |1|1| |0 + END +} + +################################### |
