diff options
| author | Mohammad S Anwar <Mohammad.Anwar@yahoo.com> | 2023-02-05 16:01:14 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-02-05 16:01:14 +0000 |
| commit | 93d184d4a4830a4f040b46194021983295f14fa1 (patch) | |
| tree | 2dc361388d7d0c756d4dcd1db79dc75edcde8ce0 | |
| parent | f925f1996edfb29910515826fbb4c0afe5338dbe (diff) | |
| parent | baa28f4354bf59cc0f70659803374c7be0557122 (diff) | |
| download | perlweeklychallenge-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.pl | 157 | ||||
| -rw-r--r-- | challenge-202/athanasius/perl/ch-2.pl | 210 | ||||
| -rw-r--r-- | challenge-202/athanasius/raku/ch-1.raku | 160 | ||||
| -rw-r--r-- | challenge-202/athanasius/raku/ch-2.raku | 206 |
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 +} + +############################################################################### |
