diff options
| author | PerlMonk-Athanasius <PerlMonk.Athanasius@gmail.com> | 2023-02-26 18:40:58 +1000 |
|---|---|---|
| committer | PerlMonk-Athanasius <PerlMonk.Athanasius@gmail.com> | 2023-02-26 18:40:58 +1000 |
| commit | 67ed83401d2b7e77caa48b9fd76b6da9be91f4bc (patch) | |
| tree | 71f2ce19840621d15cef5912c7d82fe85120c816 | |
| parent | b284f024a9a0fb134828bfaba21aa1d5354ac2f7 (diff) | |
| download | perlweeklychallenge-club-67ed83401d2b7e77caa48b9fd76b6da9be91f4bc.tar.gz perlweeklychallenge-club-67ed83401d2b7e77caa48b9fd76b6da9be91f4bc.tar.bz2 perlweeklychallenge-club-67ed83401d2b7e77caa48b9fd76b6da9be91f4bc.zip | |
Perl & Raku solutions to Tasks 1 & 2 for Week 205
| -rw-r--r-- | challenge-205/athanasius/perl/ch-1.pl | 143 | ||||
| -rw-r--r-- | challenge-205/athanasius/perl/ch-2.pl | 212 | ||||
| -rw-r--r-- | challenge-205/athanasius/raku/ch-1.raku | 146 | ||||
| -rw-r--r-- | challenge-205/athanasius/raku/ch-2.raku | 200 |
4 files changed, 701 insertions, 0 deletions
diff --git a/challenge-205/athanasius/perl/ch-1.pl b/challenge-205/athanasius/perl/ch-1.pl new file mode 100644 index 0000000000..150f4f8864 --- /dev/null +++ b/challenge-205/athanasius/perl/ch-1.pl @@ -0,0 +1,143 @@ +#!perl + +############################################################################### +=comment + +Perl Weekly Challenge 205 +========================= + +TASK #1 +------- +*Third Highest* + +Submitted by: Mohammad S Anwar + +You are given an array of integers. + +Write a script to find out the Third Highest if found otherwise return the +maximum. + +Example 1 + + Input: @array = (5,3,4) + Output: 3 + + First highest is 5. Second highest is 4. Third highest is 3. + +Example 2 + + Input: @array = (5,6) + Output: 6 + + First highest is 6. Second highest is 5. Third highest is missing, so maximum + is returned. + +Example 3 + + Input: @array = (5,4,4,3) + Output: 3 + + First highest is 5. Second highest is 4. Third highest is 3. + +=cut +############################################################################### + +#--------------------------------------# +# Copyright © 2023 PerlMonk Athanasius # +#--------------------------------------# + +#============================================================================== +=comment + +Interface +--------- +If no command-line arguments are given, the test suite is run. + +=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 205, Task #1: Third Highest (Perl)\n\n"; +} + +#============================================================================== +MAIN: +#============================================================================== +{ + if (scalar @ARGV == 0) + { + run_tests(); + } + else + { + my @array = map { $_ + 0 } @ARGV; # Normalize + + / ^ $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", find_third_highest( \@array ); + } +} + +#------------------------------------------------------------------------------ +sub find_third_highest +#------------------------------------------------------------------------------ +{ + my ($array) = @_; + my %count; + + ++$count{ $_ } for @$array; + + my @sorted = sort { $a <=> $b } keys %count; + + return scalar( @sorted ) >= 3 ? $sorted[ -3 ] : $sorted[ -1 ]; +} + +#------------------------------------------------------------------------------ +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 = map { $_ + 0 } split / , \s* /x, $input; + my $got = find_third_highest( \@array ); + + is $got, $expected + 0, $test_name; + } + + done_testing; +} + +############################################################################### + +__DATA__ +Example 1| 5, 3, 4 | 3 +Example 2| 5, 6 | 6 +Example 3| 5, 4, 4, 3 | 3 +Negatives|-1,-2,-3,-4,-2|-3 diff --git a/challenge-205/athanasius/perl/ch-2.pl b/challenge-205/athanasius/perl/ch-2.pl new file mode 100644 index 0000000000..c4e33f8e00 --- /dev/null +++ b/challenge-205/athanasius/perl/ch-2.pl @@ -0,0 +1,212 @@ +#!perl + +############################################################################### +=comment + +Perl Weekly Challenge 205 +========================= + +TASK #2 +------- +*Maximum XOR* + +Submitted by: Mohammad S Anwar + +You are given an array of integers. + +Write a script to find the highest value obtained by XORing any two distinct +members of the array. + +Example 1 + + Input: @array = (1,2,3,4,5,6,7) + Output: 7 + + The maximum result of 1 xor 6 = 7. + +Example 2 + + Input: @array = (2,4,1,3) + Output: 7 + + The maximum result of 4 xor 3 = 7. + +Example 3 + + Input: @array = (10,5,7,12,8) + Output: 15 + + The maximum result of 10 xor 5 = 15. + +=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, then the output is augmented with an + explanation of how the result was obtained. + +Assumption +---------- +The elements of the input array are *non-negative* integers only, as shown in +the examples. + +=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 [<array> ...] + perl $0 + + [<array> ...] A list of non-negative integers, at least 2 distinct\n"; + +#------------------------------------------------------------------------------ +BEGIN +#------------------------------------------------------------------------------ +{ + $| = 1; + print "\nChallenge 205, Task #2: Maximum XOR (Perl)\n\n"; +} + +#============================================================================== +MAIN: +#============================================================================== +{ + if (scalar @ARGV == 0) + { + run_tests(); + } + else + { + my $array = parse_command_line(); + + printf "Input: \@array = (%s)\n", join ',', @$array; + + my ($xor, $a, $b) = find_xor_max( $array ); + + print "Output: $xor\n"; + + if ($VERBOSE) + { + my $len_a = length sprintf '%b', $a; + my $len_b = length sprintf '%b', $b; + my $width = ($len_a >= $len_b) ? $len_a : $len_b; + + printf "\nThe maximum result of %*d xor %*d = %*d\n", + $width, $a, $width, $b, $width, $xor; + + printf " (binary: %0*b xor %0*b = %0*b)\n", + $width, $a, $width, $b, $width, $xor; + } + } +} + +#------------------------------------------------------------------------------ +sub find_xor_max +#------------------------------------------------------------------------------ +{ + my ($array) = @_; + + my %freq; + ++$freq{ $_ } for @$array; + + my @ordered = sort { $a <=> $b } keys %freq; + + scalar @ordered >= 2 + or error( 'The input array does not contain 2 distinct members' ); + + my $xor_max = -1; + my ($a_max, $b_max); + + for my $i (0 .. $#ordered - 1) + { + my $aa = $ordered[ $i ]; + + for my $j ($i + 1 .. $#ordered) + { + my $bb = $ordered[ $j ]; + my $xor = $aa ^ $bb; + + if ($xor > $xor_max) + { + $xor_max = $xor; + $a_max = $aa; + $b_max = $bb; + } + } + } + + return ($xor_max, $a_max, $b_max); +} + +#------------------------------------------------------------------------------ +sub parse_command_line +#------------------------------------------------------------------------------ +{ + my $args = scalar @ARGV; + $args >= 2 or error( 'Expected at least 2 command-line arguments, ' . + "found $args" ); + + for (@ARGV) + { + / ^ $RE{num}{int} $ /x + or error( qq["$_" is not a valid integer] ); + + $_ >= 0 or error( qq["$_" is negative] ); + } + + return [ @ARGV ]; +} + +#------------------------------------------------------------------------------ +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 = (find_xor_max( \@array ))[ 0 ]; + + is $got, $expected, $test_name; + } + + done_testing; +} + +#------------------------------------------------------------------------------ +sub error +#------------------------------------------------------------------------------ +{ + my ($message) = @_; + + die "ERROR: $message\n$USAGE"; +} + +############################################################################### + +__DATA__ +Example 1| 1, 2, 3, 4, 5, 6, 7|7 +Example 2| 2, 4, 1, 3 |7 +Example 3|10, 5, 7, 12, 8 |15 diff --git a/challenge-205/athanasius/raku/ch-1.raku b/challenge-205/athanasius/raku/ch-1.raku new file mode 100644 index 0000000000..3f7f83eaa4 --- /dev/null +++ b/challenge-205/athanasius/raku/ch-1.raku @@ -0,0 +1,146 @@ +use v6d; + +############################################################################### +=begin comment + +Perl Weekly Challenge 205 +========================= + +TASK #1 +------- +*Third Highest* + +Submitted by: Mohammad S Anwar + +You are given an array of integers. + +Write a script to find out the Third Highest if found otherwise return the +maximum. + +Example 1 + + Input: @array = (5,3,4) + Output: 3 + + First highest is 5. Second highest is 4. Third highest is 3. + +Example 2 + + Input: @array = (5,6) + Output: 6 + + First highest is 6. Second highest is 5. Third highest is missing, so maximum + is returned. + +Example 3 + + Input: @array = (5,4,4,3) + Output: 3 + + First highest is 5. Second highest is 4. Third highest is 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. + +=end comment +#============================================================================== + +use Test; + +#------------------------------------------------------------------------------ +BEGIN +#------------------------------------------------------------------------------ +{ + "\nChallenge 205, Task #1: Third Highest (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: find-third-highest( @array ); +} + +#============================================================================== +multi sub MAIN() # No input: run the test suite +#============================================================================== +{ + run-tests(); +} + +#------------------------------------------------------------------------------ +sub find-third-highest( List:D[Int:D] $array where { .elems > 0 } --> Int:D ) +#------------------------------------------------------------------------------ +{ + my UInt %count{Int}; + + ++%count{ $_ } for @$array; + + my Int @sorted = %count<>:k.sort; + + return @sorted.elems >= 3 ?? @sorted[ *-3 ] !! @sorted[ *-1 ]; +} + +#------------------------------------------------------------------------------ +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 Int $got = find-third-highest( @array ); + + is $got, $expected.Int, $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| 5, 3, 4 | 3 + Example 2| 5, 6 | 6 + Example 3| 5, 4, 4, 3 | 3 + Negatives|-1,-2,-3,-4,-2|-3 + END +} + +############################################################################### diff --git a/challenge-205/athanasius/raku/ch-2.raku b/challenge-205/athanasius/raku/ch-2.raku new file mode 100644 index 0000000000..155d804e4f --- /dev/null +++ b/challenge-205/athanasius/raku/ch-2.raku @@ -0,0 +1,200 @@ +use v6d; + +############################################################################### +=begin comment + +Perl Weekly Challenge 205 +========================= + +TASK #2 +------- +*Maximum XOR* + +Submitted by: Mohammad S Anwar + +You are given an array of integers. + +Write a script to find the highest value obtained by XORing any two distinct +members of the array. + +Example 1 + + Input: @array = (1,2,3,4,5,6,7) + Output: 7 + + The maximum result of 1 xor 6 = 7. + +Example 2 + + Input: @array = (2,4,1,3) + Output: 7 + + The maximum result of 4 xor 3 = 7. + +Example 3 + + Input: @array = (10,5,7,12,8) + Output: 15 + + The maximum result of 10 xor 5 = 15. + +=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, then the output is augmented with an explanation + of how the result was obtained. + +Assumption +---------- +The elements of the input array are *non-negative* integers only, as shown in +the examples. + +=end comment +#============================================================================== + +use Test; + +my Bool constant $VERBOSE = True; + +#------------------------------------------------------------------------------ +BEGIN +#------------------------------------------------------------------------------ +{ + "\nChallenge 205, Task #2: Maximum XOR (Raku)\n".put; +} + +#============================================================================== +multi sub MAIN +( + #| A list of non-negative integers, at least 2 distinct + + *@array where { .elems >= 2 && .all ~~ UInt:D } +) +#============================================================================== +{ + "Input: \@array = (%s)\n".printf: @array.join: ','; + + my UInt ($xor, $a, $b) = find-xor-max( @array ); + + "Output: $xor".put; + + if $VERBOSE + { + my Str $bin-a = '%b'.sprintf: $a; + my Str $bin-b = '%b'.sprintf: $b; + my UInt $width = ($bin-a.chars, $bin-b.chars).max; + + "\nThe maximum result of %*d xor %*d = %*d\n".printf: + $width, $a, $width, $b, $width, $xor; + + " (binary: %0*b xor %0*b = %0*b)\n".printf: + $width, $a, $width, $b, $width, $xor; + } +} + +#============================================================================== +multi sub MAIN() # No input: run the test suite +#============================================================================== +{ + run-tests(); +} + +#------------------------------------------------------------------------------ +sub find-xor-max( List:D[UInt:D] $array --> List:D[UInt:D] ) +#------------------------------------------------------------------------------ +{ + my UInt %freq{UInt}; + + ++%freq{ $_ } for @$array; + + my UInt @ordered = %freq.keys.sort; + + @ordered.elems >= 2 + or error( 'The input array does not contain 2 distinct members' ); + + my Int $xor-max = -1; + my UInt ($a-max, $b-max); + + for 0 .. @ordered.end - 1 -> UInt $i + { + my UInt $a = @ordered[ $i ]; + + for $i + 1 .. @ordered.end -> UInt $j + { + my UInt $b = @ordered[ $j ]; + my UInt $xor = $a +^ $b; + + if $xor > $xor-max + { + $xor-max = $xor; + $a-max = $a; + $b-max = $b; + } + } + } + + return $xor-max, $a-max, $b-max; +} + +#------------------------------------------------------------------------------ +sub run-tests() +#------------------------------------------------------------------------------ +{ + 'Running the test suite'.put; + + for test-data.lines -> Str $line + { + my Str ($test-name, $input, $expected) = $line.split: / \| /; + + my UInt @array = $input.split( / \, \s* / ).map: { .Int }; + my UInt $got = (find-xor-max( @array ))[ 0 ]; + + is $got, $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| 1, 2, 3, 4, 5, 6, 7|7 + Example 2| 2, 4, 1, 3 |7 + Example 3|10, 5, 7, 12, 8 |15 + END +} +############################################################################### |
