aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPerlMonk-Athanasius <PerlMonk.Athanasius@gmail.com>2025-07-29 18:05:32 +1000
committerPerlMonk-Athanasius <PerlMonk.Athanasius@gmail.com>2025-07-29 18:05:32 +1000
commit1ac59ef78e959c4a87834a149b4a071de4a56cee (patch)
tree73ab758ccf115129b4faf77a1b774c7586bc1e7a
parent1ff2c9796a511d63231d3757acb27e4046a91fb2 (diff)
downloadperlweeklychallenge-club-1ac59ef78e959c4a87834a149b4a071de4a56cee.tar.gz
perlweeklychallenge-club-1ac59ef78e959c4a87834a149b4a071de4a56cee.tar.bz2
perlweeklychallenge-club-1ac59ef78e959c4a87834a149b4a071de4a56cee.zip
Perl & Raku solutions to Tasks 1 & 2 for Week 332
-rw-r--r--challenge-332/athanasius/perl/ch-1.pl189
-rw-r--r--challenge-332/athanasius/perl/ch-2.pl178
-rw-r--r--challenge-332/athanasius/raku/ch-1.raku189
-rw-r--r--challenge-332/athanasius/raku/ch-2.raku165
4 files changed, 721 insertions, 0 deletions
diff --git a/challenge-332/athanasius/perl/ch-1.pl b/challenge-332/athanasius/perl/ch-1.pl
new file mode 100644
index 0000000000..8d9a85b77d
--- /dev/null
+++ b/challenge-332/athanasius/perl/ch-1.pl
@@ -0,0 +1,189 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 332
+=========================
+
+TASK #1
+-------
+*Binary Date*
+
+Submitted by: Mohammad Sajid Anwar
+
+You are given a date in the format YYYY-MM-DD.
+
+Write a script to convert it into binary date.
+
+Example 1
+
+ Input: $date = "2025-07-26"
+ Output: "11111101001-111-11010"
+
+Example 2
+
+ Input: $date = "2000-02-02"
+ Output: "11111010000-10-10"
+
+Example 3
+
+ Input: $date = "2024-12-31"
+ Output: "11111101000-1100-11111"
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2025 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=comment
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. A valid date in the format "YYYY-MM-DD" is entered on the command-line.
+
+Assumption
+----------
+Dates must be valid.
+
+=cut
+#===============================================================================
+
+use v5.32; # Enables strictures
+use warnings;
+use Const::Fast;
+use DateTime;
+use Devel::Assert qw( on );
+use Test::More;
+use Try::Tiny;
+
+const my $DATE_RE => qr/ ^ (\d{4}) \- (\d\d) \- (\d\d) $ /x;
+const my $USAGE => <<END;
+Usage:
+ perl $0 <date>
+ perl $0
+
+ <date> A valid date in the format "YYYY-MM-DD"
+END
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 332, Task #1: Binary Date (Perl)\n\n";
+}
+
+#===============================================================================
+MAIN:
+#===============================================================================
+{
+ my $argc = scalar @ARGV;
+
+ if ($argc == 0)
+ {
+ run_tests();
+ }
+ elsif ($argc == 1)
+ {
+ my $date = $ARGV[ 0 ];
+
+ date_is_valid( $date ) or error( 'Invalid date' );
+
+ print qq[Input: \$date = "$date"\n];
+
+ my $bin_date = find_binary_date( $date );
+
+ print qq[Output: "$bin_date"\n];
+ }
+ else
+ {
+ error( "Expected 1 or 0 command-line arguments, found $argc" );
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub find_binary_date
+#-------------------------------------------------------------------------------
+{
+ my ($date) = @_;
+
+ assert date_is_valid( $date );
+
+ $date =~ $DATE_RE;
+
+ my $bin_year = sprintf '%b', $1;
+ my $bin_month = sprintf '%b', $2;
+ my $bin_day = sprintf '%b', $3;
+
+ return "$bin_year-$bin_month-$bin_day";
+}
+
+#-------------------------------------------------------------------------------
+sub date_is_valid # Returns a boolean value
+#-------------------------------------------------------------------------------
+{
+ my ($date) = @_;
+ my $result = '';
+
+ if ($date =~ $DATE_RE)
+ {
+ $result = 1;
+
+ try
+ {
+ DateTime->new( year => $1, month => $2, day => $3 );
+ }
+ catch
+ {
+ $result = '';
+ }
+ }
+
+ return $result;
+}
+
+#-------------------------------------------------------------------------------
+sub run_tests
+#-------------------------------------------------------------------------------
+{
+ print "Running the test suite\n";
+
+ while (my $line = <DATA>)
+ {
+ chomp $line;
+
+ my ($test_name, $date, $expected) = split / \| /x, $line;
+
+ for ($test_name, $date, $expected)
+ {
+ s/ ^ \s+ //x;
+ s/ \s+ $ //x;
+ }
+
+ my $bin_date = find_binary_date( $date );
+
+ is $bin_date, $expected, $test_name;
+ }
+
+ done_testing;
+}
+
+#-------------------------------------------------------------------------------
+sub error
+#-------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+################################################################################
+
+__DATA__
+Example 1|2025-07-26|11111101001-111-11010
+Example 2|2000-02-02|11111010000-10-10
+Example 3|2024-12-31|11111101000-1100-11111
diff --git a/challenge-332/athanasius/perl/ch-2.pl b/challenge-332/athanasius/perl/ch-2.pl
new file mode 100644
index 0000000000..02813904db
--- /dev/null
+++ b/challenge-332/athanasius/perl/ch-2.pl
@@ -0,0 +1,178 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 332
+=========================
+
+TASK #2
+-------
+*Odd Letters*
+
+Submitted by: Mohammad Sajid Anwar
+
+You are given a string.
+
+Write a script to find out if each letter in the given string appeared odd
+number of times.
+
+Example 1
+
+ Input: $str = "weekly"
+ Output: false
+
+ w: 1 time
+ e: 2 times
+ k: 1 time
+ l: 1 time
+ y: 1 time
+
+ The letter 'e' appeared 2 times i.e. even.
+
+Example 2
+
+ Input: $str = "perl"
+ Output: true
+
+Example 3
+
+ Input: $source = "challenge"
+ Output: false
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2025 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=comment
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. A string is entered on the command-line.
+
+Assumptions
+-----------
+1. Non-letter characters in the string are ignored.
+2. The identification of a letter is not case-sensitive; so, e.g., 'a' and 'A'
+ are considered the same letter.
+
+=cut
+#===============================================================================
+
+use v5.32; # Enables strictures
+use warnings;
+use Const::Fast;
+use Devel::Assert qw( on );
+use Test::More;
+
+const my $USAGE => <<END;
+Usage:
+ perl $0 <str>
+ perl $0
+
+ <str> A string
+END
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 332, Task #2: Odd Letters (Perl)\n\n";
+}
+
+#===============================================================================
+MAIN:
+#===============================================================================
+{
+ my $argc = scalar @ARGV;
+
+ if ($argc == 0)
+ {
+ run_tests();
+ }
+ elsif ($argc == 1)
+ {
+ my ($str) = @ARGV;
+
+ print qq[Input: \$str = "$str"\n];
+
+ my $all_odd = all_letters_odd( $str );
+
+ printf "Output: %s\n", $all_odd ? 'true' : 'false';
+ }
+ else
+ {
+ error( "Expected 1 or 0 command-line arguments, found $argc" );
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub all_letters_odd
+#-------------------------------------------------------------------------------
+{
+ my ($str) = @_;
+ my @chars = split //, $str;
+ my %dict;
+
+ for my $char (@chars)
+ {
+ ++$dict{ lc $char } if $char =~ / ^ [A-Za-z] $ /x;
+ }
+
+ for my $val (values %dict)
+ {
+ return '' if $val % 2 == 0;
+ }
+
+ return 1;
+}
+
+#-------------------------------------------------------------------------------
+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;
+ }
+
+ my $all_odd = all_letters_odd( $str ) ? 'true' : 'false';
+
+ is $all_odd, $expected, $test_name;
+ }
+
+ done_testing;
+}
+
+#-------------------------------------------------------------------------------
+sub error
+#-------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+################################################################################
+
+__DATA__
+Example 1 |weekly |false
+Example 2 |perl |true
+Example 3 |challenge|false
+Mixed case 1|Test1 |false
+Mixed case 2|**ee4E%% |true
diff --git a/challenge-332/athanasius/raku/ch-1.raku b/challenge-332/athanasius/raku/ch-1.raku
new file mode 100644
index 0000000000..3f5fd7448a
--- /dev/null
+++ b/challenge-332/athanasius/raku/ch-1.raku
@@ -0,0 +1,189 @@
+use v6d;
+
+################################################################################
+=begin comment
+
+Perl Weekly Challenge 332
+=========================
+
+TASK #1
+-------
+*Binary Date*
+
+Submitted by: Mohammad Sajid Anwar
+
+You are given a date in the format YYYY-MM-DD.
+
+Write a script to convert it into binary date.
+
+Example 1
+
+ Input: $date = "2025-07-26"
+ Output: "11111101001-111-11010"
+
+Example 2
+
+ Input: $date = "2000-02-02"
+ Output: "11111010000-10-10"
+
+Example 3
+
+ Input: $date = "2024-12-31"
+ Output: "11111101000-1100-11111"
+
+=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 valid date in the format "YYYY-MM-DD" is entered on the command-line.
+
+Assumption
+----------
+Dates must be valid.
+
+=end comment
+#===============================================================================
+
+use Test;
+
+my regex Date { ^ (\d**4) \- (\d\d) \- (\d\d) $ };
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ "\nChallenge 332, Task #1: Binary Date (Raku)\n".put;
+}
+
+#===============================================================================
+multi sub MAIN
+(
+ Str:D $date where m/ <Date> / #= A valid date in the format "YYYY-MM-DD"
+)
+#===============================================================================
+{
+ my Str $msg = date-is-valid( $date );
+ $msg and error( "Invalid date: $msg" );
+
+ qq[Input: \$date = "$date"].put;
+
+ my Str $bin-date = find-binary-date( $date );
+
+ qq[Output: "$bin-date"].put;
+}
+
+#===============================================================================
+multi sub MAIN() # No input: run the test suite
+#===============================================================================
+{
+ run-tests();
+}
+
+#-------------------------------------------------------------------------------
+sub find-binary-date( Str:D $str where m/ <date=Date> / --> Str:D )
+#-------------------------------------------------------------------------------
+{
+ my Str $msg = date-is-valid( $str );
+ $msg and die( "Invalid date: $msg" );
+
+ my Str $bin-year = $<date>[ 0 ].Int.base( 2 );
+ my Str $bin-month = $<date>[ 1 ].Int.base( 2 );
+ my Str $bin-day = $<date>[ 2 ].Int.base( 2 );
+
+ return $bin-year ~ '-' ~ $bin-month ~ '-' ~ $bin-day;
+}
+
+#-------------------------------------------------------------------------------
+sub date-is-valid
+(
+ Str:D $date
+--> Str:D #= Returns the empty string if the date is valid;
+ #= otherwise, returns an error message
+)
+#-------------------------------------------------------------------------------
+{
+ my Str $result = '';
+
+ try
+ {
+ CATCH
+ {
+ when X::Temporal
+ {
+ $result = .message;
+ }
+ }
+
+ Date.new: $date;
+ }
+
+ return $result;
+}
+
+#-------------------------------------------------------------------------------
+sub run-tests()
+#-------------------------------------------------------------------------------
+{
+ 'Running the test suite'.put;
+
+ for test-data.lines -> Str $line
+ {
+ my Str ($test-name, $date, $expected) = $line.split: / \| /;
+
+ for $test-name, $date, $expected
+ {
+ s/ ^ \s+ //;
+ s/ \s+ $ //;
+ }
+
+ my Str $bin-date = find-binary-date( $date );
+
+ is $bin-date, $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|2025-07-26|11111101001-111-11010
+ Example 2|2000-02-02|11111010000-10-10
+ Example 3|2024-12-31|11111101000-1100-11111
+ END
+}
+
+################################################################################
diff --git a/challenge-332/athanasius/raku/ch-2.raku b/challenge-332/athanasius/raku/ch-2.raku
new file mode 100644
index 0000000000..a35248cd92
--- /dev/null
+++ b/challenge-332/athanasius/raku/ch-2.raku
@@ -0,0 +1,165 @@
+use v6d;
+
+################################################################################
+=begin comment
+
+Perl Weekly Challenge 332
+=========================
+
+TASK #2
+-------
+*Odd Letters*
+
+Submitted by: Mohammad Sajid Anwar
+
+You are given a string.
+
+Write a script to find out if each letter in the given string appeared odd
+number of times.
+
+Example 1
+
+ Input: $str = "weekly"
+ Output: false
+
+ w: 1 time
+ e: 2 times
+ k: 1 time
+ l: 1 time
+ y: 1 time
+
+ The letter 'e' appeared 2 times i.e. even.
+
+Example 2
+
+ Input: $str = "perl"
+ Output: true
+
+Example 3
+
+ Input: $source = "challenge"
+ Output: false
+
+=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 string is entered on the command-line.
+
+Assumptions
+-----------
+1. Non-letter characters in the string are ignored.
+2. The identification of a letter is not case-sensitive; so, e.g., 'a' and 'A'
+ are considered the same letter.
+
+=end comment
+#===============================================================================
+
+use Test;
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ "\nChallenge 332, Task #2: Odd Letters (Raku)\n".put;
+}
+
+#===============================================================================
+multi sub MAIN
+(
+ Str:D $str #= A string
+)
+#===============================================================================
+{
+ qq[Input: \$str = "$str"].put;
+
+ my Bool $all-odd = all-letters-odd( $str );
+
+ "Output: %s\n".printf: $all-odd ?? 'true' !! 'false';
+}
+
+#===============================================================================
+multi sub MAIN() # No input: run the test suite
+#===============================================================================
+{
+ run-tests();
+}
+
+#-------------------------------------------------------------------------------
+sub all-letters-odd( Str:D $str --> Bool:D )
+#-------------------------------------------------------------------------------
+{
+ my UInt %dict;
+ my Str @chars = $str.split: '', :skip-empty;
+
+ for @chars -> Str $char
+ {
+ ++%dict{ $char.lc } if $char ~~ / ^ <[ A..Z a..z ]> $ /;
+ }
+
+ for %dict.values -> UInt $val
+ {
+ return False if $val %% 2;
+ }
+
+ return True;
+}
+
+#-------------------------------------------------------------------------------
+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 Str $all-odd = all-letters-odd( $str ) ?? 'true' !! 'false';
+
+ is $all-odd, $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 |weekly |false
+ Example 2 |perl |true
+ Example 3 |challenge|false
+ Mixed case 1|Test1 |false
+ Mixed case 2|**ee4E%% |true
+ END
+}
+
+################################################################################