Extracting boundaries out of given condition in Pe

2019-04-17 17:20发布

I have a square-shape zone described by some conditions as follows:

x < b && x >= a && y < d && y >= c

I would like to extract the top-right and bottom-left corners coordinates. (Let's assume that the whole condition is given in $cond. Also, store the pairs in two lists @xy_b and @xy_t). For this example: @xy_b = (a , c) and @xy_t = (b, d).

enter image description here

REMARKS

  • The order of conditiones might be scrambled (e.g. y < d && x >= a && x < d && y >= c).
  • Expect both x < a and a > x
  • There is no condition like b =< x < a.
  • Expect conditions like: x <= b && x >= a or x < b && x > a (treat them the same unless you have a better convention to distinguish the,).
  • Expect some or all of the conditions may be missed. If one of the conditions is issued it should be consider correspondingly zero or infinity. For example in the following condition set:

    x < b && x >= a && y >= c

the upper limit for y must be infinity. If the lower limit is missing, it should be considered zero.

enter image description here

1条回答
三岁会撩人
2楼-- · 2019-04-17 18:02

It would be very easy to over complicate this problem.

However, the following is a proof of concept that attempts to break this down into the simplest regular expressions.

  1. If equal signs are ignored, just remove them.
  2. Match each variable boundary separately.
  3. For now assume each boundary can only be another variable.
  4. No other validation is done at this point for rules that aren't matched.

Here is the code that demonstrates this logic:

use strict;
use warnings;

while (<DATA>) {
    # Remove all equals signs since we ignore that data.
    s{=(?=[<>])|(?<=[<>])=}{}g;
    die "Invalid equal sign found in $_" if /=/;

    my %boundary;
    for my $var (qw(x y)) {
        my $min = /\b$var\b \s* > \s* (\w+)/x || /(\w+) \s* < \s* \b$var\b/x ? $1 : 0;
        my $max = /\b$var\b \s* < \s* (\w+)/x || /(\w+) \s* > \s* \b$var\b/x ? $1 : 'Inf';
        $boundary{$var} = {
            min => $min,
            max => $max,
        }
    }

    print "($boundary{x}{min}, $boundary{y}{min}) to ($boundary{x}{max}, $boundary{y}{max})\n\n"
}

__DATA__
x < b && x >= a && y < d && y >= c
y < d && x >= a && x < d && y >= c
x < b && x >= a && y >= c

Outputs:

(a, c) to (b, d)
(a, c) to (d, d)
(a, c) to (b, Inf)
查看更多
登录 后发表回答