aboutsummaryrefslogtreecommitdiff
path: root/challenge-026
diff options
context:
space:
mode:
authorholli-holzer <holli.holzer@gmail.com>2019-09-25 22:07:40 +0200
committerholli-holzer <holli.holzer@gmail.com>2019-09-25 22:07:40 +0200
commit3ea4c71923fa3efa6126bb82f6478c54f02208e4 (patch)
tree095f983eef6db7289c5d825708db817dfeed847d /challenge-026
parentfb785b17a1358135bf6d1a366c2c4df59b419091 (diff)
parent38173c385fb4c04bfc50cdf40fee15e8cb6901e1 (diff)
downloadperlweeklychallenge-club-3ea4c71923fa3efa6126bb82f6478c54f02208e4.tar.gz
perlweeklychallenge-club-3ea4c71923fa3efa6126bb82f6478c54f02208e4.tar.bz2
perlweeklychallenge-club-3ea4c71923fa3efa6126bb82f6478c54f02208e4.zip
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'challenge-026')
-rw-r--r--challenge-026/adam-russell/blog.txt1
-rw-r--r--challenge-026/adam-russell/perl5/ch-1.pl44
-rw-r--r--challenge-026/adam-russell/perl5/ch-2.pl35
-rw-r--r--challenge-026/arne-sommer/blog.txt1
-rwxr-xr-xchallenge-026/arne-sommer/perl6/ch-1.p67
-rwxr-xr-xchallenge-026/arne-sommer/perl6/ch-2.p615
-rwxr-xr-xchallenge-026/arne-sommer/perl6/stringcounter-loop15
-rwxr-xr-xchallenge-026/arne-sommer/perl6/stringcounter-map8
-rwxr-xr-xchallenge-026/arne-sommer/perl6/stringcounter-map-oneliner6
-rwxr-xr-xchallenge-026/arne-sommer/perl6/stringcounter-subset7
-rw-r--r--challenge-026/athanasius/perl5/ch-1.pl86
-rw-r--r--challenge-026/athanasius/perl5/ch-2.pl126
-rw-r--r--challenge-026/athanasius/perl6/ch-1.p668
-rw-r--r--challenge-026/athanasius/perl6/ch-2.p6121
-rw-r--r--challenge-026/colin-crain/perl5/ch-1.pl35
-rw-r--r--challenge-026/colin-crain/perl5/ch-2.pl57
-rw-r--r--challenge-026/daniel-mantovani/perl5/ch-1.pl22
-rw-r--r--challenge-026/daniel-mantovani/perl5/ch-2.pl35
-rw-r--r--challenge-026/donald-hunter/blog.txt1
-rw-r--r--challenge-026/donald-hunter/perl6/ch-1.p68
-rw-r--r--challenge-026/duncan-c-white/README57
-rwxr-xr-xchallenge-026/duncan-c-white/perl5/ch-1.pl38
-rwxr-xr-xchallenge-026/duncan-c-white/perl5/ch-2.pl38
-rw-r--r--challenge-026/e-choroba/blog.txt1
-rwxr-xr-xchallenge-026/e-choroba/perl5/ch-1.pl4
-rwxr-xr-xchallenge-026/e-choroba/perl5/ch-2.pl18
-rw-r--r--challenge-026/jaldhar-h-vyas/blog.txt1
-rwxr-xr-xchallenge-026/jaldhar-h-vyas/perl5/ch-1.sh2
-rwxr-xr-xchallenge-026/jaldhar-h-vyas/perl5/ch-2.pl28
-rwxr-xr-xchallenge-026/jaldhar-h-vyas/perl6/ch-1.sh1
-rwxr-xr-xchallenge-026/jaldhar-h-vyas/perl6/ch-2.p624
-rwxr-xr-xchallenge-026/joelle-maslak/perl5/ch-1.pl12
-rwxr-xr-xchallenge-026/joelle-maslak/perl5/ch-2.pl35
-rwxr-xr-xchallenge-026/joelle-maslak/perl6/ch-1.p610
-rwxr-xr-xchallenge-026/joelle-maslak/perl6/ch-2.p635
-rw-r--r--challenge-026/lubos-kolouch/perl5/ch-1.pl49
-rw-r--r--challenge-026/lubos-kolouch/perl5/ch-2.pl51
-rw-r--r--challenge-026/mark-senn/perl6/ch-1.p682
-rw-r--r--challenge-026/mark-senn/perl6/ch-2.p641
-rw-r--r--challenge-026/noud/perl6/ch-1.p613
-rw-r--r--challenge-026/noud/perl6/ch-2.p645
-rwxr-xr-xchallenge-026/ozzy/perl6/ch-1.p621
-rwxr-xr-xchallenge-026/ozzy/perl6/ch-2.p615
-rw-r--r--challenge-026/roger-bell-west/blog.txt1
-rw-r--r--challenge-026/ruben-westerberg/README16
-rwxr-xr-xchallenge-026/ruben-westerberg/perl5/ch-1.pl11
-rwxr-xr-xchallenge-026/ruben-westerberg/perl5/ch-2.pl14
-rwxr-xr-xchallenge-026/ruben-westerberg/perl6/ch-1.p66
-rwxr-xr-xchallenge-026/ruben-westerberg/perl6/ch-2.p69
-rw-r--r--challenge-026/yet-ebreo/perl5/ch-2.pl2
-rw-r--r--challenge-026/yet-ebreo/perl6/ch-1.p615
-rw-r--r--challenge-026/yet-ebreo/perl6/ch-2.p614
52 files changed, 1360 insertions, 47 deletions
diff --git a/challenge-026/adam-russell/blog.txt b/challenge-026/adam-russell/blog.txt
new file mode 100644
index 0000000000..b0d5a96b5c
--- /dev/null
+++ b/challenge-026/adam-russell/blog.txt
@@ -0,0 +1 @@
+https://adamcrussell.livejournal.com/9318.html
diff --git a/challenge-026/adam-russell/perl5/ch-1.pl b/challenge-026/adam-russell/perl5/ch-1.pl
new file mode 100644
index 0000000000..27b6048ea5
--- /dev/null
+++ b/challenge-026/adam-russell/perl5/ch-1.pl
@@ -0,0 +1,44 @@
+use strict;
+use warnings;
+##
+# Create a script that accepts two strings, let us call it them "stones" and "jewels".
+# It should print the count of the "alphabet" from "stones" found in "jewels".
+##
+
+sub contains_remove{
+ my($c) = @_;
+ return sub{
+ my($word) = @_;
+ $word =~ s/$c//;
+ return $word;
+ }
+}
+
+sub make_checks{
+ my($word) = @_;
+ my @letters = split(//, $word);
+ my @checks;
+ for my $c (@letters){
+ push @checks, contains_remove($c);
+ }
+ return @checks;
+}
+
+sub check_jewels{
+ my($jewels, $checks) = @_;
+ my $count = 0;
+ while(@{$checks}){
+ my $check = pop @{$checks};
+ my $c = $check->($jewels);
+ $count += (length($jewels) - length($c));
+ }
+ return $count;
+}
+
+MAIN:{
+ my($stones, $jewels) = ($ARGV[0], $ARGV[1]);
+ chomp($stones);
+ chomp($jewels);
+ my @checks = make_checks($stones);
+ print check_jewels($jewels, \@checks) . "\n";
+}
diff --git a/challenge-026/adam-russell/perl5/ch-2.pl b/challenge-026/adam-russell/perl5/ch-2.pl
new file mode 100644
index 0000000000..75d0e699c5
--- /dev/null
+++ b/challenge-026/adam-russell/perl5/ch-2.pl
@@ -0,0 +1,35 @@
+use strict;
+use warnings;
+##
+# Create a script that prints mean angles of the given list of angles in degrees.
+##
+use constant PI => atan2(1,1) * 4;
+
+sub deg2rad {
+ my($degrees) = @_;
+ return ($degrees / 180) * PI;
+}
+
+sub rad2deg {
+ my($radians) = @_;
+ return ($radians / PI) * 180;
+}
+
+sub compute_mean_angle{
+ my(@angles) = @_;
+ my $sum = 0;
+ map { $sum += $_ } map { sin($_) } @angles;
+ my $sin_mean = $sum / @angles;
+ $sum = 0;
+ map { $sum += $_ } map { cos($_) } @angles;
+ my $cos_mean = $sum / @angles;
+ return atan2($sin_mean, $cos_mean) if $sin_mean > 0 && $cos_mean > 0;
+ return atan2($sin_mean, $cos_mean) + deg2rad(180) if $cos_mean < 0;
+ return atan2($sin_mean, $cos_mean) + deg2rad(360) if $sin_mean < 0 && $cos_mean > 0;
+}
+
+
+MAIN:{
+ my @angles = map { deg2rad($_) } @ARGV[0 .. (@ARGV - 1)];
+ print rad2deg(compute_mean_angle(@angles)) . "\n";
+}
diff --git a/challenge-026/arne-sommer/blog.txt b/challenge-026/arne-sommer/blog.txt
new file mode 100644
index 0000000000..dd665e7af0
--- /dev/null
+++ b/challenge-026/arne-sommer/blog.txt
@@ -0,0 +1 @@
+https://perl6.eu/string-angling.html
diff --git a/challenge-026/arne-sommer/perl6/ch-1.p6 b/challenge-026/arne-sommer/perl6/ch-1.p6
new file mode 100755
index 0000000000..ab31fa021c
--- /dev/null
+++ b/challenge-026/arne-sommer/perl6/ch-1.p6
@@ -0,0 +1,7 @@
+#! /usr/bin/env perl6
+
+subset AtoZ of Str where /^ <[A .. Z a .. z]>+ $/;
+
+unit sub MAIN (AtoZ $alphabet, AtoZ $string);
+
+say ($alphabet.comb.Set ⊍ $string.comb.Bag).Int;
diff --git a/challenge-026/arne-sommer/perl6/ch-2.p6 b/challenge-026/arne-sommer/perl6/ch-2.p6
new file mode 100755
index 0000000000..916424e518
--- /dev/null
+++ b/challenge-026/arne-sommer/perl6/ch-2.p6
@@ -0,0 +1,15 @@
+#! /usr/bin/env perl6
+
+unit sub MAIN (*@angles);
+
+my \n = @angles.elems;
+my @rad = @angles.map(* * pi / 180);
+my \s = @rad.map(*.sin).sum / n;
+my \c = @rad.map(*.cos).sum / n;
+my $mean = atan2( s / c ) * 180 / pi;
+
+if c < 0 { $mean += 180; }
+elsif s < 0 { $mean += 360; }
+
+say "mean: $mean";
+
diff --git a/challenge-026/arne-sommer/perl6/stringcounter-loop b/challenge-026/arne-sommer/perl6/stringcounter-loop
new file mode 100755
index 0000000000..67ffd13b47
--- /dev/null
+++ b/challenge-026/arne-sommer/perl6/stringcounter-loop
@@ -0,0 +1,15 @@
+#! /usr/bin/env perl6
+
+unit sub MAIN (Str $alphabet, Str $string, :$verbose);
+
+my $count = 0;
+
+for $alphabet.comb.unique -> $letter
+{
+ my $current = $string.comb.grep(* eq $letter).elems;
+ $count += $current;
+ say "$letter: $current" if $verbose;
+}
+
+say $count;
+
diff --git a/challenge-026/arne-sommer/perl6/stringcounter-map b/challenge-026/arne-sommer/perl6/stringcounter-map
new file mode 100755
index 0000000000..82b1280e79
--- /dev/null
+++ b/challenge-026/arne-sommer/perl6/stringcounter-map
@@ -0,0 +1,8 @@
+#! /usr/bin/env perl6
+
+unit sub MAIN (Str $alphabet, Str $string);
+
+say $alphabet.comb.unique.map( { $string.comb.grep(* eq $_ ) } ).sum;
+
+
+
diff --git a/challenge-026/arne-sommer/perl6/stringcounter-map-oneliner b/challenge-026/arne-sommer/perl6/stringcounter-map-oneliner
new file mode 100755
index 0000000000..a0e6945ef4
--- /dev/null
+++ b/challenge-026/arne-sommer/perl6/stringcounter-map-oneliner
@@ -0,0 +1,6 @@
+#! /usr/bin/env perl6
+
+say @*ARGS[0].comb.unique.map( { @*ARGS[1].comb.grep(* eq $_ ) } ).sum;
+
+
+
diff --git a/challenge-026/arne-sommer/perl6/stringcounter-subset b/challenge-026/arne-sommer/perl6/stringcounter-subset
new file mode 100755
index 0000000000..35d3000a56
--- /dev/null
+++ b/challenge-026/arne-sommer/perl6/stringcounter-subset
@@ -0,0 +1,7 @@
+#! /usr/bin/env perl6
+
+subset AtoZ of Str where /^ <[A .. Z a .. z]>+ $/;
+
+unit sub MAIN (AtoZ $alphabet, AtoZ $string);
+
+say $alphabet.comb.unique.map( { $string.comb.grep(* eq $_ ) } ).sum;
diff --git a/challenge-026/athanasius/perl5/ch-1.pl b/challenge-026/athanasius/perl5/ch-1.pl
new file mode 100644
index 0000000000..e3682b69ca
--- /dev/null
+++ b/challenge-026/athanasius/perl5/ch-1.pl
@@ -0,0 +1,86 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 026
+=========================
+
+Task #1
+-------
+Create a script that accepts two strings, let us call it, *"stones"* and
+*"jewels"*. It should print the count of "alphabet" from the string *"stones"*
+found in the string *"jewels"*. For example, if your *stones* is *"chancellor"*
+and *"jewels"* is *"chocolate"*, then the script should print *"8"*. To keep it
+simple, only A-Z,a-z characters are acceptable. Also make the comparison case
+sensitive.
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2019 PerlMonk Athanasius #
+#--------------------------------------#
+
+use strict;
+use warnings;
+use Const::Fast;
+use Getopt::Long;
+
+const my $ALPHA => qr{ [A-Za-z] }x;
+const my $STONES => 'chancellor';
+const my $JEWELS => 'chocolate';
+const my $USAGE => "USAGE: perl $0 [--stones=<Str>] [--jewels=<Str>] " .
+ "[--show]\n";
+
+BEGIN
+{
+ $| = 1;
+ print "\n";
+}
+
+#===============================================================================
+MAIN:
+#===============================================================================
+{
+ my $stones = $STONES;
+ my $jewels = $JEWELS;
+ my $show = 0;
+
+ GetOptions
+ (
+ 'stones=s' => \$stones,
+ 'jewels=s' => \$jewels,
+ 'show' => \$show,
+
+ ) or die $USAGE;
+
+ my $count = 0;
+ my %jewels = map { $_ => undef } grep { /$ALPHA/ } split //, $jewels;
+
+ # Count each letter in the "stones" string if and only if it also occurs
+ # (anywhere, but at least once) in the "jewels" string
+
+ my @letters if $show;
+
+ for my $letter (grep { /$ALPHA/ } split //, $stones)
+ {
+ if (exists $jewels{$letter})
+ {
+ ++$count ;
+ push(@letters, $letter) if $show;
+ }
+ }
+
+ my $width = length $count;
+
+ printf "%*d of the letters in the Stones string \"%s\"\n" .
+ "%*s also occur%s in the Jewels string \"%s\"\n",
+ $width, $count, $stones,
+ ($count == 1 ? $width - 1 : $width), '',
+ ($count == 1 ? 's' : '' ), $jewels;
+
+ print('namely (', join(', ', @letters), ")\n") if $show;
+}
+
+################################################################################
diff --git a/challenge-026/athanasius/perl5/ch-2.pl b/challenge-026/athanasius/perl5/ch-2.pl
new file mode 100644
index 0000000000..4083d0ce86
--- /dev/null
+++ b/challenge-026/athanasius/perl5/ch-2.pl
@@ -0,0 +1,126 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 026
+=========================
+
+Task #2
+-------
+Create a script that prints *mean angles* of the given list of angles in
+degrees. Please read [ https://en.wikipedia.org/wiki/Mean_of_circular_quantities
+|wiki page] that explains the formula in details with an example.
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2019 PerlMonk Athanasius #
+#--------------------------------------#
+
+use strict;
+use warnings;
+use utf8;
+use Const::Fast;
+use Data::Types qw( is_float );
+use Getopt::Long;
+
+const my $PI => 4 * atan2(1, 1);
+const my $USAGE =>
+ "USAGE:\n perl $0 [<angles> ...]\n" .
+ " perl $0 -- [<angles> ...] (to include +/- prefixes)\n" .
+ " perl $0 [--filename=<Str>]\n";
+
+BEGIN
+{
+ $| = 1;
+ print "\n";
+}
+
+#===============================================================================
+MAIN:
+#===============================================================================
+{
+ # Parse the command line
+
+ GetOptions('file=s' => \my $file)
+ or die $USAGE;
+
+ defined $file && scalar @ARGV > 0
+ and die "ERROR: Found filename as well as angle(s)\n$USAGE";
+
+ # Read and validate the input data
+
+ my @angles = defined $file ? read_file($file) : @ARGV;
+
+ scalar @angles > 0
+ or die $USAGE;
+
+ for my $angle (@angles)
+ {
+ is_float($angle)
+ or die "ERROR: Invalid angle \"$angle\"\n$USAGE";
+ }
+
+ # Calculate and display the circular mean
+
+ printf "The circular mean of the angle%s\n (%s)\nis %s°\n",
+ scalar @angles == 1 ? '' : 's',
+ join(', ', map { "$_°" } @angles),
+ sprintf find_circular_mean(@angles);
+}
+
+#-------------------------------------------------------------------------------
+sub read_file
+#-------------------------------------------------------------------------------
+{
+ my ($file) = @_;
+ my @angles;
+
+ open my $fh, '<', $file
+ or die "Cannot open file \"$file\" for reading, stopped";
+
+ # File format: one angle (in degrees) per line; blank lines are ignored
+
+ while (my $line = <$fh>)
+ {
+ $line =~ s/ ^ \s+ //x; # trim leading whitespace
+ $line =~ s/ \s+ $ //x; # trim trailing whitespace (including newline)
+
+ next if $line eq '';
+
+ push @angles, $line;
+ }
+
+ close $fh
+ or die "Cannot close file \"$file\", stopped";
+
+ return @angles;
+}
+
+#-------------------------------------------------------------------------------
+sub find_circular_mean
+#-------------------------------------------------------------------------------
+{
+ # The circular mean (in radians) is given by the formula:
+ #
+ # atan2( 1/n ∑ [j=1..n] sin α_j, 1/n ∑ [j=1..n] cos α_j )
+
+ my @angles = @_;
+ my $sum_of_sines = 0;
+ my $sum_of_cosines = 0;
+
+ for my $degrees (@angles)
+ {
+ my $radians = $degrees * ($PI / 180);
+ $sum_of_sines += sin $radians; # build ∑ [j=1..n] sin α_j
+ $sum_of_cosines += cos $radians; # build ∑ [j=1..n] cos α_j
+ }
+
+ my $n = scalar @angles;
+
+ return atan2($sum_of_sines / $n, $sum_of_cosines / $n) * (180 / $PI);
+}
+
+################################################################################
diff --git a/challenge-026/athanasius/perl6/ch-1.p6 b/challenge-026/athanasius/perl6/ch-1.p6
new file mode 100644
index 0000000000..29f9663afb
--- /dev/null
+++ b/challenge-026/athanasius/perl6/ch-1.p6
@@ -0,0 +1,68 @@
+use v6;
+
+################################################################################
+=begin comment
+
+Perl Weekly Challenge 026
+=========================
+
+Task #1
+-------
+Create a script that accepts two strings, let us call it, *"stones"* and
+*"jewels"*. It should print the count of "alphabet" from the string *"stones"*
+found in the string *"jewels"*. For example, if your *stones* is *"chancellor"*
+and *"jewels"* is *"chocolate"*, then the script should print *"8"*. To keep it
+simple, only A-Z,a-z characters are acceptable. Also make the comparison case
+sensitive.
+
+=end comment
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2019 PerlMonk Athanasius #
+#--------------------------------------#
+
+my Regex constant $ALPHA = rx{ <[A..Za..z]> };
+my Str constant $STONES = 'chancellor';
+my Str constant $JEWELS = 'chocolate';
+
+BEGIN say '';
+
+#===============================================================================
+sub MAIN
+#===============================================================================
+(
+ Str:D :$stones = $STONES, #= The "stones" string
+ Str:D :$jewels = $JEWELS, #= The "jewels" string
+ Bool:D :$show = False, #= Show the matching letters?
+)
+{
+ my UInt $count = 0;
+ my Nil %jewels = $jewels.split('').grep( { $ALPHA } ).map( { $_ => Nil } );
+
+ # Count each letter in the "stones" string if and only if it also occurs
+ # (anywhere, but at least once) in the "jewels" string
+
+ my Str @letters if $show;
+
+ for $stones.split('').grep( { $ALPHA } ) -> Str $letter
+ {
+ if %jewels{$letter}:exists
+ {
+ ++$count;
+ @letters.push($letter) if $show;
+ }
+ }
+
+ my UInt $width = $count.chars;
+
+ ("%*d of the letters in the Stones string \"%s\"\n" ~
+ "%*s also occur%s in the Jewels string \"%s\"\n").printf:
+ $width, $count, $stones,
+ ($count == 1 ?? $width - 1 !! $width), '',
+ ($count == 1 ?? 's' !! '' ), $jewels;
+
+ "namely ({ @letters.join(', ') })".say if $show && @letters.elems;
+}
+
+################################################################################
diff --git a/challenge-026/athanasius/perl6/ch-2.p6 b/challenge-026/athanasius/perl6/ch-2.p6
new file mode 100644
index 0000000000..612b67c15a
--- /dev/null
+++ b/challenge-026/athanasius/perl6/ch-2.p6
@@ -0,0 +1,121 @@
+use v6;
+
+################################################################################
+=begin comment
+
+Perl Weekly Challenge 026
+=========================
+
+Task #2
+-------
+Create a script that prints *mean angles* of the given list of angles in
+degrees. Please read [ https://en.wikipedia.org/wiki/Mean_of_circular_quantities
+|wiki page] that explains the formula in details with an example.
+
+=end comment
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2019 PerlMonk Athanasius #
+#--------------------------------------#
+
+BEGIN say '';
+
+#===============================================================================
+multi sub MAIN(Str:D :$file) #= Data file containing angles (degrees),
+ #= one per line
+#===============================================================================
+{
+ my Real @angles;
+
+ for $file.IO.lines
+ {
+ my $line = $_;
+
+ $line ~~ s/ ^^ \s+ //;
+ $line ~~ s/ \s+ $$ //;
+
+ next unless $line.chars > 0;
+
+ use fatal;
+
+ @angles.push: val($line, :val-or-fail);
+ }
+
+ MAIN(@angles);
+
+ CATCH
+ {
+ when X::Str::Numeric
+ {
+ $*ERR.say: "In file \"$file\":\n{ .message }\n$*USAGE";
+ }
+ }
+}
+
+#-------------------------------------------------------------------------------
+class X::Mean-Angles::No-Angles is Exception
+#-------------------------------------------------------------------------------
+{
+ method message(--> Str:D)
+ {
+ return 'No angles found';
+ }
+}
+
+#===============================================================================
+multi sub MAIN(*@angles) #= One or more angles (all in degrees)
+#===============================================================================
+{
+ my Real:D @real-angles = @angles;
+
+ @real-angles.elems > 0
+ or X::Mean-Angles::No-Angles.new.throw;
+
+ # Calculate and display the circular mean
+
+ $*OUT.encoding('windows-1252');
+
+ "The circular mean of the angle%s\n (%s)\nis %.1f°\n".printf:
+ @angles.elems == 1 ?? '' !! 's',
+ @angles.map( { "$_°" } ).join(', '),
+ find-circular-mean(@angles);
+
+ CATCH
+ {
+ when X::TypeCheck::Assignment
+ {
+ $*ERR.say: .message ~ "\n$*USAGE";
+ }
+
+ when X::Mean-Angles::No-Angles
+ {
+ $*ERR.say: .message ~ "\n$*USAGE";
+ }
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub find-circular-mean(*@angles --> Real:D)
+#-------------------------------------------------------------------------------
+{
+ # The circular mean (in radians) is given by the formula:
+ #
+ # atan2( 1/n ∑ [j=1..n] sin α_j, 1/n ∑ [j=1..n] cos α_j )
+
+ my Real $sum-of-sines = 0;
+ my Real $sum-of-cosines = 0;
+
+ for @angles -> Real $degrees
+ {
+ my Real $radians = $degrees * (π / 180);
+ $sum-of-sines += $radians.sin; # build ∑ [j=1..n] sin α_j
+ $sum-of-cosines += $radians.cos; # build ∑ [j=1..n] cos α_j
+ }
+
+ my UInt $n = @angles.elems;
+
+ return ($sum-of-sines / $n).atan2($sum-of-cosines / $n) * (180 / π);
+}
+
+################################################################################
diff --git a/challenge-026/colin-crain/perl5/ch-1.pl b/challenge-026/colin-crain/perl5/ch-1.pl
new file mode 100644
index 0000000000..8850b2c724
--- /dev/null
+++ b/challenge-026/colin-crain/perl5/ch-1.pl
@@ -0,0 +1,35 @@
+#! /opt/local/bin/perl
+#
+# stones_and_jewels.pl
+