aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2023-02-05 16:01:14 +0000
committerGitHub <noreply@github.com>2023-02-05 16:01:14 +0000
commit93d184d4a4830a4f040b46194021983295f14fa1 (patch)
tree2dc361388d7d0c756d4dcd1db79dc75edcde8ce0
parentf925f1996edfb29910515826fbb4c0afe5338dbe (diff)
parentbaa28f4354bf59cc0f70659803374c7be0557122 (diff)
downloadperlweeklychallenge-club-93d184d4a4830a4f040b46194021983295f14fa1.tar.gz
perlweeklychallenge-club-93d184d4a4830a4f040b46194021983295f14fa1.tar.bz2
perlweeklychallenge-club-93d184d4a4830a4f040b46194021983295f14fa1.zip
Merge pull request #7524 from PerlMonk-Athanasius/branch-for-challenge-202
Perl & Raku solutions to Tasks 1 & 2 for Week 202
-rw-r--r--challenge-202/athanasius/perl/ch-1.pl157
-rw-r--r--challenge-202/athanasius/perl/ch-2.pl210
-rw-r--r--challenge-202/athanasius/raku/ch-1.raku160
-rw-r--r--challenge-202/athanasius/raku/ch-2.raku206
4 files changed, 733 insertions, 0 deletions
diff --git a/challenge-202/athanasius/perl/ch-1.pl b/challenge-202/athanasius/perl/ch-1.pl
new file mode 100644
index 0000000000..2702ef99ce
--- /dev/null
+++ b/challenge-202/athanasius/perl/ch-1.pl
@@ -0,0 +1,157 @@
+#!perl
+
+###############################################################################
+=comment
+
+Perl Weekly Challenge 202
+=========================
+
+TASK #1
+-------
+*Consecutive Odds*
+
+Submitted by: Mohammad S Anwar
+
+You are given an array of integers.
+
+Write a script to print 1 if there are THREE consecutive odds in the given
+array otherwise print 0.
+
+Example 1
+
+ Input: @array = (1,5,3,6)
+ Output: 1
+
+Example 2
+
+ Input: @array = (2,6,3,5)
+ Output: 0
+
+Example 3
+
+ Input: @array = (1,2,3,4)
+ Output: 0
+
+Example 4
+
+ Input: @array = (2,3,5,7)
+ Output: 1
+
+=cut
+###############################################################################
+
+#--------------------------------------#
+# Copyright © 2023 PerlMonk Athanasius #
+#--------------------------------------#
+
+#==============================================================================
+=comment
+
+Interface
+---------
+If no command-line arguments are given, the test suite is run.
+
+Assumption
+----------
+Where the Task description says "if there are THREE consecutive odds in the
+given array", it means "if there are AT LEAST THREE consecutive odds in the
+given array".
+
+=cut
+#==============================================================================
+
+use strict;
+use warnings;
+use Const::Fast;
+use Regexp::Common qw( number );
+use Test::More;
+
+const my $USAGE =>
+"Usage:
+ perl $0 [<array> ...]
+ perl $0
+
+ [<array> ...] A list of 1 or more integers\n";
+
+#------------------------------------------------------------------------------
+BEGIN
+#------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 202, Task #1: Consecutive Odds (Perl)\n\n";
+}
+
+#==============================================================================
+MAIN:
+#==============================================================================
+{
+ if (scalar @ARGV == 0)
+ {
+ run_tests();
+ }
+ else
+ {
+ my @array = @ARGV;
+
+ / ^ $RE{num}{int} $ /x
+ or die qq[ERROR: "$_" is not a valid integer\n$USAGE]
+ for @array;
+
+ printf "Input: \@array = (%s)\n", join ',', @array;
+
+ printf "Output: %d\n", three_consecutive_odds( \@array );
+ }
+}
+
+#------------------------------------------------------------------------------
+sub three_consecutive_odds
+#------------------------------------------------------------------------------
+{
+ my ($array) = @_;
+ my $found = 0;
+ my $count = 0; # Count of consecutive odd numbers
+
+ for my $n (@$array)
+ {
+ if ($n % 2 == 0) # Even
+ {
+ $count = 0; # Reset the count
+ }
+ elsif (++$count == 3) # Odd and 3 consecutive odds found
+ {
+ $found = 1;
+ last;
+ }
+ }
+
+ return $found;
+}
+
+#------------------------------------------------------------------------------
+sub run_tests
+#------------------------------------------------------------------------------
+{
+ print "Running the test suite\n";
+
+ while (my $line = <DATA>)
+ {
+ chomp $line;
+
+ my ($test_name, $input, $expected) = split / \| /x, $line;
+
+ my @array = split / , \s* /x, $input;
+ my $got = three_consecutive_odds( \@array );
+
+ is $got, $expected, $test_name;
+ }
+
+ done_testing;
+}
+
+###############################################################################
+
+__DATA__
+Example 1|1,5,3,6|1
+Example 2|2,6,3,5|0
+Example 3|1,2,3,4|0
+Example 4|2,3,5,7|1
diff --git a/challenge-202/athanasius/perl/ch-2.pl b/challenge-202/athanasius/perl/ch-2.pl
new file mode 100644
index 0000000000..928bf6b6a4
--- /dev/null
+++ b/challenge-202/athanasius/perl/ch-2.pl
@@ -0,0 +1,210 @@
+#!perl
+
+###############################################################################
+=comment
+
+Perl Weekly Challenge 202
+=========================
+
+TASK #2
+-------
+*Widest Valley*
+
+Submitted by: E. Choroba
+
+Given a profile as a list of altitudes, return the leftmost *widest valley*. A
+valley is defined as a subarray of the profile consisting of two parts: the
+first part is non-increasing and the second part is non-decreasing. Either part
+can be empty.
+
+Example 1
+
+ Input: 1, 5, 5, 2, 8
+ Output: 5, 5, 2, 8
+
+Example 2
+
+ Input: 2, 6, 8, 5
+ Output: 2, 6, 8
+
+Example 3
+
+ Input: 9, 8, 13, 13, 2, 2, 15, 17
+ Output: 13, 13, 2, 2, 15, 17
+
+Example 4
+
+ Input: 2, 1, 2, 1, 3
+ Output: 2, 1, 2
+
+Example 5
+
+ Input: 1, 3, 3, 2, 1, 2, 3, 3, 2
+ Output: 3, 3, 2, 1, 2, 3, 3
+
+=cut
+###############################################################################
+
+#--------------------------------------#
+# Copyright © 2023 PerlMonk Athanasius #
+#--------------------------------------#
+
+#==============================================================================
+=comment
+
+Interface
+---------
+If no command-line arguments are given, the test suite is run.
+
+Assumption
+----------
+Altitudes are relative to sea level (and may therefore be negative), but are
+restricted to integer values as per the Examples.
+
+=cut
+#==============================================================================
+
+use strict;
+use warnings;
+use Const::Fast;
+use Regexp::Common qw( number );
+use Test::More;
+
+const my $USAGE =>
+"Usage:
+ perl $0 [<altitudes> ...]
+ perl $0
+
+ [<altitudes> ...] A non-empty list of integers\n";
+
+#------------------------------------------------------------------------------
+BEGIN
+#------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 202, Task #2: Widest Valley (Perl)\n\n";
+}
+
+#==============================================================================
+MAIN:
+#==============================================================================
+{
+ if (scalar @ARGV == 0)
+ {
+ run_tests();
+ }
+ else
+ {
+ my @altitudes = @ARGV;
+
+ for (@altitudes)
+ {
+ / ^ $RE{num}{int} $ /x
+ or die qq[ERROR: "$_" is not a valid integer\n$USAGE];
+ }
+
+ printf "Input: %s\n", join ', ', @altitudes;
+
+ my $valley = find_widest_valley( \@altitudes );
+
+ printf "Output: %s\n", join ', ', @$valley;
+ }
+}
+
+#------------------------------------------------------------------------------
+# Given a profile as a list of altitudes, return the leftmost *widest valley*.
+# A valley is defined as a subarray of the profile consisting of two parts: the
+# first part is non-increasing and the second part is non-decreasing. Either
+# part can be empty.
+#
+# Example 1 Input: 1, 5, 5, 2, 8
+# Output: 5, 5, 2, 8
+#
+# Example 2 Input: 2, 6, 8, 5
+# Output: 2, 6, 8
+#
+# Example 3 Input: 9, 8, 13, 13, 2, 2, 15, 17
+# Output: 13, 13, 2, 2, 15, 17
+#
+# Example 4 Input: 2, 1, 2, 1, 3
+# Output: 2, 1, 2
+#
+# Example 5 Input: 1, 3, 3, 2, 1, 2, 3, 3, 2
+# Output: 3, 3, 2, 1, 2, 3, 3
+#------------------------------------------------------------------------------
+sub find_widest_valley
+#------------------------------------------------------------------------------
+{
+ my ($altitudes) = @_;
+ my $in_left = 1;
+ my @valley = $altitudes->[ 0 ];
+ my @widest;
+
+ for (my $idx = 1; $idx <= $#$altitudes; ++$idx)
+ {
+ my $last = $valley[ -1 ];
+ my $next = $altitudes->[ $idx ];
+
+ if ($in_left) # In the left part of the valley
+ {
+ push @valley, $next;
+
+ $in_left = 0 if $next > $last; # Change direction: left to right
+ }
+ elsif ($next >= $last) # In the right part of the valley
+ {
+ push @valley, $next;
+ }
+ else # Change direction: right to left
+ {
+ # Backtrack to left-most non-ascending altitude
+
+ --$idx while $altitudes->[ $idx - 1 ] >= $altitudes->[ $idx ];
+
+ @widest = @valley if scalar @valley > scalar @widest;
+ @valley = $altitudes->[ $idx ];
+ $in_left = 1;
+ }
+ }
+
+ @widest = @valley if scalar @valley > scalar @widest;
+
+ return \@widest;
+}
+
+#------------------------------------------------------------------------------
+sub run_tests
+#------------------------------------------------------------------------------
+{
+ print "Running the test suite\n";
+
+ while (my $line = <DATA>)
+ {
+ chomp $line;
+
+ my ($test, $in, $out) = split / \| /x, $line;
+
+ $in =~ s/ (.+?) \s* $ /$1/x; # Trim trailing whitespace
+
+ my @altitudes = split /,/, $in;
+ my @expected = split /,/, $out;
+
+ is_deeply find_widest_valley( \@altitudes ), \@expected, $test;
+ }
+
+ done_testing;
+}
+
+###############################################################################
+
+__DATA__
+Example 1|1,5,5,2,8 |5,5,2,8
+Example 2|2,6,8,5 |2,6,8
+Example 3|9,8,13,13,2,2,15,17 |13,13,2,2,15,17
+Example 4|2,1,2,1,3 |2,1,2
+Example 5|1,3,3,2,1,2,3,3,2 |3,3,2,1,2,3,3
+First |5,4,3,2,4,5,4,3,1,4,5 |5,4,3,2,4,5
+Second |10,7,3,5,9,9,8,6,4,4,3,5,7,1|9,9,8,6,4,4,3,5,7
+Negatives|3,2,0,-1,-2,4,5,3,2 |3,2,0,-1,-2,4,5
+No left |1,2,3,4,5,3,2 |1,2,3,4,5
+No right |11,10,9,10,11,8,5,3,1,0,0 |11,8,5,3,1,0,0
diff --git a/challenge-202/athanasius/raku/ch-1.raku b/challenge-202/athanasius/raku/ch-1.raku
new file mode 100644
index 0000000000..52debc1018
--- /dev/null
+++ b/challenge-202/athanasius/raku/ch-1.raku
@@ -0,0 +1,160 @@
+use v6d;
+
+###############################################################################
+=begin comment
+
+Perl Weekly Challenge 202
+=========================
+
+TASK #1
+-------
+*Consecutive Odds*
+
+Submitted by: Mohammad S Anwar
+
+You are given an array of integers.
+
+Write a script to print 1 if there are THREE consecutive odds in the given
+array otherwise print 0.
+
+Example 1
+
+ Input: @array = (1,5,3,6)
+ Output: 1
+
+Example 2
+
+ Input: @array = (2,6,3,5)
+ Output: 0
+
+Example 3
+
+ Input: @array = (1,2,3,4)
+ Output: 0
+
+Example 4
+
+ Input: @array = (2,3,5,7)
+ Output: 1
+
+=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 the first argument is negative, it must be preceded by "--" to distin-
+ guish it from a command-line flag.
+
+Assumption
+----------
+Where the Task description says "if there are THREE consecutive odds in the
+given array", it means "if there are AT LEAST THREE consecutive odds in the
+given array".
+
+=end comment
+#==============================================================================
+
+use Test;
+
+#------------------------------------------------------------------------------
+BEGIN
+#------------------------------------------------------------------------------
+{
+ "\nChallenge 202, Task #1: Consecutive Odds (Raku)\n".put;
+}
+
+#==============================================================================
+multi sub MAIN
+(
+ #| A list of 1 or more integers
+
+ *@array where { .elems >= 1 && .all ~~ Int:D }
+)
+#==============================================================================
+{
+ "Input: \@array = (%s)\n".printf: @array.join: ',';
+
+ "Output: %d\n".printf: three-consecutive-odds( @array ) ?? 1 !! 0;
+}
+
+#==============================================================================
+multi sub MAIN() # No input: run the test suite
+#==============================================================================
+{
+ run-tests();
+}
+
+#------------------------------------------------------------------------------
+sub three-consecutive-odds( List:D[Int:D] $array --> Bool:D )
+#------------------------------------------------------------------------------
+{
+ my Bool $found = False;
+ my UInt $count = 0; # Count of consecutive odd numbers
+
+ for @$array -> Int $n
+ {
+ if $n %% 2 # Even
+ {
+ $count = 0; # Reset the count
+ }
+ elsif ++$count == 3 # Odd and 3 consecutive odds found
+ {
+ $found = True;
+ last;
+ }
+ }
+
+ return $found;
+}
+
+#------------------------------------------------------------------------------
+sub run-tests()
+#------------------------------------------------------------------------------
+{
+ 'Running the test suite'.put;
+
+ for test-data.lines -> Str $line
+ {
+ my Str ($test-name, $input, $expected) = $line.split: / \| /;
+
+ my Int @array = $input.split( / \, \s* / ).map: { .Int };
+ my UInt $got = three-consecutive-odds( @array ) ?? 1 !! 0;
+
+ is $got, $expected, $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|1,5,3,6|1
+ Example 2|2,6,3,5|0
+ Example 3|1,2,3,4|0
+ Example 4|2,3,5,7|1
+ END
+}
+
+###############################################################################
diff --git a/challenge-202/athanasius/raku/ch-2.raku b/challenge-202/athanasius/raku/ch-2.raku
new file mode 100644
index 0000000000..4c9647339f
--- /dev/null
+++ b/challenge-202/athanasius/raku/ch-2.raku
@@ -0,0 +1,206 @@
+use v6d;
+
+###############################################################################
+=begin comment
+
+Perl Weekly Challenge 202
+=========================
+
+TASK #2
+-------
+*Widest Valley*
+
+Submitted by: E. Choroba
+
+Given a profile as a list of altitudes, return the leftmost *widest valley*. A
+valley is defined as a subarray of the profile consisting of two parts: the
+first part is non-increasing and the second part is non-decreasing. Either part
+can be empty.
+
+Example 1
+
+ Input: 1, 5, 5, 2, 8
+ Output: 5, 5, 2, 8
+
+Example 2
+
+ Input: 2, 6, 8, 5
+ Output: 2, 6, 8
+
+Example 3
+
+ Input: 9, 8, 13, 13, 2, 2, 15, 17
+ Output: 13, 13, 2, 2, 15, 17
+
+Example 4
+
+ Input: 2, 1, 2, 1, 3
+ Output: 2, 1, 2
+
+Example 5
+
+ Input: 1, 3, 3, 2, 1, 2, 3, 3, 2
+ Output: 3, 3, 2, 1, 2, 3, 3
+
+=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 the first argument is negative, it must be preceded by "--" to distin-
+ guish it from a command-line flag.
+
+Assumption
+----------
+Altitudes are relative to sea level (and may therefore be negative), but are
+restricted to integer values as per the Examples.
+
+=end comment
+#==============================================================================
+
+use Test;
+
+#------------------------------------------------------------------------------
+BEGIN
+#------------------------------------------------------------------------------
+{
+ "\nChallenge 202, Task #2: Widest Valley (Raku)\n".put;
+}
+
+#==============================================================================
+multi sub MAIN
+(
+ *@altitudes where { .all ~~ Int:D } #= A non-empty list of integers
+)
+#==============================================================================
+{
+ "Input: %s\n".printf: @altitudes.join: ', ';
+
+ my Int @valley = find-widest-valley( @altitudes );
+
+ "Output: %s\n".printf: @valley\ .join: ', ';
+}
+
+#==============================================================================
+multi sub MAIN() # No input: run the test suite
+#==============================================================================
+{
+ run-tests();
+}
+
+#------------------------------------------------------------------------------
+# Given a profile as a list of altitudes, return the leftmost *widest valley*.
+# A valley is defined as a subarray of the profile consisting of two parts: the
+# first part is non-increasing and the second part is non-decreasing. Either
+# part can be empty.
+#
+# Example 1 Input: 1, 5, 5, 2, 8
+# Output: 5, 5, 2, 8
+#
+# Example 2 Input: 2, 6, 8, 5
+# Output: 2, 6, 8
+#
+# Example 3 Input: 9, 8, 13, 13, 2, 2, 15, 17
+# Output: 13, 13, 2, 2, 15, 17
+#
+# Example 4 Input: 2, 1, 2, 1, 3
+# Output: 2, 1, 2
+#
+# Example 5 Input: 1, 3, 3, 2, 1, 2, 3, 3, 2
+# Output: 3, 3, 2, 1, 2, 3, 3
+#------------------------------------------------------------------------------
+sub find-widest-valley( List:D[Int:D] $altitudes --> List:D[Int:D] )
+#------------------------------------------------------------------------------
+{
+ my Bool $in-left = True;
+ my Int @valley = $altitudes[ 0 ];
+ my Int @widest;
+
+ loop (my UInt $idx = 1; $idx <= $altitudes.end; ++$idx)
+ {
+ my Int $last = @valley[ *-1 ];
+ my Int $next = $altitudes[ $idx ];
+
+ if $in-left # In the left part of the valley
+ {
+ @valley.push: $next;
+
+ $in-left = False if $next > $last; # Change direction: left-->right
+ }
+ elsif $next >= $last # In the right part of the valley
+ {
+ @valley.push: $next;
+ }
+ else # Change direction: right-->left
+ {
+ # Backtrack to left-most non-ascending altitude
+
+ --$idx while $altitudes[ $idx - 1 ] >= $altitudes[ $idx ];
+
+ @widest = @valley if @valley.elems > @widest.elems;
+ @valley = $altitudes[ $idx ];
+ $in-left = True;
+ }
+ }
+
+ @widest = @valley if @valley.elems > @widest.elems;
+
+ return @widest;
+}
+
+#------------------------------------------------------------------------------
+sub run-tests()
+#------------------------------------------------------------------------------
+{
+ 'Running the test suite'.put;
+
+ for test-data.lines -> Str $line
+ {
+ my Str ($test, $in, $out) = $line.split: / \| /;
+ my Int @altitudes = $in\ .split( / \, / ).map: { .Int };
+ my Int @expected = $out\.split( / \, / ).map: { .Int };
+
+ is-deeply find-widest-valley( @altitudes ), @expected, $test;
+ }
+
+ 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|1,5,5,2,8 |5,5,2,8
+ Example 2|2,6,8,5 |2,6,8
+ Example 3|9,8,13,13,2,2,15,17 |13,13,2,2,15,17
+ Example 4|2,1,2,1,3 |2,1,2
+ Example 5|1,3,3,2,1,2,3,3,2 |3,3,2,1,2,3,3
+ First |5,4,3,2,4,5,4,3,1,4,5 |5,4,3,2,4,5
+ Second |10,7,3,5,9,9,8,6,4,4,3,5,7,1|9,9,8,6,4,4,3,5,7
+ Negatives|3,2,0,-1,-2,4,5,3,2 |3,2,0,-1,-2,4,5
+ No left |1,2,3,4,5,3,2 |1,2,3,4,5
+ No right |11,10,9,10,11,8,5,3,1,0,0 |11,8,5,3,1,0,0
+ END
+}
+
+###############################################################################