diff options
| author | PerlMonk-Athanasius <PerlMonk.Athanasius@gmail.com> | 2025-06-27 22:17:04 +1000 |
|---|---|---|
| committer | PerlMonk-Athanasius <PerlMonk.Athanasius@gmail.com> | 2025-06-27 22:17:04 +1000 |
| commit | c9647c2984b1a78f285f2f808ff4d73a8220e3ab (patch) | |
| tree | 649fd65a425b0d343212d72a10bea23afcb20aaf | |
| parent | 9b60d9035df0ef4c2674e87e9b01844523665e13 (diff) | |
| download | perlweeklychallenge-club-c9647c2984b1a78f285f2f808ff4d73a8220e3ab.tar.gz perlweeklychallenge-club-c9647c2984b1a78f285f2f808ff4d73a8220e3ab.tar.bz2 perlweeklychallenge-club-c9647c2984b1a78f285f2f808ff4d73a8220e3ab.zip | |
Perl & Raku solutions to Tasks 1 & 2 for Week 327
| -rw-r--r-- | challenge-327/athanasius/perl/ch-1.pl | 165 | ||||
| -rw-r--r-- | challenge-327/athanasius/perl/ch-2.pl | 196 | ||||
| -rw-r--r-- | challenge-327/athanasius/raku/ch-1.raku | 169 | ||||
| -rw-r--r-- | challenge-327/athanasius/raku/ch-2.raku | 189 |
4 files changed, 719 insertions, 0 deletions
diff --git a/challenge-327/athanasius/perl/ch-1.pl b/challenge-327/athanasius/perl/ch-1.pl new file mode 100644 index 0000000000..d0f9157d43 --- /dev/null +++ b/challenge-327/athanasius/perl/ch-1.pl @@ -0,0 +1,165 @@ +#!perl + +################################################################################ +=comment + +Perl Weekly Challenge 327 +========================= + +TASK #1 +------- +*Missing Integers* + +Submitted by: Mohammad Sajid Anwar + +You are given an array of n integers. + +Write a script to find all the missing integers in the range 1..n in the given +array. + +Example 1 + + Input: @ints = (1, 2, 1, 3, 2, 5) + Output: (4, 6) + + The given array has 6 elements. + So we are looking for integers in the range 1..6 in the given array. + The missing integers: (4, 6) + +Example 2 + + Input: @ints = (1, 1, 1) + Output: (2, 3) + +Example 3 + + Input: @ints = (2, 2, 1) + Output: (3) + +=cut +################################################################################ + +#--------------------------------------# +# Copyright © 2025 PerlMonk Athanasius # +#--------------------------------------# + +#=============================================================================== +=comment + +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.32; # Enables strictures +use warnings; +use Const::Fast; +use Regexp::Common qw( number ); +use Test::More; + +const my $USAGE => <<END; +Usage: + perl $0 [<ints> ...] + perl $0 + + [<ints> ...] A non-empty list of integers +END + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + $| = 1; + print "\nChallenge 327, Task #1: Missing Integers (Perl)\n\n"; +} + +#=============================================================================== +MAIN: +#=============================================================================== +{ + if (scalar @ARGV == 0) + { + run_tests(); + } + else + { + my @ints = @ARGV; + + for (@ints) + { + / ^ $RE{num}{int} $ /x or error( qq["$_" is not a valid integer] ); + } + + printf "Input: \@ints = (%s)\n", join ', ', @ints; + + my $missing = find_missing_ints( \@ints ); + + printf "Output: (%s)\n", join ', ', @$missing; + } +} + +#------------------------------------------------------------------------------- +sub find_missing_ints +#------------------------------------------------------------------------------- +{ + my ($ints) = @_; + my (@missing, %int_set); + + ++$int_set{ $_ } for @$ints; + + for my $i (1 .. scalar @$ints) + { + push @missing, $i unless exists $int_set{ $i }; + } + + return \@missing; +} + +#------------------------------------------------------------------------------- +sub run_tests +#------------------------------------------------------------------------------- +{ + print "Running the test suite\n"; + + while (my $line = <DATA>) + { + chomp $line; + + my ($test_name, $ints_str, $expd_str) = split / \| /x, $line; + + for ($test_name, $ints_str, $expd_str) + { + s/ ^ \s+ //x; + s/ \s+ $ //x; + } + + my @ints = split / \s+ /x, $ints_str; + my $missing = find_missing_ints( \@ints ); + my @expected = split / \s+ /x, $expd_str; + + is_deeply $missing, \@expected, $test_name; + } + + done_testing; +} + +#------------------------------------------------------------------------------- +sub error +#------------------------------------------------------------------------------- +{ + my ($message) = @_; + + die "ERROR: $message\n$USAGE"; +} + +################################################################################ + +__DATA__ +Example 1| 1 2 1 3 2 5|4 6 +Example 2| 1 1 1 |2 3 +Example 3| 2 2 1 |3 +None | 1 2 3 4 5 6| +Negatives|-2 0 3 5 -4 |1 2 4 diff --git a/challenge-327/athanasius/perl/ch-2.pl b/challenge-327/athanasius/perl/ch-2.pl new file mode 100644 index 0000000000..15112aef40 --- /dev/null +++ b/challenge-327/athanasius/perl/ch-2.pl @@ -0,0 +1,196 @@ +#!perl + +################################################################################ +=comment + +Perl Weekly Challenge 327 +========================= + +TASK #2 +------- +*MAD* + +Submitted by: Mohammad Sajid Anwar + +You are given an array of distinct integers. + +Write a script to find all pairs of elements with minimum absolute difference +(MAD) of any two elements. + +Example 1 + + Input: @ints = (4, 1, 2, 3) + Output: [1,2], [2,3], [3,4] + + The minimum absolute difference is 1. + Pairs with MAD: [1,2], [2,3], [3,4] + +Example 2 + + Input: @ints = (1, 3, 7, 11, 15) + Output: [1,3] + +Example 3 + + Input: @ints = (1, 5, 3, 8) + Output: [1,3], [3,5] + +=cut +################################################################################ + +#--------------------------------------# +# Copyright © 2025 PerlMonk Athanasius # +#--------------------------------------# + +#=============================================================================== +=comment + +Interface +--------- +1. If no command-line arguments are given, the test suite is run. Otherwise: +2. A non-empty list of distinct integers is entered on the command-line. + +Note +---- +Since the input integers are distinct, the smallest possible MAD is 1. + +=cut +#=============================================================================== + +use v5.32; # Enables strictures +use warnings; +use Const::Fast; +use List::Util qw( min ); +use Regexp::Common qw( number ); +use Test::More; + +const my $USAGE => <<END; +Usage: + perl $0 [<ints> ...] + perl $0 + + [<ints> ...] A non-empty list of distinct integers +END + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + $| = 1; + print "\nChallenge 327, Task #2: MAD (Perl)\n\n"; +} + +#=============================================================================== +MAIN: +#=============================================================================== +{ + if (scalar @ARGV == 0) + { + run_tests(); + } + else + { + my @ints = @ARGV; + + for (@ints) + { + / ^ $RE{num}{int} $ /x + or error( qq["$_" is not a valid integer] ) + } + + distinct( \@ints ) or error( 'The input integers are not distinct' ); + + printf "Input: \@ints = (%s)\n", join ', ', @ints; + + my $mad_pairs = find_MAD_pairs( \@ints ); + + printf "Output: %s\n", + join ', ', map { sprintf '[%d,%d]', @$_ } @$mad_pairs; + } +} + +#------------------------------------------------------------------------------- +sub find_MAD_pairs +#------------------------------------------------------------------------------- +{ + my ($ints) = @_; + my @sorted = sort { $a <=> $b } @$ints; + my %ab_diff; + + for my $i (0 .. $#sorted - 1) + { + my $lhs = $sorted[ $i ]; + my $rhs = $sorted[ $i + 1 ]; + my $diff = $rhs - $lhs; + + push @{ $ab_diff{ $diff } }, [ $lhs, $rhs ]; + } + + my $mad = min keys %ab_diff; + + return $ab_diff{ $mad }; +} + +#------------------------------------------------------------------------------- +sub distinct +#------------------------------------------------------------------------------- +{ + my ($ints) = @_; + my %count; + + for (@$ints) + { + return 0 if ++$count{ $_ } > 1; + } + + return 1; +} + +#------------------------------------------------------------------------------- +sub run_tests +#------------------------------------------------------------------------------- +{ + print "Running the test suite\n"; + + while (my $line = <DATA>) + { + chomp $line; + + my ($test_name, $ints_str, @exp_strs) = split / \| /x, $line; + + for ($test_name, $ints_str, @exp_strs) + { + s/ ^ \s+ //x; + s/ \s+ $ //x; + } + + my @ints = split / \s+ /x, $ints_str; + my $mad_pairs = find_MAD_pairs( \@ints ); + my @expected; + + for my $exp_pair (@exp_strs) + { + push @expected, [ split / \s+ /x, $exp_pair ]; + } + + is_deeply $mad_pairs, \@expected, $test_name; + } + + done_testing; +} + +#------------------------------------------------------------------------------- +sub error +#------------------------------------------------------------------------------- +{ + my ($message) = @_; + + die "ERROR: $message\n$USAGE"; +} + +################################################################################ + +__DATA__ +Example 1|4 1 2 3 |1 2|2 3|3 4 +Example 2|1 3 7 11 15|1 3 +Example 3|1 5 3 8 |1 3|3 5 diff --git a/challenge-327/athanasius/raku/ch-1.raku b/challenge-327/athanasius/raku/ch-1.raku new file mode 100644 index 0000000000..06fd543b42 --- /dev/null +++ b/challenge-327/athanasius/raku/ch-1.raku @@ -0,0 +1,169 @@ +use v6d; + +################################################################################ +=begin comment + +Perl Weekly Challenge 327 +========================= + +TASK #1 +------- +*Missing Integers* + +Submitted by: Mohammad Sajid Anwar + +You are given an array of n integers. + +Write a script to find all the missing integers in the range 1..n in the given +array. + +Example 1 + + Input: @ints = (1, 2, 1, 3, 2, 5) + Output: (4, 6) + + The given array has 6 elements. + So we are looking for integers in the range 1..6 in the given array. + The missing integers: (4, 6) + +Example 2 + + Input: @ints = (1, 1, 1) + Output: (2, 3) + +Example 3 + + Input: @ints = (2, 2, 1) + Output: (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. A non-empty list of integers is entered on the command-line. +3. If the first integer in the list is negative, it must be preceded by "--" to + signal that it is not a command-line flag. + +=end comment +#=============================================================================== + +use Test; + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + "\nChallenge 327, Task #1: Missing Integers (Raku)\n".put; +} + +#=============================================================================== +multi sub MAIN +( + #| A non-empty list of integers + + *@ints where { .elems > 0 && .all ~~ Int:D } +) +#=============================================================================== +{ + "Input: \@ints = (%s)\n".printf: @ints.join: ', '; + + my UInt @missing = find-missing-ints( @ints ); + + "Output: (%s)\n".printf: @missing.join: ', '; +} + +#=============================================================================== +multi sub MAIN() # No input: run the test suite +#=============================================================================== +{ + run-tests(); +} + +#------------------------------------------------------------------------------- +sub find-missing-ints( List:D[Int:D] $ints --> List:D[UInt:D] ) +#------------------------------------------------------------------------------- +{ + my UInt @missing; + my Set[Int] $int-set = Set[Int].new: $ints.map: { .Int }; # Int, NOT IntStr + + for 1 .. $ints.elems -> UInt $i + { + @missing.push: $i if $i ∉ $int-set; + } + + return @missing; +} + +#------------------------------------------------------------------------------- +sub run-tests() +#------------------------------------------------------------------------------- +{ + 'Running the test suite'.put; + + for test-data.lines -> Str $line + { + my Str ($test-name, $ints-str, $expd-str) = $line.split: / \| /; + + for $test-name, $ints-str, $expd-str + { + s/ ^ \s+ //; + s/ \s+ $ //; + } + + my Int @ints = $ints-str.split( / \s+ /, :skip-empty ) + .map: { .Int }; + my UInt @missing = find-missing-ints( @ints ); + my UInt @expected = $expd-str.split( / \s+ /, :skip-empty ) + .map: { .Int }; + + is-deeply @missing, @expected, $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 1 3 2 5|4 6 + Example 2| 1 1 1 |2 3 + Example 3| 2 2 1 |3 + None | 1 2 3 4 5 6| + Negatives|-2 0 3 5 -4 |1 2 4 + END +} + +################################################################################ diff --git a/challenge-327/athanasius/raku/ch-2.raku b/challenge-327/athanasius/raku/ch-2.raku new file mode 100644 index 0000000000..3dfbd89c9d --- /dev/null +++ b/challenge-327/athanasius/raku/ch-2.raku @@ -0,0 +1,189 @@ +use v6d; + +################################################################################ +=begin comment + +Perl Weekly Challenge 327 +========================= + +TASK #2 +------- +*MAD* + +Submitted by: Mohammad Sajid Anwar + +You are given an array of distinct integers. + +Write a script to find all pairs of elements with minimum absolute difference +(MAD) of any two elements. + +Example 1 + + Input: @ints = (4, 1, 2, 3) + Output: [1,2], [2,3], [3,4] + + The minimum absolute difference is 1. + Pairs with MAD: [1,2], [2,3], [3,4] + +Example 2 + + Input: @ints = (1, 3, 7, 11, 15) + Output: [1,3] + +Example 3 + + Input: @ints = (1, 5, 3, 8) + Output: [1,3], [3,5] + +=end comment +################################################################################ + +#--------------------------------------# +# Copyright © 2025 PerlMonk Athanasius # +#--------------------------------------# + +#=============================================================================== +=begin comment + +Interface +--------- +1. If no command-line arguments are given, the test suite is run. Otherwise: +2. A non-empty list of distinct integers is entered on the command-line. +3. If the first integer in the list is negative, it must be preceded by "--" to + signal that it is not a command-line flag. + +Note +---- +Since the input integers are distinct, the smallest possible MAD is 1. + +=end comment +#=============================================================================== + +use Test; + +subset IntPair of List where (Int, Int); +subset Pos of Int where * > 0; + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + "\nChallenge 327, Task #2: MAD (Raku)\n".put; +} + +#=============================================================================== +multi sub MAIN +( + #| A non-empty list of distinct integers + + *@ints where { .elems > 0 && .all ~~ Int:D && distinct( @ints ) } +) +#=============================================================================== +{ + "Input: \@ints = (%s)\n".printf: @ints.join: ', '; + + my IntPair @mad-pairs = find-MAD-pairs( @ints ); + + "Output: %s\n".printf: + @mad-pairs.map( { '[%d,%d]'.sprintf: @$_ } ).join: ', '; +} + +#=============================================================================== +multi sub MAIN() # No input: run the test suite +#=============================================================================== +{ + run-tests(); +} + +#------------------------------------------------------------------------------- +sub find-MAD-pairs( List:D[Int:D] $ints --> List:D[IntPair:D] ) +#------------------------------------------------------------------------------- +{ + my Array[IntPair] %ab-diff{Pos}; + + my Int @sorted = $ints.sort; + + for 0 .. @sorted.end - 1 -> UInt $i + { + my Int $lhs = @sorted[ $i ]; + my Int $rhs = @sorted[ $i + 1 ]; + my Pos $diff = $rhs - $lhs; + + %ab-diff{ $diff }.push: [ +$lhs, +$rhs ]; + } + + my Pos $mad = %ab-diff.keys.min; + + return |%ab-diff{ $mad }; +} + +#------------------------------------------------------------------------------- +sub distinct( List:D[Int:D] $ints --> Bool:D ) +#------------------------------------------------------------------------------- +{ + my Pos %count{Int}; + + for @$ints + { + return False if ++%count{ $_ } > 1; + } + + return True; +} + +#------------------------------------------------------------------------------- +sub run-tests() +#------------------------------------------------------------------------------- +{ + 'Running the test suite'.put; + + for test-data.lines -> Str $line + { + my Str ($test-name, $ints-str, @exp-strs) = $line.split: / \| /; + + for $test-name, $ints-str, @exp-strs + { + s/ ^ \s+ //; + s/ \s+ $ //; + } + + my Int @ints = $ints-str.split( / \s+ /, :skip-empty ) + .map: { .Int }; + my IntPair @mad-pairs = find-MAD-pairs( @ints ); + my IntPair @expected; + + for @exp-strs -> Str $exp-pair + { + @expected.push: [ $exp-pair.split( / \s+ /, :skip-empty ) + .map: { .Int } ]; + } + + is-deeply @mad-pairs, @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|4 1 2 3 |1 2|2 3|3 4 + Example 2|1 3 7 11 15|1 3 + Example 3|1 5 3 8 |1 3|3 5 + END +} + +################################################################################ |
