diff options
| -rw-r--r-- | challenge-272/athanasius/perl/ch-1.pl | 176 | ||||
| -rw-r--r-- | challenge-272/athanasius/perl/ch-2.pl | 231 | ||||
| -rw-r--r-- | challenge-272/athanasius/raku/ch-1.raku | 172 | ||||
| -rw-r--r-- | challenge-272/athanasius/raku/ch-2.raku | 204 |
4 files changed, 783 insertions, 0 deletions
diff --git a/challenge-272/athanasius/perl/ch-1.pl b/challenge-272/athanasius/perl/ch-1.pl new file mode 100644 index 0000000000..eb28c4ea49 --- /dev/null +++ b/challenge-272/athanasius/perl/ch-1.pl @@ -0,0 +1,176 @@ +#!perl + +################################################################################ +=comment + +Perl Weekly Challenge 272 +========================= + +TASK #1 +------- +*Defang IP Address* + +Submitted by: Mohammad Sajid Anwar + +You are given a valid IPv4 address. + +Write a script to return the defanged version of the given IP address. + + A defanged IP address replaces every period “.” with “[.]". + +Example 1 + + Input: $ip = "1.1.1.1" + Output: "1[.]1[.]1[.]1" + +Example 2 + + Input: $ip = "255.101.1.0" + Output: "255[.]101[.]1[.]0" + +=cut +################################################################################ + +#--------------------------------------# +# Copyright © 2024 PerlMonk Athanasius # +#--------------------------------------# + +#=============================================================================== +=comment + +Assumptions +----------- +1. The given IP address is in quad-dotted notation: 4 decimal numbers (octets), + each in the range 0 to 255, separated by dots (periods). +2. For octets, leading zeros are allowed, but leading "+" signs are not. + +Interface +--------- +1. If no command-line arguments are given, the test suite is run. Otherwise: +2. The IP to be defanged is entered on the command-line as a single string. + +=cut +#=============================================================================== + +use v5.32.1; # Enables strictures +use warnings; +use Const::Fast; +use Regexp::Common qw( number ); +use Test::More; + +const my $OCTET_MAX => 255; +const my $USAGE => <<END; +Usage: + perl $0 <ip> + perl $0 + + <ip> A valid IP address in quad-dotted notation +END + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + $| = 1; + print "\nChallenge 272, Task #1: Defang IP Address (Perl)\n\n"; +} + +#=============================================================================== +MAIN: +#=============================================================================== +{ + my $argc = scalar @ARGV; + + if ($argc == 0) + { + run_tests(); + } + elsif ($argc == 1) + { + my $ip = $ARGV[ 0 ]; + + is_valid_ip( $ip ) or error( qq[Invalid IP "$ip"] ); + + print qq[Input: \$ip = "$ip"\n]; + + my $defanged = defang( $ip ); + + print qq[Output: "$defanged"\n]; + } + else + { + error( "Expected 1 or 0 command-line arguments, found $argc" ); + } +} + +#------------------------------------------------------------------------------- +sub defang +#------------------------------------------------------------------------------- +{ + my ($ip) = @_; + + return $ip =~ s{ \. }{[.]}grx; +} + +#------------------------------------------------------------------------------- +sub is_valid_ip +#------------------------------------------------------------------------------- +{ + my ($ip) = @_; + + return 0 unless $ip =~ / ^ [0-9.]+ $ /x; + + my @octets = split / \. /x, $ip; + + return 0 unless scalar @octets == 4; + + for (@octets) + { + return 0 unless m/ ^ $RE{num}{int} $ /x && 0 <= $_ <= $OCTET_MAX; + } + + return 1; +} + +#------------------------------------------------------------------------------- +sub run_tests +#------------------------------------------------------------------------------- +{ + print "Running the test suite\n"; + + while (my $line = <DATA>) + { + chomp $line; + + my ($test_name, $ip, $expected) = split / \| /x, $line; + + for ($test_name, $ip, $expected) + { + s/ ^ \s+ //x; + s/ \s+ $ //x; + } + + is_valid_ip( $ip ) or error( qq[Invalid IP "$ip"] ); + + my $defanged = defang( $ip ); + + is $defanged, $expected, $test_name; + } + + done_testing; +} + +#------------------------------------------------------------------------------- +sub error +#------------------------------------------------------------------------------- +{ + my ($message) = @_; + + die "ERROR: $message\n$USAGE"; +} + +################################################################################ + +__DATA__ +Example 1|1.1.1.1 |1[.]1[.]1[.]1 +Example 2|255.101.1.0|255[.]101[.]1[.]0 diff --git a/challenge-272/athanasius/perl/ch-2.pl b/challenge-272/athanasius/perl/ch-2.pl new file mode 100644 index 0000000000..f2c9322ea9 --- /dev/null +++ b/challenge-272/athanasius/perl/ch-2.pl @@ -0,0 +1,231 @@ +#!perl + +################################################################################ +=comment + +Perl Weekly Challenge 272 +========================= + +TASK #2 +------- +*String Score* + +Submitted by: Mohammad Sajid Anwar + +You are given a string, $str. + +Write a script to return the score of the given string. + + The score of a string is defined as the sum of the absolute difference + between the ASCII values of adjacent characters. + +Example 1 + + Input: $str = "hello" + Output: 13 + + ASCII values of characters: + h = 104 + e = 101 + l = 108 + l = 108 + o = 111 + + Score => |104 - 101| + |101 - 108| + |108 - 108| + |108 - 111| + => 3 + 7 + 0 + 3 + => 13 + +Example 2 + + Input: "perl" + Output: 30 + + ASCII values of characters: + p = 112 + e = 101 + r = 114 + l = 108 + + Score => |112 - 101| + |101 - 114| + |114 - 108| + => 11 + 13 + 6 + => 30 + +Example 3 + + Input: "raku" + Output: 37 + + ASCII values of characters: + r = 114 + a = 97 + k = 107 + u = 117 + + Score => |114 - 97| + |97 - 107| + |107 - 117| + => 17 + 10 + 10 + => 37 + +=cut +################################################################################ + +#--------------------------------------# +# Copyright © 2024 PerlMonk Athanasius # +#--------------------------------------# + +#=============================================================================== +=comment + +Assumption +---------- +The input string may contain only printable ASCII characters, in the range ' ' +(space, value 0x20 = 32) to '~' (tilde, value 0x7E = 176). + +Interface +--------- +1. If no command-line arguments are given, the test suite is run. Otherwise: +2. The input string is entered on the command-line. + +Note +---- +Command-line input is assumed to be ASCII-encoded. The input is checked for non- +ASCII characters; however, if the input is in a different encoding, this might +not be detected. For example, when "perl ch-2.pl ΓΔ" is entered at a DOS prompt +under Windows 11, the script receives the input string as "G?", which passes the +ASCII check. + +=cut +#=============================================================================== + +use v5.32.1; # Enables strictures +use warnings; +use Const::Fast; +use Test::More; + +use constant DEBUG => 0; + +const my $ASCII_MAX => '~'; +const my $ASCII_MIN => ' '; +const my $USAGE => <<END; +Usage: + perl $0 <str> + perl $0 + + <str> A string of printable ASCII characters +END + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + $| = 1; + print "\nChallenge 272, Task #2: String Score (Perl)\n\n"; +} + +#=============================================================================== +MAIN: +#=============================================================================== +{ + my $argc = scalar @ARGV; + + if ($argc == 0) + { + run_tests(); + } + elsif ($argc == 1) + { + my $str = $ARGV[ 0 ]; + + validate_ascii( $str ); + + print qq[Input: \$str = "$str"\n]; + + my $score = find_string_score( $str ); + + print "Output: $score\n"; + } + else + { + error( "Expected 1 or 0 command-line arguments, found $argc" ); + } +} + +#------------------------------------------------------------------------------- +sub find_string_score +#------------------------------------------------------------------------------- +{ + my ($str) = @_; + my @ascii = map { ord() } split //, $str; + my $score = 0; + + for my $i (0 .. $#ascii - 1) + { + $score += abs( $ascii[ $i ] - $ascii[ $i + 1 ] ); + } + + return $score; +} + +#------------------------------------------------------------------------------- +sub validate_ascii +#------------------------------------------------------------------------------- +{ + my ($str) = @_; + + if (DEBUG) + { + my @ords = map { ord() } split //, $str; + + printf qq[DEBUG: \$str = "%s" (%s)\n], + $str, join ' ', map { sprintf '%x', $_ } @ords; + } + + for (split //, $str) + { + $ASCII_MIN le $_ le $ASCII_MAX + or error( 'chr(' . ord . ') is not a printable ASCII character'); + } +} + +#------------------------------------------------------------------------------- +sub run_tests +#------------------------------------------------------------------------------- +{ + print "Running the test suite\n"; + + while (my $line = <DATA>) + { + chomp $line; + + my ($test_name, $str, $expected) = split / \| /x, $line; + + for ($test_name, $str, $expected) + { + s/ ^ \s+ //x; + s/ \s+ $ //x; + } + + validate_ascii( $str ) if DEBUG; + + my $score = find_string_score( $str ); + + is $score, $expected, $test_name; + } + + done_testing; +} + +#------------------------------------------------------------------------------- +sub error +#------------------------------------------------------------------------------- +{ + my ($message) = @_; + + die "ERROR: $message\n$USAGE"; +} + +################################################################################ + +__DATA__ +Example 1|hello|13 +Example 2|perl |30 +Example 3|raku |37 diff --git a/challenge-272/athanasius/raku/ch-1.raku b/challenge-272/athanasius/raku/ch-1.raku new file mode 100644 index 0000000000..abb4b5e7b4 --- /dev/null +++ b/challenge-272/athanasius/raku/ch-1.raku @@ -0,0 +1,172 @@ +use v6d; + +################################################################################ +=begin comment + +Perl Weekly Challenge 272 +========================= + +TASK #1 +------- +*Defang IP Address* + +Submitted by: Mohammad Sajid Anwar + +You are given a valid IPv4 address. + +Write a script to return the defanged version of the given IP address. + + A defanged IP address replaces every period “.” with “[.]". + +Example 1 + + Input: $ip = "1.1.1.1" + Output: "1[.]1[.]1[.]1" + +Example 2 + + Input: $ip = "255.101.1.0" + Output: "255[.]101[.]1[.]0" + +=end comment +################################################################################ + +#--------------------------------------# +# Copyright © 2024 PerlMonk Athanasius # +#--------------------------------------# + +#=============================================================================== +=begin comment + +Assumptions +----------- +1. The given IP address is in quad-dotted notation: 4 decimal numbers (octets), + each in the range 0 to 255, separated by dots (periods). +2. For octets, leading zeros are allowed, but leading "+" signs are not. + +Interface +--------- +1. If no command-line arguments are given, the test suite is run. Otherwise: +2. The IP to be defanged is entered on the command-line as a single string. + +=end comment +#=============================================================================== + +use Test; + +my UInt constant OCTET-MAX = 255; + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + "\nChallenge 272, Task #1: Defang IP Address (Raku)\n".put; +} + +#=============================================================================== +multi sub MAIN +( + Str:D $ip #= A valid IP address in quad-dotted notation +) +#=============================================================================== +{ + is-valid-ip( $ip ) or error( qq[Invalid IP "$ip"] ); + + qq[Input: \$ip = "$ip"].put; + + my Str $defanged = defang( $ip ); + + qq[Output: "$defanged"].put; +} + +#=============================================================================== +multi sub MAIN() # No input: run the test suite +#=============================================================================== +{ + run-tests(); +} + +#------------------------------------------------------------------------------- +sub defang( Str:D $ip --> Str:D ) +#------------------------------------------------------------------------------- +{ + return S:g{ \. } = '[.]' with $ip; +} + +#------------------------------------------------------------------------------- +sub is-valid-ip( Str:D $ip --> Bool:D ) +#------------------------------------------------------------------------------- +{ + return False unless $ip ~~ / ^ <[ 0..9 . ]>+ $ /; + + my Str @octets = $ip.split: '.', :skip-empty; + + return False unless @octets.elems == 4; + + for @octets + { + return False unless +$_ ~~ UInt:D && +$_ <= OCTET-MAX; + } + + return True; +} + +#------------------------------------------------------------------------------- +sub run-tests() +#------------------------------------------------------------------------------- +{ + 'Running the test suite'.put; + + for test-data.lines -> Str $line + { + my Str ($test-name, $ip, $expected) = $line.split: / \| /; + + for $test-name, $ip, $expected + { + s/ ^ \s+ //; + s/ \s+ $ //; + } + + is-valid-ip( $ip ) or error( qq[Invalid IP "$ip"] ); + + my Str $defanged = defang( $ip ); + + is $defanged, $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.1.1.1 |1[.]1[.]1[.]1 + Example 2|255.101.1.0|255[.]101[.]1[.]0 + END +} + +################################################################################ diff --git a/challenge-272/athanasius/raku/ch-2.raku b/challenge-272/athanasius/raku/ch-2.raku new file mode 100644 index 0000000000..7c9714edae --- /dev/null +++ b/challenge-272/athanasius/raku/ch-2.raku @@ -0,0 +1,204 @@ +use v6d; + +################################################################################ +=begin comment + +Perl Weekly Challenge 272 +========================= + +TASK #2 +------- +*String Score* + +Submitted by: Mohammad Sajid Anwar + +You are given a string, $str. + +Write a script to return the score of the given string. + + The score of a string is defined as the sum of the absolute difference + between the ASCII values of adjacent characters. + +Example 1 + + Input: $str = "hello" + Output: 13 + + ASCII values of characters: + h = 104 + e = 101 + l = 108 + l = 108 + o = 111 + + Score => |104 - 101| + |101 - 108| + |108 - 108| + |108 - 111| + => 3 + 7 + 0 + 3 + => 13 + +Example 2 + + Input: "perl" + Output: 30 + + ASCII values of characters: + p = 112 + e = 101 + r = 114 + l = 108 + + Score => |112 - 101| + |101 - 114| + |114 - 108| + => 11 + 13 + 6 + => 30 + +Example 3 + + Input: "raku" + Output: 37 + + ASCII values of characters: + r = 114 + a = 97 + k = 107 + u = 117 + + Score => |114 - 97| + |97 - 107| + |107 - 117| + => 17 + 10 + 10 + => 37 + +=end comment +################################################################################ + +#--------------------------------------# +# Copyright © 2024 PerlMonk Athanasius # +#--------------------------------------# + +#=============================================================================== +=begin comment + +Assumptions +----------- +1. Command-line input is assumed to be ASCII-encoded. +2. The input string may contain only printable ASCII characters, in the range + ' ' (space, value 0x20 = 32) to '~' (tilde, value 0x7E = 176). + +Interface +--------- +1. If no command-line arguments are given, the test suite is run. Otherwise: +2. The input string is entered on the command-line. + +=end comment +#=============================================================================== + +use Test; + +my Str constant ASCII-MAX = '~'; +my Str constant ASCII-MIN = ' '; + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + "\nChallenge 272, Task #2: String Score (Raku)\n".put; +} + +#=============================================================================== +multi sub MAIN +( + Str:D $str #= A string of printable ASCII characters +) +#=============================================================================== +{ + for $str.split: '', :skip-empty + { + ASCII-MIN le $_ le ASCII-MAX + or error( qq["$_" (chr { .ord.base( 16 ) }) is not a printable ] ~ + 'ASCII character' ); + } + + qq[Input: \$str = "$str"].put; + + my UInt $score = find-string-score( $str ); + + "Output: $score".put; +} + +#=============================================================================== +multi sub MAIN() # No input: run the test suite +#=============================================================================== +{ + run-tests(); +} + +#------------------------------------------------------------------------------- +sub find-string-score( Str:D $str --> UInt:D ) +#------------------------------------------------------------------------------- +{ + my UInt @ascii = $str.split( '', :skip-empty ).map: { .ord }; + my UInt $score = 0; + + for 0 .. @ascii.end - 1 -> UInt $i + { + $score += ( @ascii[ $i ] - @ascii[ $i + 1 ] ).abs; + } + + return $score; +} + +#------------------------------------------------------------------------------- +sub run-tests() +#------------------------------------------------------------------------------- +{ + 'Running the test suite'.put; + + for test-data.lines -> Str $line + { + my Str ($test-name, $str, $expected) = $line.split: / \| /; + + for $test-name, $str, $expected + { + s/ ^ \s+ //; + s/ \s+ $ //; + } + + my UInt $score = find-string-score( $str ); + + is $score, $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|hello|13 + Example 2|perl |30 + Example 3|raku |37 + END +} + +################################################################################ |
