aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorholli-holzer <holli.holzer@gmail.com>2019-09-17 20:35:45 +0200
committerholli-holzer <holli.holzer@gmail.com>2019-09-17 20:35:45 +0200
commit79c26caafa0533b8a500825357fdfdac40100c6e (patch)
tree3a2b2e75e368c25a679efd6697b75398a42bc06b
parentecc3de5bb7bd780c1300ae1d3fba5379a5f82a7b (diff)
downloadperlweeklychallenge-club-79c26caafa0533b8a500825357fdfdac40100c6e.tar.gz
perlweeklychallenge-club-79c26caafa0533b8a500825357fdfdac40100c6e.tar.bz2
perlweeklychallenge-club-79c26caafa0533b8a500825357fdfdac40100c6e.zip
Revised the code to make it leaner. Added comments.
-rw-r--r--challenge-026/markus-holzer/perl6/ch-1.p630
-rw-r--r--challenge-026/markus-holzer/perl6/ch-2.p641
2 files changed, 40 insertions, 31 deletions
diff --git a/challenge-026/markus-holzer/perl6/ch-1.p6 b/challenge-026/markus-holzer/perl6/ch-1.p6
index cd39fe4cb7..85f29cab2c 100644
--- a/challenge-026/markus-holzer/perl6/ch-1.p6
+++ b/challenge-026/markus-holzer/perl6/ch-1.p6
@@ -1,21 +1,31 @@
-use v6;
use Test;
-multi sub infix:<+∩>( $stones, $jewels )
+# In Raku, all operators are just multi - functions.
+# So we can easily define ourselves an infix left-associative element-of operator.
+# It will take an `Iterable` (`Seq`, `Array`, `List`) on its left side and a `Set` on the right side.
+# It returns a `Seq` of all elements of the left side that are present on the right side.
+
+multi sub infix:<\<∈>( Iterable $stones, Set $jewels ) returns Seq
{
- $stones.Str +∩ $jewels.Str
+ $stones.grep: * ∈ $jewels
}
-multi sub infix:<+∩>( Str $stones, Str $jewels )
+# Now we could call that good, but in true Raku spirit we provide additional
+# versions of our operator to make using it easier.
+# We don't need to repeat ourselves. We can rely on the multi-mechanism
+# to do the right thing.
+
+multi sub infix:<\<∈>( Iterable $stones, Iterable $jewels ) returns Seq
{
- $stones.split( '', :skip-empty ) +∩ $jewels.split( '', :skip-empty ).Set
+ $stones <∈ $jewels.Set
}
-multi sub infix:<+∩>( Iterable $stones, Set $jewels )
+multi sub infix:<\<∈>( Str $stones, Str $jewels ) returns Str
{
- $stones.grep({ $_ ∈ $jewels })
+ ( $stones.split( '', :skip-empty ) <∈ $jewels.split( '', :skip-empty ) ).join("")
}
-ok( ( "chancellor" +∩ "chocolates" ).elems == 8 );
-ok( ( "chocolatiers" +∩ "chancellor" ).elems == 9 );
-ok( ( "bottle" +∩ "beer" ).elems == 2 );
+# And here we finally use it to solve the problem
+ok( ( ["b", "e", "e", "r"] <∈ ["b", "o", "t", "t", "l", "e"] ).elems == 3, "3 characters of 'beer' are also in 'bottle'" );
+ok( ( "chancellor" <∈ "chocolates" ).chars == 8, "8 characters of 'chancellor' are also in 'chocolates'" );
+ok( "chancellor" <∈ "chocolates" eq "chacello", "These characters are 'chacello'" );
diff --git a/challenge-026/markus-holzer/perl6/ch-2.p6 b/challenge-026/markus-holzer/perl6/ch-2.p6
index 0fc41be74d..2273b4f199 100644
--- a/challenge-026/markus-holzer/perl6/ch-2.p6
+++ b/challenge-026/markus-holzer/perl6/ch-2.p6
@@ -1,26 +1,25 @@
-use v6;
-use Test;
+# Rakus trigonometry functions operate on radians. So we must convert degrees to radians.
+# That's simple enough using a new postfix operator and high school math.
+multi sub postfix:<°>( Numeric $degrees ) returns Real { $degrees * π / 180 }
-sub radians( $degrees )
+# This implements the "simple" version of the algorithm as described on Wikipedia.
+# There already is an implementation of the complex math version (that uses `i`)
+# on Rosetta-Code https://rosettacode.org/wiki/Averages/Mean_angle#Perl_6
+sub mean-angle( *@α ) returns Real
{
- $degrees * π / 180
-}
-
-sub degrees( $radians )
-{
- $radians * 180 / π
-}
-
-sub mean-angle( *@angles )
-{
- my $inv = 1 / @angles.elems;
+ # Neiter inv, nor ρ will ever change, so we can define them as immutable
+ my \inv = 1 / @α.elems;
+ my \ρ = atan2(
+ (inv * [+] @α>>.sin), # calculate the sine of all angles, sum the result and multiply that with the factor
+ (inv * [+] @α>>.cos) # same, but with cosine
+ );
- degrees( atan2(
- $inv * [+] @angles.map({ radians( $_ ).sin }),
- $inv * [+] @angles.map({ radians( $_ ).cos })
- ));
+ ρ > 0
+ ?? ρ # We always want positive values
+ !! ρ + 2 * π # When it isn't, we add 360°
}
-ok( mean-angle( 10, 10, 10 ) =~= 10 );
-ok( mean-angle( 10, 20, 30 ) =~= 20 );
-ok( mean-angle( 355, 5, 15 ) =~= 5 );
+ok( mean-angle( 10°, 10°, 10° ) =~= 10°, "The mean of 3 times alpha is alpha" );
+ok( mean-angle( 10°, 20°, 30° ) =~= 20°, "All angles in one quadrant" );
+ok( mean-angle( 355°, 5°, 15° ) =~= 5°, "Angles in multiple quadrants" );
+ok( mean-angle( 90°, 180°, 270°, 360° ) =~= 270°, "Angle is not negative" );