diff options
| author | Lubos Kolouch <lubos@kolouch.net> | 2019-09-29 10:05:08 +0200 |
|---|---|---|
| committer | Lubos Kolouch <lubos@kolouch.net> | 2019-09-29 10:05:08 +0200 |
| commit | d21597a12fa8a3186cd70c3352927f6724170b6b (patch) | |
| tree | 0e7a986a1ef7bc10dcacb9bac997a14a42668d58 | |
| parent | ab19596cb9203bbc66ebcf8a07be29a26144b37c (diff) | |
| parent | 6d1910afd271caaac2fd6c601cdf7850dc858451 (diff) | |
| download | perlweeklychallenge-club-d21597a12fa8a3186cd70c3352927f6724170b6b.tar.gz perlweeklychallenge-club-d21597a12fa8a3186cd70c3352927f6724170b6b.tar.bz2 perlweeklychallenge-club-d21597a12fa8a3186cd70c3352927f6724170b6b.zip | |
Merge branch 'master' of https://github.com/manwar/perlweeklychallenge-club
44 files changed, 5769 insertions, 5330 deletions
diff --git a/challenge-026/markus-holzer/perl6/ch-1.p6 b/challenge-026/markus-holzer/perl6/ch-1.p6 index 70e6ceeaeb..ec85b011b2 100644 --- a/challenge-026/markus-holzer/perl6/ch-1.p6 +++ b/challenge-026/markus-holzer/perl6/ch-1.p6 @@ -25,7 +25,7 @@ multi sub infix:<\<∈>( Iterable $stones, Iterable $jewels ) returns Seq multi sub infix:<\<∈>( Str $stones, Str $jewels ) returns Str { - ( $stones.split( '', :skip-empty ) <∈ $jewels.split( '', :skip-empty ) ).join("") + ( $stones.comb <∈ $jewels.comb ).join("") } # And here we finally use it to solve the problem diff --git a/challenge-027/joelle-maslak/perl6/ch-1.p6 b/challenge-027/joelle-maslak/perl6/ch-1.p6 new file mode 100755 index 0000000000..4a711c64b1 --- /dev/null +++ b/challenge-027/joelle-maslak/perl6/ch-1.p6 @@ -0,0 +1,174 @@ +#!/usr/bin/env perl6 +use v6; + +use StrictClass; + +# This program finds the intersection of two lines. While the word +# "ends" is used, I'm instead assuming that these are true mathematical +# lines, not line segments, so the intersection point may not be between +# the two points that define the line. +# +# The first thing we need to do is to find the slope of each line. +# +# Edge case 1: If either line is not fully defined, we return an error. +# This happens if both points are the same. +# +# Edge case 2: A vertical line can't be defined by the standard y = A × x₁ + C +# equation. In this case we handle it differently, see below. We use ∞ +# for the slope in this case. +# +# To find the slope (of non-vertical lines), it's just rise / run, which is +# easy to calculate. For the constant, we need to solve this: +# y = Ax + C +# A given point will define x and y, while the slope defines A, so we just +# solve for C. THus: +# C = y - Ax; +# +# If we have two equations: y₁ = A₁ × x₁ + C₁ +# y₂ = A₂ × x₂ + C₂ +# +# We can find the intersection: +# 1) If slope is identical, and constants differ, NO INTERSECTION +# 2) If slope is identical, and constants are the same, this is the +# same line. +# 3) If the slope is infinite of either line, just solve the other +# equation to determine y for that value of x. +# 4) Otherwise, we're looking for the point where x₁=x₂ and y₁=y₂ +# Thus, we can rewrite the equations as: +# y = A₁ × x + C₁ +# y = A₂ × x + C₂ +# We can solve this system for x: +# A₁ × x + C₁ = A₂ × x + C₂ +# Rewritten: +# A₁ × x - A₂ × x = C₂ - C₁ +# Rewritten: +# (A₁ - A₂) × x = C₂ - C₁ +# x = (C₂ - C₁) ÷ (A₁ - A₂) +# Once we have x, we can solve for y by plugging into either of the +# original equations. +# + +class Point does StrictClass { + has Real:D $.x is rw is required; + has Real:D $.y is rw is required; + + method from-string(Str:D $point-str is copy -->Point:D) { + $point-str ~~ s:s/^ '(' [.*] ')' $/$0/; # Remove parens + my (Real:D $x, Real:D $y) = $point-str.split(',').map( +* ); + + return Point.new(:$x, :$y); + + CATCH { + # We must have been passed a bad point + die "$point-str is an invalid point definition"; + } + } +} + +class Line does StrictClass { + has Real:D $.slope is rw is required; + has Point:D $.point is rw is required; # Any valid point on the line + + method solve-for-x(Real:D $y -->Real:D) { + # Vertical line exception + return $.point.x if $.slope == ∞; + + # Horizontal line exception + if $.slope == 0 { + die "Cannot solve for $y" if $.point.y ≠ $y; + } + + return ($y - self.y-offset) ÷ $.slope; + } + + method solve-for-y(Real:D $x -->Real:D) { + # Horizontal line exception + return $.point.y if $.slope == 0; + + # Vertical line exception + if $.slope == ∞ { + die "Cannot solve for $x" if $.point.x ≠ $x; + } + + # Lines between horizontal and ertical + return $.slope × $x + self.y-offset; + } + + method y-offset(-->Real:D) { + # Vertical line exception + return ∞ if $.slope == ∞; + + # Non-vertical lines + return $.point.y - $.slope × $.point.x; + } + + method intersection(Line:D $line -->Point:D) { + die "Lines are the same" if self eqv $line; + die "Lines do not intersect" if self.slope == $line.slope; + + # If either line is vertical + if self.slope == ∞ { + return Point.new(:x(self.point.x), :y($line.solve-for-y(self.point.x))); + } elsif $line.slope == ∞ { + return Point.new(:x($line.point.x), :y(self.solve-for-y($line.point.x))); + } + + # We're finding a normal intersection + my $x = ($line.y-offset - self.y-offset) ÷ (self.slope - $line.slope); + my $y = self.solve-for-y($x); + + return Point.new(:$x, :$y); + } + + # We need an eqv that works + CORE::<&infix:<eqv>>.add_dispatchee( + multi sub infix:<eqv> (Line:D $line1, Line:D $line2 -->Bool) { + return False if $line1.slope ≠ $line2.slope; + + # Are both vertical? + if $line1.slope == ∞ and $line2.slope == ∞ { + return $line1.point.x == $line2.point.x; + } + + # All other lines + return $line1.point.y == $line2.solve-for-y($line1.point.x); + } + ); + + method from-points(Point:D $point1, Point:D $point2 -->Line:D) { + # Handle same point + die "Lines must be defined with two different points" if $point1 eqv $point2; + + # Handle vertical line exception + return Line.new(:point($point1), :slope(∞)) if $point1.x == $point2.x; + + # Handle other lines. + my $slope = ($point1.y - $point2.y) ÷ ($point1.x - $point2.x); + return Line.new(:point($point1), :$slope); + } +} + +# point1 and point2 define a line. You can determine which line by the +# letter +sub MAIN(Str:D $point1a, Str:D $point2a, Str:D $point1b, $point2b) { + my $line1 = Line.from-points( + Point.from-string($point1a), + Point.from-string($point2a), + ); + my $line2 = Line.from-points( + Point.from-string($point1b), + Point.from-string($point2b), + ); + + if $line1 eqv $line2 { + say "The two lines are the same"; + } elsif $line1.slope == $line2.slope { + say "The two lines don't intersect"; + } else { + my $intersection = $line1.intersection($line2); + say "The lines intersect at ({ $intersection.x },{ $intersection.y })"; + } + + return; +} + diff --git a/challenge-027/joelle-maslak/perl6/ch-2.p6 b/challenge-027/joelle-maslak/perl6/ch-2.p6 new file mode 100755 index 0000000000..8183d58d79 --- /dev/null +++ b/challenge-027/joelle-maslak/perl6/ch-2.p6 @@ -0,0 +1,59 @@ +#!/usr/bin/env perl6 +use v6; + +# Limitation: With nested data structures, we only store the version as +# it existed at the time of setting the proxy (I.E. an array that +# changes *after* the proxy variable is set will only be stored as the +# initial value of the array. +class History { + has @!hist; + has $!data; + + method get-proxy() is rw { + my $data := $!data; + my $history := @!hist; + Proxy.new( + FETCH => method () { $data }, + STORE => method ($val) { $data = $val; $history.push( $data.clone ) }, + ); + } + + method history() { + my @h = @!hist; + @h.push: $!data; + return @h; + } +} + +sub MAIN() { + my $hist = History.new; + my $x := $hist.get-proxy(); + + $x = 10; + $x = 20; + $x -= 5; + + my $y := $hist.get-proxy(); # It's okay to have multiple proxies + $y++; + $y = 'Foo!'; + + # And to show that the second proxy is using the same values + $x ~= ' Bar!'; + + # A new instance of history should be independnet. + my $hist2 = History.new; + my $z := $hist2.get-proxy(); + $z = 3; # Won't show up in history for $hist. + + # And we just set the original history, the one we log, to a new + # value + $x = 'Baz.'; + + # Also let's do an array. + my @a = 1,2,3; + $x = @a; + + say join("\n", $hist.history».perl); +} + + diff --git a/challenge-027/markus-holzer/README b/challenge-027/markus-holzer/README index 64aaa503e7..2000655be2 100644 --- a/challenge-027/markus-holzer/README +++ b/challenge-027/markus-holzer/README @@ -1 +1,6 @@ Solutions by Markus Holzer. + +Solution #2 only works on the current developer branch and uses a module I wrote +Please see https://github.com/holli-holzer/perl6-Scalar-History +To be on CPAN soon + diff --git a/challenge-027/markus-holzer/perl6/ch-1.pl6 b/challenge-027/markus-holzer/perl6/ch-1.pl6 new file mode 100644 index 0000000000..4c7e3b5448 --- /dev/null +++ b/challenge-027/markus-holzer/perl6/ch-1.pl6 @@ -0,0 +1,27 @@ +multi sub MAIN( Int:D $x1, Int:D $y1, Int:D $x2, Int:D $y2, Int:D $x3, Int:D $y3, Int:D $x4, Int:D $y4 ) +{ + with intersection( $x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4 ) -> ($x, $y) + { + say "The intersection is at $x, $y."; + } + else + { + say .exception.message; + } +} + + +sub intersection( Int \x1, Int \y1, Int \x2, Int \y2, Int \x3, Int \y3, Int \x4, Int \y4 ) +{ + CATCH { default { fail "Lines are parallel or identical" } } + + return ( + eager # potential for division by zero, + ( (x1 * y2 - y1 * x2 ) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3*x4) ) div + ( (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4) ), + + eager # without eager, laziness will bite us later + ( (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 -y2) * (x3*y4 - y3 * x4) ) div + ( (x1 - x2) * (y3 - y4) - (y1 - y2) * (x2 - x4) ) + ); +} diff --git a/challenge-027/markus-holzer/perl6/ch-2.pl6 b/challenge-027/markus-holzer/perl6/ch-2.pl6 new file mode 100644 index 0000000000..d3bea23017 --- /dev/null +++ b/challenge-027/markus-holzer/perl6/ch-2.pl6 @@ -0,0 +1,9 @@ +use Test; +use Scalar::History; # See the README + +my Int $x := Scalar::History.create(10, Int); +$x = 20; +$x -= 5; + +ok( $x == 15 ); +is-deeply( $x.VAR.get-history, (10, 20) );
\ No newline at end of file diff --git a/challenge-027/markus-holzer/perl6/lib/Scalar/History.pm6 b/challenge-027/markus-holzer/perl6/lib/Scalar/History.pm6 new file mode 100644 index 0000000000..13c8346424 --- /dev/null +++ b/challenge-027/markus-holzer/perl6/lib/Scalar/History.pm6 @@ -0,0 +1,93 @@ +use Test; + +my $minumum-version = Version.new('2019.07.1.357.gd.00674.b.31'); + +die "Scalar::History requires $minumum-version or later" + if ( $*PERL.compiler.version cmp $minumum-version ) == Less; + +class Scalar::History::Proxy is Proxy +{ + has @!history; + has $!position; + + # This is needed for now since the standard ways + # like assigning in the `has` statement, TWEAK + # and BUILD don't work with `Proxy` + + method new( :&FETCH!, :&STORE!, *%_ ) is raw + { + my $self := self.Proxy::new( :&FETCH, :&STORE ); + $self.VAR.TWEAK( |%_ ); + $self + } + + method TWEAK( :$!position = 0 ) { + # yadayada + } + + method current-value( \SELF: ) + { + @!history[ $!position ] + } + + method latest-value( \SELF: ) + { + @!history[ *-1 ] + } + + method get-history( \SELF: Bool :$all = False ) + { + my $to-index = $all ?? @!history.elems - 1 !! $!position; + @!history[ ^$to-index ] + } + + method reset-history( \SELF: ) + { + @!history = (); + $!position = 0; + } + + method forward-history( \SELF: $steps ) + { + $!position = $!position + $steps; + $!position = @!history.elems - 1 + if $!position >= @!history.elems; + $!position; + } + + method rewind-history( \SELF: $steps ) + { + $!position = $!position - $steps; + $!position = 0 + if $!position < 0; + $!position; + } + + method store-value( \SELF: $new-value, $register-duplicates ) + { + # Forget stuff after rewind + if @!history.elems > $!position + 1 + { + @!history.splice( $!position + 1 ); + } + + if !($new-value eqv SELF.current-value) || $register-duplicates + { + @!history.push( $new-value ); + $!position = @!history.elems - 1; + } + } +} + +class Scalar::History +{ + method create( $value, ::T $type = Any, Bool :$register-duplicates = False ) + { + return-rw Scalar::History::Proxy.new( + FETCH => method ( \SELF: ) { + SELF.current-value() }, + STORE => method ( \SELF: T $new-value ) { + SELF.store-value( $new-value, $register-duplicates ); } + ) = $value; + } +}
\ No newline at end of file diff --git a/challenge-027/yet-ebreo/perl6/ch-2.p6 b/challenge-027/yet-ebreo/perl6/ch-2.p6 new file mode 100644 index 0000000000..52f254c429 --- /dev/null +++ b/challenge-027/yet-ebreo/perl6/ch-2.p6 @@ -0,0 +1,23 @@ +# Write a script that allows you to capture/display historical data. It could be an object or a scalar. For example +# my $x = 10; $x = 20; $x -= 5; +# After the above operations, it should list $x historical value in order. + +class hist { + has @.history; + has $!var handles <Str gist FETCH Numeric>; + method STORE($val) { + push @.history, $val; + $!var = $val; + } +} + +my \x = hist.new(history => []); + +x = 10; +x = 20; +x -= 5; +x = 3.1416; +x = Q[a quick brown fox jumps over the lazy dog]; +x = 1e3; +x*= sqrt 3; +.say for x.history; diff --git a/stats/pwc-challenge-001.json b/stats/pwc-challenge-001.json index 8c87056def..d54dea2b81 100644 --- a/stats/pwc-challenge-001.json +++ b/stats/pwc-challenge-001.json @@ -1,9 +1,9 @@ { - "xAxis" : { - "type" : "category" + "chart" : { + "type" : "column" }, - "legend" : { - "enabled" : 0 + "title" : { + "text" : "Perl Weekly Challenge - 001" }, "drilldown" : { "series" : [ @@ -18,52 +18,52 @@ 1 ] ], - "name" : "Adam Russell", - "id" : "Adam Russell" + "id" : "Adam Russell", + "name" : "Adam Russell" }, { + "name" : "Ailbhe Tweedie", "data" : [ [ "Perl 5", 1 ] ], - "id" : "Ailbhe Tweedie", - "name" : "Ailbhe Tweedie" + "id" : "Ailbhe Tweedie" }, { "id" : "Alex Daniel", - "name" : "Alex Daniel", "data" : [ [ "Perl 6", 2 ] - ] + ], + "name" : "Alex Daniel" }, { + "name" : "Andrezgz", + "id" : "Andrezgz", "data" : [ [ "Perl 5", 2 ] - ], - "name" : "Andrezgz", - "id" : "Andrezgz" + ] }, { + "name" : "Antonio Gamiz", "data" : [ [ "Perl 6", 2 ] ], - "name" : "Antonio Gamiz", "id" : "Antonio Gamiz" }, { - "id" : "Arne Sommer", "name" : "Arne Sommer", + "id" : "Arne Sommer", "data" : [ [ "Perl 5", @@ -81,43 +81,43 @@ }, { "name" : "Arpad Toth", - "id" : "Arpad Toth", "data" : [ [ "Perl 5", 2 ] - ] + ], + "id" : "Arpad Toth" }, { "name" : "Athanasius", - "id" : "Athanasius", "data" : [ [ "Perl 5", 2 ] - ] + ], + "id" : "Athanasius" }, { + "name" : "Bob Kleemann", + "id" : "Bob Kleemann", "data" : [ [ "Perl 5", 2 ] - ], - "id" : "Bob Kleemann", - "name" : "Bob Kleemann" + ] }, { - "name" : "Daniel Mantovani", - "id" : "Daniel Mantovani", "data" : [ [ "Perl 5", 1 ] - ] + ], + "id" : "Daniel Mantovani", + "name" : "Daniel Mantovani" }, { "data" : [ @@ -130,12 +130,11 @@ 1 ] ], - "name" : "Dave Cross", - "id" : "Dave Cross" + "id" : "Dave Cross", + "name" : "Dave Cross" }, { "name" : "Dave Jacoby", - "id" : "Dave Jacoby", "data" : [ [ "Perl 5", @@ -145,7 +144,8 @@ "Blog", 1 ] - ] + ], + "id" : "Dave Jacoby" }, { "data" : [ @@ -164,8 +164,8 @@ 2 ] ], - "name" : "Doug Schrag", - "id" : "Doug Schrag" + "id" : "Doug Schrag", + "name" : "Doug Schrag" }, { "data" : [ @@ -178,18 +178,18 @@ 2 ] ], - "name" : "Dr James A. Smith", - "id" : "Dr James A. Smith" + "id" : "Dr James A. Smith", + "name" : "Dr James A. Smith" }, { "id" : "Duncan C. White", - "name" : "Duncan C. White", "data" : [ [ "Perl 5", 2 ] - ] + ], + "name" : "Duncan C. White" }, { "data" : [ @@ -202,48 +202,47 @@ "name" : "Eddy HS" }, { + "name" : "Finley", "data" : [ [ "Perl 6", 2 ] ], - "name" : "Finley", "id" : "Finley" }, { - "id" : "Fred Zinn", - "name" : "Fred Zinn", "data" : [ [ "Perl 5", 1 ] - ] + ], + "id" : "Fred Zinn", + "name" : "Fred Zinn" }, { "id" : "Freddie B", - "name" : "Freddie B", "data" : [ [ "Perl 5", 2 ] - ] + ], + "name" : "Freddie B" }, { + "name" : "Gustavo Chaves", "data" : [ [ "Perl 5", 1 ] ], - "name" : "Gustavo Chaves", "id" : "Gustavo Chaves" }, { "name" : "JJ Merelo", - "id" : "JJ Merelo", "data" : [ [ "Perl 6", @@ -253,9 +252,12 @@ "Blog", 1 ] - ] + ], + "id" : "JJ Merelo" }, { + "name" : "Jaldhar H. Vyas", + "id" : "Jaldhar H. Vyas", "data" : [ [ "Perl 5", @@ -265,19 +267,17 @@ "Perl 6", 2 ] - ], - "name" : "Jaldhar H. Vyas", - "id" : "Jaldhar H. Vyas" + ] }, { + "name" : "Jeff", + "id" : "Jeff", "data" : [ [ "Perl 5", 2 ] - ], - "id" : "Jeff", - "name" : "Jeff" + ] }, { "data" : [ @@ -304,7 +304,6 @@ "name" : "Jim Bacon" }, { - "id" : "Jo Christian Oterhals", "name" : "Jo Christian Oterhals", "data" : [ [ @@ -319,9 +318,11 @@ "Blog", 1 ] - ] + ], + "id" : "Jo Christian Oterhals" }, { + "name" : "Joelle Maslak", "data" : [ [ |
