aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPerlMonk-Athanasius <PerlMonk.Athanasius@gmail.com>2023-05-22 02:34:49 +1000
committerPerlMonk-Athanasius <PerlMonk.Athanasius@gmail.com>2023-05-22 02:34:49 +1000
commit697ccec10af0587d98a25523f958504027135ead (patch)
tree056535ab5d7e77188aa3282229f8bc07eb3fdff5
parentc4b5be7c34b100fcda4b1e2481df1e497a7d2661 (diff)
downloadperlweeklychallenge-club-697ccec10af0587d98a25523f958504027135ead.tar.gz
perlweeklychallenge-club-697ccec10af0587d98a25523f958504027135ead.tar.bz2
perlweeklychallenge-club-697ccec10af0587d98a25523f958504027135ead.zip
Perl & Raku solutions to Task 1 for Week 217
-rw-r--r--challenge-217/athanasius/perl/ch-1.pl261
-rw-r--r--challenge-217/athanasius/raku/ch-1.raku255
2 files changed, 516 insertions, 0 deletions
diff --git a/challenge-217/athanasius/perl/ch-1.pl b/challenge-217/athanasius/perl/ch-1.pl
new file mode 100644
index 0000000000..28ba086c1b
--- /dev/null
+++ b/challenge-217/athanasius/perl/ch-1.pl
@@ -0,0 +1,261 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 217
+=========================
+
+TASK #1
+-------
+*Sorted Matrix*
+
+Submitted by: Mohammad S Anwar
+
+You are given a n x n matrix where n >= 2.
+
+Write a script to find 3rd smallest element in the sorted matrix.
+
+Example 1
+
+ Input: @matrix = ([3, 1, 2], [5, 2, 4], [0, 1, 3])
+ Output: 1
+
+ The sorted list of the given matrix: 0, 1, 1, 2, 2, 3, 3, 4, 5.
+ The 3rd smallest of the sorted list is 1.
+
+Example 2
+
+ Input: @matrix = ([2, 1], [4, 5])
+ Output: 4
+
+ The sorted list of the given matrix: 1, 2, 4, 5.
+ The 3rd smallest of the sorted list is 4.
+
+Example 3
+
+ Input: @matrix = ([1, 0, 3], [0, 0, 0], [1, 2, 1])
+ Output: 0
+
+ The sorted list of the given matrix: 0, 0, 0, 0, 1, 1, 1, 2, 3.
+ The 3rd smallest of the sorted list is 0.
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2023 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=comment
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. If $VERBOSE is set to a true value (the default), the output is followed by
+ an explanation of the result.
+
+Assumption
+----------
+Matrix elements are integers.
+
+=cut
+#===============================================================================
+
+use strict;
+use warnings;
+use Const::Fast;
+use Regexp::Common qw( number );
+use Test::More;
+
+const my $VERBOSE => 1;
+const my $USAGE =>
+"Usage:
+ perl $0 <matrix>
+ perl $0
+
+ <matrix> String representation of an n x n integer matrix where n >= 2
+";
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 217, Task #1: Sorted Matrix (Perl)\n\n";
+}
+
+#===============================================================================
+MAIN:
+#===============================================================================
+{
+ my $args = scalar @ARGV;
+
+ if ($args == 0)
+ {
+ run_tests();
+ }
+ elsif ($args == 1)
+ {
+ my $matrix = parse_matrix_string( $ARGV[ 0 ] );
+
+ printf "Input: \@matrix = %s\n", format_matrix( $matrix );
+
+ my @elements;
+ my $third_smallest = find_third_smallest( $matrix, \@elements );
+
+ printf "Output: %d\n", $third_smallest;
+
+ if ($VERBOSE)
+ {
+ printf "\nThe sorted list of the given matrix: %s\n",
+ join ', ', @elements;
+
+ my $padding = length( $elements[ 0 ] ) +
+ length( $elements[ 1 ] ) + 4;
+
+ printf "The third-smallest element: %s%s\n",
+ ' ' x $padding, '^' x length $third_smallest;
+ }
+ }
+ else
+ {
+ error( "Expected 0 or 1 command-line arguments, found $args" );
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub find_third_smallest
+#-------------------------------------------------------------------------------
+{
+ my ($matrix, $elements_ref) = @_;
+ my @elements;
+
+ push @elements, @$_ for @$matrix;
+
+ @elements = sort { $a <=> $b } @elements;
+
+ scalar @elements >= 3 or error( 'Matrix too small' );
+
+ @$elements_ref = @elements if $elements_ref;
+
+ return $elements[ 2 ];
+}
+
+#-------------------------------------------------------------------------------
+sub parse_matrix_string
+#-------------------------------------------------------------------------------
+{
+ my ($matrix) = @_;
+
+ $matrix =~ / ^ \s* \( (.*?) \s* \) \s* $ /x
+ or error( 'Invalid input string' );
+
+ my $body = $1;
+ my @matrix;
+
+ while ($body =~ / \[ (.+?) \] /gx)
+ {
+ my $row = $1;
+ my @elems = split / , \s* /x, $row;
+
+ for my $elem (@elems)
+ {
+ $elem =~ s/ ^ \s+ //x;
+ $elem =~ s/ \s+ $ //x;
+ $elem =~ m/ ^ $RE{num}{int} $ /x
+ or error( qq["$elem" is not a valid integer] );
+ }
+
+ push @matrix, [ @elems ];
+
+ }
+
+ validate_matrix( \@matrix );
+
+ return \@matrix;
+}
+
+#-------------------------------------------------------------------------------
+sub validate_matrix
+#-------------------------------------------------------------------------------
+{
+ my ($matrix) = @_;
+
+ my $rows = scalar @$matrix;
+ my $n = scalar @{ $matrix->[ 0 ] };
+
+ $rows >= 2 or error( 'Too few rows in matrix' );
+ $rows == $n or error( 'Matrix is not square' );
+
+ for my $i (1 .. $#$matrix)
+ {
+ my $m = scalar @{ $matrix->[ $i ] };
+ my $j = $i + 1;
+
+ $m == $n or error( "In matrix row $j: expected $n elements, found $m" );
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub format_matrix
+#-------------------------------------------------------------------------------
+{
+ my ($matrix) = @_;
+ my $matrix_str = '(';
+ my @row_strs;
+
+ for my $elems (@$matrix)
+ {
+ push @row_strs, '[' . join( ', ', @$elems ) . ']';
+ }
+
+ $matrix_str .= join( ', ', @row_strs ) . ')';
+
+ return $matrix_str;
+}
+
+#-------------------------------------------------------------------------------
+sub run_tests
+#-------------------------------------------------------------------------------
+{
+ print "Running the test suite\n";
+
+ while (my $line = <DATA>)
+ {
+ chomp $line;
+
+ my ($test_name, $matrix_str, $expected) = split / \| /x, $line;
+
+ for ($test_name, $matrix_str, $expected) # Trim whitespace
+ {
+ s/ ^ \s+ //x;
+ s/ \s+ $ //x;
+ }
+
+ my @matrix = parse_matrix_string( $matrix_str );
+ my $third_smallest = find_third_smallest( @matrix );
+
+ is $third_smallest, $expected, $test_name;
+ }
+
+ done_testing;
+}
+
+#-------------------------------------------------------------------------------
+sub error
+#-------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+################################################################################
+
+__DATA__
+Example 1|([3, 1, 2], [5, 2, 4], [ 0, 1, 3])| 1
+Example 2|([2, 1], [4, 5]) | 4
+Example 3|([1, 0, 3], [0, 0, 0], [ 1, 2, 1])| 0
+Negatives|([0, -1, -2], [0, -1, -3], [-3, 1, 2])|-2
diff --git a/challenge-217/athanasius/raku/ch-1.raku b/challenge-217/athanasius/raku/ch-1.raku
new file mode 100644
index 0000000000..43e9d9e547
--- /dev/null
+++ b/challenge-217/athanasius/raku/ch-1.raku
@@ -0,0 +1,255 @@
+use v6d;
+
+################################################################################
+=begin comment
+
+Perl Weekly Challenge 217
+=========================
+
+TASK #1
+-------
+*Sorted Matrix*
+
+Submitted by: Mohammad S Anwar
+
+You are given a n x n matrix where n >= 2.
+
+Write a script to find 3rd smallest element in the sorted matrix.
+
+Example 1
+
+ Input: @matrix = ([3, 1, 2], [5, 2, 4], [0, 1, 3])
+ Output: 1
+
+ The sorted list of the given matrix: 0, 1, 1, 2, 2, 3, 3, 4, 5.
+ The 3rd smallest of the sorted list is 1.
+
+Example 2
+
+ Input: @matrix = ([2, 1], [4, 5])
+ Output: 4
+
+ The sorted list of the given matrix: 1, 2, 4, 5.
+ The 3rd smallest of the sorted list is 4.
+
+Example 3
+
+ Input: @matrix = ([1, 0, 3], [0, 0, 0], [1, 2, 1])
+ Output: 0
+
+ The sorted list of the given matrix: 0, 0, 0, 0, 1, 1, 1, 2, 3.
+ The 3rd smallest of the sorted list is 0.
+
+=end comment
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2023 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=begin comment
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. If VERBOSE is set to True (the default), the output is followed by an explan-
+ ation of the result
+
+Assumption
+----------
+Matrix elements are integers.
+
+=end comment
+#===============================================================================
+
+use Test;
+
+subset Result of List where (Int, Array[Int]);
+
+my Bool constant VERBOSE = True;
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ "\nChallenge 217, Task #1: Sorted Matrix (Raku)\n".put;
+}
+
+#===============================================================================
+multi sub MAIN
+(
+ #| String representation of an n x n integer matrix where n >= 2
+
+ Str:D $matrix
+)
+#===============================================================================
+{
+ my Array[Int] @matrix = parse-matrix-string( $matrix );
+
+ "Input: \@matrix = %s\n".printf: format-matrix( @matrix );
+
+ my Result $result = find-third-smallest( @matrix );
+
+ "Output: %d\n".printf: $result[ 0 ];
+
+ if VERBOSE
+ {
+ my Int @elements = $result[ 1 ];
+
+ "\nThe sorted list of the given matrix: %s\n".printf:
+ @elements.join: ', ';
+
+ my UInt $padding = @elements[ 0 ].chars + @elements[ 1 ].chars + 4;
+
+ "The third-smallest element: %s%s\n".printf:
+ ' ' x $padding, '^' x $result[ 0 ].chars;
+ }
+}
+
+#===============================================================================
+multi sub MAIN() # No input: run the test suite
+#===============================================================================
+{
+ run-tests();
+}
+
+#-------------------------------------------------------------------------------
+sub find-third-smallest( List:D[List:D[Int:D]] $matrix --> Result:D )
+#-------------------------------------------------------------------------------
+{
+ my Int @elements;
+
+ @elements.push: |$_ for @$matrix;
+
+ @elements.= sort;
+
+ @elements.elems >= 3 or error( 'Matrix too small' );
+
+ return @elements[ 2 ], @elements;
+}
+
+#===============================================================================
+grammar Matrix
+#===============================================================================
+{
+ token TOP { ^ \s* '(' \s* [ <row> <sep> ]+ <row> \s* ')' \s* $ }
+ token row { '[' \s* [ <elem> <sep> ]+ <elem> \s* ']' }
+ token elem { <[-+]>? <[0..9]>+ }
+ token sep { \, \s* }
+}
+
+#-------------------------------------------------------------------------------
+sub parse-matrix-string( Str:D $matrix --> List:D[List:D[Int:D]] )
+#-------------------------------------------------------------------------------
+{
+ my Matrix $parsed = Matrix.parse( $matrix )
+ or error( 'Invalid input string' );
+
+ my Array[Int] @matrix;
+ my Str @rows = $parsed< row >.map: { .Str };
+
+ for @rows -> Str $row
+ {
+ $row ~~ / ^ \[ \s* (.+?) \s* \] $ /;
+
+ @matrix.push: Array[Int].new: $0.Str.split( / \, \s* / ).map: { .Int };
+ }
+
+ validate-matrix( @matrix );
+
+ return @matrix;
+}
+
+#-------------------------------------------------------------------------------
+sub validate-matrix( List:D[List:D[Int:D]] $matrix )
+#-------------------------------------------------------------------------------
+{
+ my UInt $rows = $matrix.elems;
+ my UInt $n = $matrix[ 0 ].elems;
+
+ $rows >= 2 or error( 'Too few rows in matrix' );
+ $rows == $n or error( 'Matrix is not square' );
+
+ for 1 .. $matrix.end -> UInt $i
+ {
+ my UInt $m = $matrix[ $i ].elems;
+ my UInt $j = $i + 1;
+
+ $m == $n or error( "In matrix row $j: expected $n elements, found $m" );
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub format-matrix( List:D[List:D[Int:D]] $matrix --> Str:D )
+#-------------------------------------------------------------------------------
+{
+ my Str $matrix-str = '(';
+ my Str @row-strs;
+
+ for @$matrix -> Int @elems
+ {
+ @row-strs.push: '[' ~ @elems.join( ', ' ) ~ ']';
+ }
+
+ $matrix-str ~= @row-strs.join( ', ' ) ~ ')';
+
+ return $matrix-str;
+}
+
+#-------------------------------------------------------------------------------
+sub run-tests()
+#-------------------------------------------------------------------------------
+{
+ 'Running the test suite'.put;
+
+ for test-data.lines -> Str $line
+ {
+ my Str ($test-name, $matrix-str, $expected) = $line.split: / \| /;
+
+ s/ \s+ $ // for $test-name, $matrix-str; # Trim whitespace
+
+ my Array[Int] @matrix = parse-matrix-string( $matrix-str );
+ my Result $result = find-third-smallest( @matrix );
+
+ is $result[ 0 ], $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|([3, 1, 2], [5, 2, 4], [ 0, 1, 3])| 1
+ Example 2|([2, 1], [4, 5]) | 4
+ Example 3|([1, 0, 3], [0, 0, 0], [ 1, 2, 1])| 0
+ Negatives|([0, -1, -2], [0, -1, -3], [-3, 1, 2])|-2
+ END
+}
+
+################################################################################