Perl Weekly Challenge: Week 26

Challenge 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.

It's easy to solve this in Perl5 as a one-liner:

perl -E '%a = map {$_ => 1} split //, $ARGV[0]; say scalar grep {exists $a{$_}} split //, $ARGV[1]' chancellor chocolate

(Full code on Github.)

In Perl6, we can also do this as a one-liner in a slightly different way thanks to the in-built set support.

perl6 -e 'my @a = @*ARGS[0].comb ∩ @*ARGS[1].comb; @*ARGS[1].comb.grep({$_ ∈  @a.any }).elems.say' chancellor chocolate

(Full code on Github.)

Challenge 2:

Create a script that prints mean angles of the given list of angles in degrees. Please read wiki page that explains the formula in details with an example.

Both Perl5 and Perl6 have a full complement of trignometric functions so we can easily implement the method given on the wikipedia page. The only minor impediment is that those functions operate on values in radians while we typically express values in degrees. For Perl5, I could have used the Math::Trig module which has functions to convert from degrees to radians and vice versa but I don't know if that is available in Perl6 and anyway the conversions are trivial so I just did my own. Heres the Perl5 version:

use constant PI => (atan2 1, 1) * 4;

sub deg2rad {
    return $_[0] * (PI / 180);
}

sub rad2deg {
    return $_[0] / (PI / 180);
}

my $sines = 0;
my $cosines = 0;

for my $angle (@ARGV) {
    $sines += sin deg2rad($angle);
    $cosines += cos deg2rad($angle);
}

$sines /= scalar @ARGV;
$cosines /= scalar @ARGV;

say rad2deg(atan2 $sines, $cosines);

(Full code on Github.)

And here is Perl6:

sub deg2rad ($deg) {
    return $deg * (π / 180);
}

sub rad2deg($rad) {
    return $rad / (π / 180);
}

multi sub MAIN(*@ARGS) {
    my $sines = 0;
    my $cosines = 0;

    for @*ARGS -> $angle {
        $sines += sin deg2rad($angle);
        $cosines += cos deg2rad($angle);
    }

    $sines /= @*ARGS.elems;
    $cosines /= @*ARGS.elems;

   say rad2deg(atan2 $sines, $cosines).round;
}

(Full code on Github.)

I added the .round because the extra high precision of Perl6 real numbers was causing answers to be ever so slightly off.