Download the raw code.
use v6;
# sliding-window() with possibility to adjust the sliding-speed:
sub sliding-window(@scenery, $width, $speed) {
gather for 0, $speed ...^ * > +@scenery - $width -> $pos {
take @scenery[ $pos .. $pos + $width - 1 ];
}
}
my regex number { '-'? \d+ '.' \d+ }
my @polygon = $*IN.get.comb: /<&number>/;
my ($px, $py) = $*IN.get.comb: /<&number>/;
if +@polygon < 6 || +@polygon % 2 or ! defined ($px && $py) {
say 'invalid input';
exit;
}
# now, let us count the intersections of a straight line going down from the
# point in question, and the polygon's edges.
@polygon.push: @polygon[0,1]; # so that we get the Pn->P1 edge
my $intersections = 0;
my $ON_OUTLINE = 0; # should be: my constant $ON_OUTLINE
for sliding-window(@polygon, 4, 2) -> $ax, $ay, $bx, $by {
next if $ay & $by > $py # skip upper edges
or $ax & $bx < $px # skip left edges
or $ax & $bx > $px; # skip right edges
# function representing the edge: Ey(x) = mx + b
if $bx - $ax -> $dx {
my $m = ($by - $ay) / $dx;
my $b = $ay - $m * $ax;
given $m * $px + $b {
when * < $py { ++$intersections }
when * == $py {
$intersections = $ON_OUTLINE;
last;
}
}
}
elsif $ay | $by > $py {
$intersections = $ON_OUTLINE;
last;
}
}
say $intersections % 2 ?? 'yes' !! 'no';
Clearly laid out. Names are either understandable or explained.
It wasn't required anywhere, but exit
ing with a non-zero status would
be preferable if the reason for exiting is invalid input. People didn't
use die
because of the constraints base-test
put up; but doing a
normal exit
still feels wrongish.
The cases in the main loop are not well explained, but at least fairly easy to follow.
This solution stores coordinates flat inside an array, staggering x
and
y
coordinates. It's less of a data structure overhead than the other
solutions, but no less worthy of a comment.
Not much of a concern in this problem. The solution is clearly linear on the number of points.
Generally nice use of junctions to simplify condition expressions in this one.
TimToady++ pointed out a nice Perl 6 idiom that I stared at but managed to
miss: the if $bx - $ax -> $dx { ... }
on line 33. Clearly an appropriate
use of the lambda arrow.
The semantics of the regex number
on line 10... 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 number
doesn't. It's my
personal opinion, but reinventing parsing wheels should be fairly stigmatized.
The solution is nice and short.