aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPerlMonk-Athanasius <PerlMonk.Athanasius@gmail.com>2022-10-16 17:13:05 +1000
committerPerlMonk-Athanasius <PerlMonk.Athanasius@gmail.com>2022-10-16 17:13:05 +1000
commita78d93215d7cc179472eccbbe1f2d8839d5daf7a (patch)
tree9fa37e641f8e277b4e51a6a7dbfda515a2ae0e55
parent12cd1a84754b7826172d0f94217e72ea766d6f6d (diff)
downloadperlweeklychallenge-club-a78d93215d7cc179472eccbbe1f2d8839d5daf7a.tar.gz
perlweeklychallenge-club-a78d93215d7cc179472eccbbe1f2d8839d5daf7a.tar.bz2
perlweeklychallenge-club-a78d93215d7cc179472eccbbe1f2d8839d5daf7a.zip
Perl & Raku solutions to Tasks 1 & 2 for Week 186
-rw-r--r--challenge-186/athanasius/perl/ch-1.pl157
-rw-r--r--challenge-186/athanasius/perl/ch-2.pl271
-rw-r--r--challenge-186/athanasius/raku/ch-1.raku142
-rw-r--r--challenge-186/athanasius/raku/ch-2.raku270
4 files changed, 840 insertions, 0 deletions
diff --git a/challenge-186/athanasius/perl/ch-1.pl b/challenge-186/athanasius/perl/ch-1.pl
new file mode 100644
index 0000000000..e83bfd4a23
--- /dev/null
+++ b/challenge-186/athanasius/perl/ch-1.pl
@@ -0,0 +1,157 @@
+#!perl
+
+###############################################################################
+=comment
+
+Perl Weekly Challenge 186
+=========================
+
+TASK #1
+-------
+*Zip List*
+
+Submitted by: Mohammad S Anwar
+
+You are given two list @a and @b of same size.
+
+Create a subroutine sub zip(@a, @b) that merge the two list as shown in the
+example below.
+
+Example
+
+ Input: @a = qw/1 2 3/; @b = qw/a b c/;
+ Output: zip(@a, @b) should return qw/1 a 2 b 3 c/;
+ zip(@b, @a) should return qw/a 1 b 2 c 3/;
+
+=cut
+###############################################################################
+
+#--------------------------------------#
+# Copyright © 2022 PerlMonk Athanasius #
+#--------------------------------------#
+
+#==============================================================================
+=comment
+
+Interface
+---------
+If no arguments are given on the command-line, the test suite is run.
+
+=cut
+#==============================================================================
+
+use strict;
+use warnings;
+use Const::Fast;
+use Test::More;
+
+const my $TEST_FIELDS => 4;
+const my $USAGE =>
+"Usage:
+ perl $0 <a> <b>
+ perl $0
+
+ <a> String representing \@a, with list elements separated by whitespace
+ <b> String representing \@b, with list elements separated by whitespace
+";
+
+#------------------------------------------------------------------------------
+BEGIN
+#------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 186, Task #1: Zip List (Perl)\n\n";
+}
+
+#==============================================================================
+MAIN:
+#==============================================================================
+{
+ my $args = scalar @ARGV;
+
+ if ($args == 0)
+ {
+ run_tests();
+ }
+ elsif ($args == 2)
+ {
+ my ($a_ref, $b_ref) = parse_command_line();
+
+ printf "Input: \@a = (%s); \@b = (%s)\n",
+ join( ', ', @$a_ref ), join( ', ', @$b_ref );
+
+ printf "Output: zip(\@a, \@b) = (%s)\n",
+ join ', ', @{ zip( $a_ref, $b_ref ) };
+ }
+ else
+ {
+ error( "Expected 0 or 2 command-line arguments, found $args" );
+ }
+}
+
+#------------------------------------------------------------------------------
+sub zip
+#------------------------------------------------------------------------------
+{
+ my ($a_ref, $b_ref) = @_;
+ my @zipped;
+
+ for my $i (0 .. $#$a_ref)
+ {
+ push @zipped, $a_ref->[ $i ], $b_ref->[ $i ];
+ }
+
+ return \@zipped;
+}
+
+#------------------------------------------------------------------------------
+sub parse_command_line
+#------------------------------------------------------------------------------
+{
+ my @a = split /\s+/, $ARGV[ 0 ];
+ my @b = split /\s+/, $ARGV[ 1 ];
+
+ scalar @a == scalar @b
+ or error( 'The lists must be the same size' );
+
+ return (\@a, \@b);
+}
+
+#------------------------------------------------------------------------------
+sub error
+#------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+#------------------------------------------------------------------------------
+sub run_tests
+#------------------------------------------------------------------------------
+{
+ print "Running the test suite\n";
+
+ while (my $line = <DATA>)
+ {
+ chomp $line;
+
+ my ($name, $in1, $in2, $exp)
+ = split / , \s* /x, $line, $TEST_FIELDS;
+ my @a = split /\s+/, $in1;
+ my @b = split /\s+/, $in2;
+ my $out = join ' ', @{ zip( \@a, \@b ) };
+
+ is $out, $exp, $name;
+ }
+
+ done_testing;
+}
+
+###############################################################################
+
+__DATA__
+Example 1, 1 2 3, a b c, 1 a 2 b 3 c
+Example 2, a b c, 1 2 3, a 1 b 2 c 3
+Odd/even, 1 3 5 7 9, 2 4 6 8 10, 1 2 3 4 5 6 7 8 9 10
+Sentence, There's than way do, more 1 to it, There's more than 1 way to do it
diff --git a/challenge-186/athanasius/perl/ch-2.pl b/challenge-186/athanasius/perl/ch-2.pl
new file mode 100644
index 0000000000..2d0fc5d94a
--- /dev/null
+++ b/challenge-186/athanasius/perl/ch-2.pl
@@ -0,0 +1,271 @@
+#!perl
+
+###############################################################################
+=comment
+
+Perl Weekly Challenge 186
+=========================
+
+TASK #2
+-------
+*Unicode Makeover*
+
+Submitted by: Mohammad S Anwar
+
+You are given a string with possible unicode characters.
+
+Create a subroutine sub makeover($str) that replace the unicode characters with
+ascii equivalent. For this task, let us assume it only contains alphabets.
+
+Example 1
+
+ Input: $str = 'ÃÊÍÒÙ';
+ Output: 'AEIOU'
+
+Example 2
+
+ Input: $str = 'âÊíÒÙ';
+ Output: 'aEiOU'
+
+=cut
+###############################################################################
+
+#--------------------------------------#
+# Copyright © 2022 PerlMonk Athanasius #
+#--------------------------------------#
+
+#==============================================================================
+=comment
+
+Interface
+---------
+If no arguments are given on the command-line, the test suite is run.
+
+Unicode Characters
+------------------
+Characters to be replaced are drawn from the following Unicode blocks:
+ Basic Latin ($),
+ Latin-1 Supplement (¢, À, Á, ...)
+ Latin Extended-A (Ā, ā, Ă, ...)
+ Latin Extended-B (ƀ, Ɓ, Ƃ, ...)
+ IPA Extensions (ɛ, ɔ)
+ Latin Extended Additional (Ḁ, ḁ, Ḃ, ...)
+ Letterlike Symbols (ℂ, ℍ, ℎ, ...).
+
+In many cases, the identification of equivalent characters is straightforward;
+for example, Unicode character U+00C0, named "Latin Capital Letter A with
+grave," obviously has ASCII capital A as its equivalent. In other cases,
+identification of "equivalent" characters is based on my subjective judgment.
+
+For my convenience, Unicode characters which do not display in the DejaVu Sans
+Mono font have been excluded.
+
+Algorithm
+---------
+The hash %ASCII_2_UNICODE maps ASCII characters to their Unicode equivalents.
+This presents the required data in a convenient form. The create_lookup() sub-
+routine reverses this hash to create the hash %UNICODE_2_ASCII, which maps
+Unicode characters to their ASCII equivalents. This is the lookup table used in
+making the required replacements.
+
+Any character not entered in the lookup table is simply left unchanged in the
+output string.
+
+=cut
+#==============================================================================
+
+use strict;
+use warnings;
+use utf8;
+use Const::Fast;
+use Test::More;
+
+const my %ASCII_2_UNICODE =>
+(
+ A => [ qw( À Á Â Ã Ä Å Ā Ă Ą Ǎ Ǟ Ǡ Ȁ Ȃ Ȧ Ⱥ Ḁ ) ],
+ AE => [ qw( Æ Ǣ Ǽ ) ],
+ B => [ qw( Ɓ Ƃ Ƀ Ḃ Ḅ ) ],
+ C => [ qw( Ç Ć Ĉ Ċ Č Ƈ Ȼ ℂ ) ],
+ D => [ qw( Ð Ď Đ Ɖ Ɗ Ƌ ) ],
+ E => [ qw( È É Ê Ë Ē Ĕ Ė Ę Ě Ȅ Ȇ Ȩ ) ],
+ F => [ qw( Ƒ ) ],
+ G => [ qw( Ĝ Ğ Ġ Ģ Ɠ Ǧ Ǵ ) ],
+ H => [ qw( Ĥ Ħ Ȟ ℍ ) ],
+ I => [ qw( Ì Í Î Ï Ĩ Ī Ĭ Į İ Ɩ Ɨ Ǐ Ȉ Ȋ ) ],
+ IJ => [ qw( IJ ) ],
+ J => [ qw( Ĵ ) ],
+ K => [ qw( Ķ Ƙ Ǩ ) ],
+ L => [ qw( £ Ĺ Ļ Ľ Ŀ Ł Ƚ ) ],
+ N => [ qw( Ñ Ń Ņ Ň Ɲ Ǹ Ƞ ℕ ) ],
+ No => [ qw( № ) ],
+ NG => [ qw( Ŋ ) ],
+ O => [ qw( Ò Ó Ô Õ Ö Ø Ō Ŏ Ő Ɵ Ơ Ǒ Ǫ Ǭ Ǿ Ȍ Ȏ Ȫ Ȭ Ȯ Ȱ ) ],
+ OE => [ qw( Œ ) ],
+ P => [ qw( Ƥ ℙ ) ],
+ Q => [ qw( ℚ ) ],
+ R => [ qw( Ŕ Ŗ Ř Ȑ Ɍ ℝ ) ],
+ S => [ qw( $ Ś Ŝ Ş Š Ș ) ],
+ T => [ qw( Ţ Ť Ŧ Ƭ Ʈ Ț Ⱦ ) ],
+ TH => [ qw( Þ ) ],
+ U => [ qw( Ù Ú Û Ü Ũ Ū Ŭ Ů Ű Ų Ư Ǔ Ǘ Ǚ Ǜ Ȕ Ȗ Ʉ ) ],
+ V => [ qw( Ʋ ) ],
+ W => [ qw( Ŵ ) ],
+ Y => [ qw( ¥ Ý Ŷ Ÿ Ƴ Ȳ ) ],
+ Z => [ qw( Ź Ż Ž Ƶ Ʒ Ǯ Ȥ ℤ ) ],
+ a => [ qw( à á â ã ä å ā ă ą ǎ ǟ ǡ ȁ ȃ ȧ ḁ ) ],
+ ae => [ qw( æ ǣ ǽ ) ],
+ b => [ qw( ƀ ƃ ḃ ) ],
+ c => [ qw( ¢ ç ć ĉ ċ č ƈ ȼ ) ],
+ d => [ qw( ð ď đ ƌ ȡ ) ],
+ e => [ qw( è é ê ë ē ĕ ė ę ě ȅ ȇ ȩ ℮ ɛ ) ],
+ f => [ qw( ƒ ) ],
+ g => [ qw( ĝ ğ ġ ģ ǧ ǵ ) ],
+ h => [ qw( ĥ ħ ȟ ℎ ℏ ) ],
+ i => [ qw( ì í î ï ĩ ī ĭ į ı ǐ ȉ ȋ ) ],
+ ij => [ qw( ij ) ],
+ j => [ qw( ĵ ǰ ȷ ) ],
+ k => [ qw( ķ ĸ ƙ ǩ ) ],
+ l => [ qw( ĺ ļ ľ ŀ ł ƚ ȴ ) ],
+ n => [ qw( ñ ń ņ ň ʼn ƞ ǹ ȵ ) ],
+ ng => [ qw( ŋ ) ],
+ o => [ qw( ò ó ô õ ö ø ō ŏ ő ơ ǒ ǫ ǭ ǿ ȍ ȏ ȫ ȭ ȯ ȱ ɔ ) ],
+ oe => [ qw( œ ) ],
+ p => [ qw( ƥ ) ],
+ r => [ qw( ŕ ŗ ř ȑ ɍ ) ],
+ s => [ qw( ś ŝ ş š ſ ș ȿ ) ],
+ ss => [ qw( ß ) ],
+ t => [ qw( ţ ť ŧ ƫ ƭ ț ȶ ) ],
+ th => [ qw( þ ) ],
+ u => [ qw( ù ú û ü ũ ū ŭ ů ű ų ư ǔ ǘ ǚ ǜ ȕ ȗ ) ],
+ w => [ qw( ŵ ƿ ) ],
+ y => [ qw( ý ÿ ŷ ƴ ȳ ) ],
+ z => [ qw( ź ż ž ƶ ƺ ǯ ȥ ɀ ) ],
+);
+
+const my $TEST_FIELDS => 3;
+const my $USAGE =>
+"Usage:
+ perl $0 <str>
+ perl $0
+
+ <str> A Unicode string\n";
+
+my %UNICODE_2_ASCII;
+
+#------------------------------------------------------------------------------
+BEGIN
+#------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 186, Task #2: Unicode Makeover (Perl)\n\n";
+}
+
+#==============================================================================
+MAIN:
+#==============================================================================
+{
+ my $args = scalar @ARGV;
+
+ if ($args == 0)
+ {
+ create_lookup();
+ run_tests();
+ }
+ elsif ($args == 1)
+ {
+ create_lookup();
+
+ my $str = $ARGV[ 0 ];
+
+ print "Input: \$str = '$str'\n";
+
+ my $out = makeover( $str );
+
+ print "Output: '$out'\n";
+ }
+ else
+ {
+ error( "Expected 0 or 1 arguments, found $args" );
+ }
+}
+
+#------------------------------------------------------------------------------
+sub makeover
+#------------------------------------------------------------------------------
+{
+ my ($str) = @_;
+ my $plain;
+
+ for my $char (split //, $str)
+ {
+ if (exists $UNICODE_2_ASCII{ $char })
+ {
+ $plain .= $UNICODE_2_ASCII{ $char };
+ }
+ else
+ {
+ $plain .= $char;
+ }
+ }
+
+ return $plain;
+}
+
+#------------------------------------------------------------------------------
+sub create_lookup
+#------------------------------------------------------------------------------
+{
+ for my $key (keys %ASCII_2_UNICODE)
+ {
+ for my $val (@{ $ASCII_2_UNICODE{ $key } })
+ {
+ $UNICODE_2_ASCII{ $val } = $key;
+ }
+ }
+}
+
+#------------------------------------------------------------------------------
+sub error
+#------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+#------------------------------------------------------------------------------
+sub run_tests
+#------------------------------------------------------------------------------
+{
+ print "Running the test suite\n";
+
+ while (my $line = <DATA>)
+ {
+ chomp $line;
+
+ my ($name, $in, $exp) = split / , \s* /x, $line, $TEST_FIELDS;
+
+ my $out = makeover( $in );
+
+ is $out, $exp, $name;
+ }
+
+ done_testing;
+}
+
+###############################################################################
+
+__DATA__
+Example 1, ÃÊÍÒÙ, AEIOU
+Example 2, âÊíÒÙ, aEiOU
+Finnish, En ymmärrä, En ymmarra
+French 1, Combien ça coûte?, Combien ca coute?
+French 2, Théâtralité évêché éphémère, Theatralite eveche ephemere
+German, Wie heißt du?, Wie heisst du?
+Icelandic, Góðan daginn, Godan daginn
+Letter o, òóôõöøōŏőơǒǫǭǿȍȏȫȭȯȱɔ, ooooooooooooooooooooo
+Acute capitals, ÁǼĆÉǴÍĹŃÓŔŚÚÝŹ, AAECEGILNORSUYZ
+Circumflex small, âĉêĝîĵôŝûŵŷ, acegijosuwy
+Double capitals, ÆIJ№ŊŒÞ, AEIJNoNGOETH
+Yours truly, ℙėŗŀMȯƞķ Ąþåñąſïůș, PerlMonk Athanasius
+Krio, Jɔs wan ɔda hakɛr, Jos wan oda haker
diff --git a/challenge-186/athanasius/raku/ch-1.raku b/challenge-186/athanasius/raku/ch-1.raku
new file mode 100644
index 0000000000..b41e539e6d
--- /dev/null
+++ b/challenge-186/athanasius/raku/ch-1.raku
@@ -0,0 +1,142 @@
+use v6d;
+
+###############################################################################
+=begin comment
+
+Perl Weekly Challenge 186
+=========================
+
+TASK #1
+-------
+*Zip List*
+
+Submitted by: Mohammad S Anwar
+
+You are given two list @a and @b of same size.
+
+Create a subroutine sub zip(@a, @b) that merge the two list as shown in the
+example below.
+
+Example
+
+ Input: @a = qw/1 2 3/; @b = qw/a b c/;
+ Output: zip(@a, @b) should return qw/1 a 2 b 3 c/;
+ zip(@b, @a) should return qw/a 1 b 2 c 3/;
+
+=end comment
+###############################################################################
+
+#--------------------------------------#
+# Copyright © 2022 PerlMonk Athanasius #
+#--------------------------------------#
+
+#==============================================================================
+=begin comment
+
+Interface
+---------
+If no arguments are given on the command-line, the test suite is run.
+
+=end comment
+#==============================================================================
+
+use Test;
+
+my UInt constant $TEST-FIELDS = 4;
+
+#------------------------------------------------------------------------------
+BEGIN
+#------------------------------------------------------------------------------
+{
+ "\nChallenge 186, Task #1: Zip List (Raku)\n".put;
+}
+
+#==============================================================================
+multi sub MAIN
+(
+ #| String representing @a, with list elements separated by whitespace
+ Str:D $a,
+
+ #| String representing @b, with list elements separated by whitespace
+ Str:D $b
+)
+#==============================================================================
+{
+ my Str @a = $a.split: / \s+ /, :skip-empty;
+ my Str @b = $b.split: / \s+ /, :skip-empty;
+
+ "Input: @a = (%s); @b = (%s)\n".printf: @a.join( ', ' ), @b.join( ', ' );
+
+ "Output: zip(@a, @b) = (%s)\n".printf: zip( @a, @b ).join: ', ';
+}
+
+#==============================================================================
+multi sub MAIN() # Run the test suite
+#==============================================================================
+{
+ 'Running the test suite'.put;
+
+ for test-data.lines -> Str $line
+ {
+ my Str ($name, $in1, $in2, $exp) =
+ $line.split: / \, \s* /, $TEST-FIELDS, :skip-empty;
+
+ my Str @a = $in1.split: / \s+ /, :skip-empty;
+ my Str @b = $in2.split: / \s+ /, :skip-empty;
+ my Str $out = zip( @a, @b ).join: ' ';
+
+ is $out, $exp, $name;
+ }
+
+ done-testing;
+}
+
+#------------------------------------------------------------------------------
+sub zip( List:D[Str:D] $a, List:D[Str:D] $b --> List:D[Str:D] )
+#------------------------------------------------------------------------------
+{
+ my Str @zipped;
+
+ for 0 .. $a.end -> UInt $i
+ {
+ @zipped.push: $a[ $i ], $b[ $i ];
+ }
+
+ return @zipped;
+}
+
+#------------------------------------------------------------------------------
+sub test-data()
+#------------------------------------------------------------------------------
+{
+ return q:to/END/;
+Example 1, 1 2 3, a b c, 1 a 2 b 3 c
+Example 2, a b c, 1 2 3, a 1 b 2 c 3
+Odd/even, 1 3 5 7 9, 2 4 6 8 10, 1 2 3 4 5 6 7 8 9 10
+Sentence, There's than way do, more 1 to it, There's more than 1 way to do it
+END
+}
+
+#------------------------------------------------------------------------------
+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;
+}
+
+###############################################################################
diff --git a/challenge-186/athanasius/raku/ch-2.raku b/challenge-186/athanasius/raku/ch-2.raku
new file mode 100644
index 0000000000..d84862850d
--- /dev/null
+++ b/challenge-186/athanasius/raku/ch-2.raku
@@ -0,0 +1,270 @@
+use v6d;
+
+###############################################################################
+=begin comment
+
+Perl Weekly Challenge 186
+=========================
+
+TASK #2
+-------
+*Unicode Makeover*
+
+Submitted by: Mohammad S Anwar
+
+You are given a string with possible unicode characters.
+
+Create a subroutine sub makeover($str) that replace the unicode characters with
+ascii equivalent. For this task, let us assume it only contains alphabets.
+
+Example 1
+
+ Input: $str = 'ÃÊÍÒÙ';
+ Output: 'AEIOU'
+
+Example 2
+
+ Input: $str = 'âÊíÒÙ';
+ Output: 'aEiOU'
+
+=end comment
+###############################################################################
+
+#--------------------------------------#
+# Copyright © 2022 PerlMonk Athanasius #
+#--------------------------------------#
+
+#==============================================================================
+=begin comment
+
+Interface
+---------
+If no arguments are given on the command-line, the test suite is run.
+
+Unicode Characters
+------------------
+Characters to be replaced are drawn from the following Unicode blocks:
+ Basic Latin ($),
+ Latin-1 Supplement (¢, À, Á, ...)
+ Latin Extended-A (Ā, ā, Ă, ...)
+ Latin Extended-B (ƀ, Ɓ, Ƃ, ...)
+ IPA Extensions (ɛ, ɔ)
+ Latin Extended Additional (Ḁ, ḁ, Ḃ, ...)
+ Letterlike Symbols (ℂ, ℍ, ℎ, ...).
+
+In many cases, the identification of equivalent characters is straightforward;
+for example, Unicode character U+00C0, named "Latin Capital Letter A with
+grave," obviously has ASCII capital A as its equivalent. In other cases,
+identification of "equivalent" characters is based on my subjective judgment.
+
+For my convenience, Unicode characters which do not display in the DejaVu Sans
+Mono font have been excluded.
+
+Algorithm
+---------
+The hash %ASCII-TO-UNICODE maps ASCII characters to their Unicode equivalents.
+This presents the required data in a convenient form. The create-lookup() sub-
+routine reverses this hash to create the hash %UNICODE-TO-ASCII, which maps
+Unicode characters to their ASCII equivalents. This is the lookup table used in
+making the required replacements.
+
+Any character not entered in the lookup table is simply left unchanged in the
+output string.
+
+=end comment
+#==============================================================================
+
+use Test;
+
+my constant %ASCII-TO-UNICODE =
+ A => [ < À Á Â Ã Ä Å Ā Ă Ą Ǎ Ǟ Ǡ Ȁ Ȃ Ȧ Ⱥ Ḁ > ],
+ AE => [ < Æ Ǣ Ǽ > ],
+ A => [ < À Á Â Ã Ä Å Ā Ă Ą Ǎ Ǟ Ǡ Ȁ Ȃ Ȧ Ⱥ Ḁ > ],
+ AE => [ < Æ Ǣ Ǽ > ],
+ B => [ < Ɓ Ƃ Ƀ Ḃ Ḅ > ],
+ C => [ < Ç Ć Ĉ Ċ Č Ƈ Ȼ ℂ > ],
+ D => [ < Ð Ď Đ Ɖ Ɗ Ƌ > ],
+ E => [ < È É Ê Ë Ē Ĕ Ė Ę Ě Ȅ Ȇ Ȩ > ],
+ F => [ < Ƒ > ],
+ G => [ < Ĝ Ğ Ġ Ģ Ɠ Ǧ Ǵ > ],
+ H => [ < Ĥ Ħ Ȟ ℍ > ],
+ I => [ < Ì Í Î Ï Ĩ Ī Ĭ Į İ Ɩ Ɨ Ǐ Ȉ Ȋ > ],
+ IJ => [ < IJ > ],
+ J => [ < Ĵ > ],
+ K => [ < Ķ Ƙ Ǩ > ],
+ L => [ < £ Ĺ Ļ Ľ Ŀ Ł Ƚ > ],
+ N => [ < Ñ Ń Ņ Ň Ɲ Ǹ Ƞ ℕ > ],
+ No => [ < № > ],
+ NG => [ < Ŋ > ],
+ O => [ < Ò Ó Ô Õ Ö Ø Ō Ŏ Ő Ɵ Ơ Ǒ Ǫ Ǭ Ǿ Ȍ Ȏ Ȫ Ȭ Ȯ Ȱ > ],
+ OE => [ < Œ > ],
+ P => [ < Ƥ ℙ > ],
+ Q => [ < ℚ > ],
+ R => [ < Ŕ Ŗ Ř Ȑ Ɍ ℝ > ],
+ S => [ < Ś Ŝ Ş Š Ș > ],
+ T => [ < Ţ Ť Ŧ Ƭ Ʈ Ț Ⱦ > ],
+ TH => [ < Þ > ],
+ U => [ < Ù Ú Û Ü Ũ Ū Ŭ Ů Ű Ų Ư Ǔ Ǘ Ǚ Ǜ Ȕ Ȗ Ʉ > ],
+ V => [ < Ʋ > ],
+ W => [ < Ŵ > ],
+ Y => [ < ¥ Ý Ŷ Ÿ Ƴ Ȳ > ],
+ Z => [ < Ź Ż Ž Ƶ Ʒ Ǯ Ȥ ℤ > ],
+ a => [ < à á â ã ä å ā ă ą ǎ ǟ ǡ ȁ ȃ ȧ ḁ > ],
+ ae => [ < æ ǣ ǽ > ],
+ b => [ < ƀ ƃ ḃ > ],
+ c => [ < ¢ ç ć ĉ ċ č ƈ ȼ > ],
+ d => [ < ð ď đ ƌ ȡ > ],
+ e => [ < è é ê ë ē ĕ ė ę ě ȅ ȇ ȩ ℮ ɛ > ],
+ f => [ < ƒ > ],
+ g => [ < ĝ ğ ġ ģ ǧ ǵ > ],
+ h => [ < ĥ ħ ȟ ℎ ℏ > ],
+ i => [ < ì í î ï ĩ ī ĭ į ı ǐ ȉ ȋ > ],
+ ij => [ < ij > ],
+ j => [ < ĵ ǰ ȷ > ],
+ k => [ < ķ ĸ ƙ ǩ > ],
+ l => [ < ĺ ļ ľ ŀ ł ƚ ȴ > ],
+ n => [ < ñ ń ņ ň ʼn ƞ ǹ ȵ > ],
+ ng => [ < ŋ > ],
+ o => [ < ò ó ô õ ö ø ō ŏ ő ơ ǒ ǫ ǭ ǿ ȍ ȏ ȫ ȭ ȯ ȱ ɔ > ],
+ oe => [ < œ > ],
+ p => [ < ƥ > ],
+ r => [ < ŕ ŗ ř ȑ ɍ > ],
+ s => [ < ś ŝ ş š ſ ș ȿ > ],
+ ss => [ < ß > ],
+ t => [ < ţ ť ŧ ƫ ƭ ț ȶ > ],
+ th => [ < þ > ],
+ u => [ < ù ú û ü ũ ū ŭ ů ű ų ư ǔ ǘ ǚ ǜ ȕ ȗ > ],
+ w => [ < ŵ ƿ > ],
+ y => [ < ý ÿ ŷ ƴ ȳ > ],
+ z => [ < ź ż ž ƶ ƺ ǯ ȥ ɀ > ];
+
+my UInt constant $TEST-FIELDS = 3;
+
+my %UNICODE-TO-ASCII;
+
+#------------------------------------------------------------------------------
+BEGIN
+#------------------------------------------------------------------------------
+{
+ "\nChallenge 186, Task #2: Unicode Makeover (Raku)\n".put;
+}
+
+#==============================================================================
+multi sub MAIN
+(
+ Str:D $str #= A Unicode string
+)
+#==============================================================================
+{
+ my UInt $args = @*ARGS.elems;
+
+ $args == 1 or error( "Expected 0 or 1 arguments, found $args" );
+
+ create-lookup();
+
+ "Input: \$str = '$str'".put;
+
+ my Str $out = makeover( $str );
+
+ "Output: '$out'".put;
+}
+
+#==============================================================================
+multi sub MAIN() # Run the test suite
+#==============================================================================
+{
+ 'Running the test suite'.put;
+
+ create-lookup();
+
+ for test-data.lines -> Str $line
+ {
+ my Str ($name, $in, $exp) =
+ $line.split: / \, \s* /, $TEST-FIELDS, :skip-empty;
+
+ my Str $out = makeover( $in );
+
+ is $out, $exp, $name;
+ }
+
+ done-testing;
+}
+
+#------------------------------------------------------------------------------
+sub makeover( Str:D $str --> Str:D )
+#------------------------------------------------------------------------------
+{
+ my Str $plain;
+
+ for $str.split( '', :skip-empty ) -> Str $char
+ {
+ if %UNICODE-TO-ASCII{ $char }:exists
+ {
+ $plain ~= %UNICODE-TO-ASCII{ $char };
+ }
+ else
+ {
+ $plain ~= $char;
+ }
+ }
+
+ return $plain;
+}
+
+#------------------------------------------------------------------------------
+sub create-lookup
+#------------------------------------------------------------------------------
+{
+ for %ASCII-TO-UNICODE.keys -> Str $key
+ {
+ for %ASCII-TO-UNICODE{ $key }.list -> Str $val
+ {
+ %UNICODE-TO-ASCII{ $val } = $key;
+ }
+ }
+}
+
+#------------------------------------------------------------------------------
+sub test-data()
+#------------------------------------------------------------------------------
+{
+ return q:to/END/;
+ Example 1, ÃÊÍÒÙ, AEIOU
+ Example 2, âÊíÒÙ, aEiOU
+ Finnish, En ymmärrä, En ymmarra
+ French 1, Combien ça coûte?, Combien ca coute?
+ French 2, Théâtralité évêché éphémère, Theatralite eveche ephemere
+ German, Wie heißt du?, Wie heisst du?
+ Icelandic, Góðan daginn, Godan daginn
+ Letter o, òóôõöøōŏőơǒǫǭǿȍȏȫȭȯȱɔ, ooooooooooooooooooooo
+ Acute capitals, ÁǼĆÉǴÍĹŃÓŔŚÚÝŹ, AAECEGILNORSUYZ
+ Circumflex small, âĉêĝîĵôŝûŵŷ, acegijosuwy
+ Double capitals, ÆIJ№ŊŒÞ, AEIJNoNGOETH
+ Yours truly, ℙėŗŀMȯƞķ Ąþåñąſïůș, PerlMonk Athanasius
+ Krio, Jɔs wan ɔda hakɛr, Jos wan oda haker
+ END
+}
+
+#------------------------------------------------------------------------------
+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;
+}
+
+###############################################################################