Download the raw code.
class Point {
has Num $.x;
has Num $.y;
my $num_re = rx{ \-? \d+ \. \d+ };
method points ( Str $s ) {
return gather for $s.split(' ') {
/ ^ ($num_re) \, ($num_re) $ /
or say 'invalid input' and exit;
take Point.new( x => +$0, y => +$1 );
}
}
# This algorithm is a translation of pnpoly() from the
# comp.graphics.algorithms FAQ question q2.03, "How do I find if a point
# lies within a polygon?", http://www.faqs.org/faqs/graphics/algorithms-faq/
# It returns True for strictly interior points, False for strictly exterior.
# For points on the boundary, use a different algorithm.
method in_poly ( $p: @ps ) returns Bool {
my Bool $c = False;
my Point $j = @ps[*-1];
for @ps -> Point $i {
next unless $i.y <= $p.y < $j.y
or $j.y <= $p.y < $i.y;
$c = !$c if $p.x < $i.x
+ ($j.x - $i.x)
* ($p.y - $i.y)
/ ($j.y - $i.y);
$j = $i;
}
return $c;
}
}
my @poly = Point.points: $*IN.get;
my ($point) = Point.points: $*IN.get;
say $point.in_poly(@poly) ?? 'yes' !! 'no';
The code starts off with too few blank lines for my taste, but it quickly improves.
exit
ing with a non-zero status would be preferable to exit
ing with a zero
status, as the reason for exiting is invalid input. If not, might as well use
die
. (Except that's not an option here, because die
in Rakudo outputs
a backtrace no matter what you do -- "\n" trick from Perl 5 doesn't work --
and base-test
is very specific about exactly what error message it wants.)
The code is a bit more tied to the particulars of the input format than I had in mind. Exactly one space between coordinate pairs, no whitespace between coordinates. I don't really feel entitled to nag about this part, though; I could easily have added a crazy test in base-test were I so inclined.
This solution has more explicit types than most of the others. It does make a difference.
Nice, natural use of a class Point
. I like.
Not really a concern with this task. Clearly linear. No pun intended.
The semantics of $num_re
on line 4 -- yes, this is the same complaint as
with another contestant's code -- is already provided by STD and Rakudo as
dec_number
(except for the minus sign). Notice how dec_number
also
considers two cases of decimal numbers that $num_re
doesn't. It's my personal
opinion, but reinventing parsing wheels should be fairly stigmatized.
The $j = $i
on line 29 (along with its accomplice at line 20) feels like a
poor man's zipped for loop. Simple, but not exactly playing to the strengths of
Perl 6.
The gather
on line 6 is nice, but should probably have been a map
instead.
Or just a for
loop without an explicit return
, though that might be a
bit too subtle.
The code is short and to the point.