package Math::Inequalities::Parser;
use strict;
use warnings;
use Carp qw/ croak /;
use Exporter qw/ import /;
our @EXPORT = qw/ parse_inequality /;
our $VERSION = '0.002';
sub parse_inequality {
my ($string) = @_;
$string ||= '';
if ($string =~ /^\s*(\d+)\s*<\s*n\s*<\s*(\d+)\s*$/ ) {
return ($1+1, $2-1);
}
elsif ($string =~ /^\s*(\d+)\s*<(=)?\s*n/ ) {
return ($1 + ($2 ? 0 : 1), undef);
}
elsif ($string =~ /^\s*(\d+)\s*>(=)?\s*n\s*$/ ) {
return (undef, $1 - ($2 ? 0 : 1));
}
elsif ($string =~ /^\s*n\s*>(=)?\s*(\d+)\s*$/ ) {
return ($2 + ($1 ? 0 : 1), undef);
}
elsif ($string =~ /^\s*n\s*<(=)?\s*(\d+)\s*$/ ) {
return (undef, $2 - ($1 ? 0 : 1));
}
elsif ($string =~ /^\s*(\d+)\s*$/ ) {
return ($1, $1);
}
elsif (length $string && $string !~ /^\s+$/) {
croak "Cannot parse '$string' as an inequality.";
}
return (undef, undef);
}
1;
=head1 NAME
Math::Inequalities::Parser - Minimum and maximum values allowed by an inequality.
=head1 SYNOPSIS
use Math::Inequalities::Parser;
my ($min, $max) = parse_inequality( ' 10 < n < 20 ' );
# $min = 11
# $max = 19
=head1 DESCRIPTION
Tiny library for parsing integer maximum and minimum out when given an arbitrary inequality.
Because getting this simple thing right was far harder
than it looked, and I never want to have to think about it again.
=head1 FUNCTIONS
=head2 parse_inequality
Parses an inequality string and returns a list of two values, the minimum and the maxium value
that string will allow.
=head1 TYPES OF INEQUALITY
=head2 VALUE
The simplest type, a single value, e.g. C<< 42 = Min 42, Max 42 >>.
=head2 n < VALUE
Maximum is VALUE - 1, Minimum is undefined, e.g. C<< n < 42 = Min undef, Max 41 >>.
=head2 n > VALUE
Minimum is VALUE +1, Maximum is undefined, e.g. C<< n > 42 = Min 43, Max undef >>.
=head2 n <= VALUE
Maximum is VALUE, Minimum is undefined, e.g. C<< n < 42 = Min undef, Max 42 >>.
=head2 n >= VALUE
Minimum is VALUE, Maximum is undefined, e.g. C<< n > 42 = Min 42, Max undef >>.
=head2 Cases with VALUE, followed by N.
Handled as above, but with minimum and maximum reversed as expected.
=head2 VALUE1 < n < VALUE2
Minimum is VALUE1 + 1, maximum is VALUE2 - 1, e.g C<< 42 < n < 200 = Min 43, Max 199 >>.
=head1 BUGS
=over
=item Does not handle C<< VALUE1 <= n <= VALUE2 >> or similar. Patches welcome.
=item Does not complain at impossible C<> combinations (e.g. C<< 5 < n < 4 >>) which result in a higher minumum than the maxiumum. Patches welcome.
=item Does not work with negative numbers. Patches welcome.
=item Always uses C<< n >> as the number identifier, this should be configureable at import time.
=item Uses Exporter (should use Sub::Exporter)
=item B work with floating point numbers. I consider this a feature.
=back
=head1 AUTHORS
Tomas Doran (t0m) C<< >>
Dave Lambley
=head1 COPYRIGHT & LICENSE
Copyright 2011 the above author(s).
This sofware is free software, and is licensed under the same terms as perl itself.
=cut