Download the raw code.
# This is my favorite problem of the five.
# I plan to write a talk around this, to show off this cool feature.
class InExRange {
has $.type; # Is + or - for inclusion or exclusion.
has $.range;
method new ( $type, $start, $stop ) {
my $range = $start .. $stop;
self.bless: *, :$type, :$range;
}
# Int, because smartmatch against range in silently
# buggy if LHS is accidentally Str.
method in_range ( Int $num ) {
given self.type {
return ? ( $num ~~ self.range ) when '+';
return ? ( $num !~~ self.range ) when '-';
die "Can't happen";
}
}
}
grammar Range::Grammar {
token TOP { \n* <expr>+ }
token start { \d+ }
token stop { \d+ }
token type { <[+\-]> }
rule expr { <type> '[' <start> '..' <stop> ']' }
}
class Range::Actions {
method TOP ( $/ ) { make $<expr>».ast }
method expr ( $/ ) { make InExRange.new: ~$<type>, +$<start>, +$<stop> }
}
my ( $ranges_line, $num ) = $*IN.lines;
$num ~~ /\d+/
or say 'invalid input' and exit;
my $match = Range::Grammar.parse( $ranges_line, actions => Range::Actions.new )
or say 'no' and exit;
my @ranges = $match.ast.list;
say all(@ranges).in_range($num.Int) ?? 'yes' !! 'no';
Util likes to glom together the declarations in classes a bit more than I do, but that's OK. It only really "affects" the first class; with the grammar and the second class, it looks fine.
Lines 11 and 12 mention a bug in (i presume) Rakudo, but I've seen no corresponding bug report. (Correct me if I'm wrong.) Too bad, could have been some honour in reporting a bug along with your code submission.
Zero-status exit
on faulty condition (line 38)... people couldn't use die
because of the constraints base-test
put up. The one on line 41 is fine.
Range::Grammar
names the rules not after what they contain, but after their
semantic use. Kudos.
The method on line 13 could have been called a number of things, but I'm
pretty sure in_range
wasn't the best choice. Isn't something inside of
an excluding range "in range"? Not according to this method.
Fast, but wrong.
Line 44 uses a junction to join up the results. It thus commits the error of ignoring the order of the ranges (and thus the part of the problem description that said "Inclusions and exclusions are performed from left to right.").
It's nice to see grammars and actions being used this way. make $<expr>».ast
on line 31 is very expressive.
This one also has the build-up feel to it. The solution is short and sweet, and yet it contains a grammar and two classes.