On 28 Mar 02 at 12:16:20AM, Jonathan E. Paton wrote:
> The regular expression version I managed is:
>
> __BEGIN PERL__
> my @array = qw(3 4 1 2);
> ($max, $min)=("@array"=~/^([\d.]+)/, $1);
> "@array"=~/(?:^|[^\d.])([\d.]+)(?=[^\d.]|$)(?{$max<$1?$max=$1:{}})$/;
> "@array"=~/(?:^|[^\d.])([\d.]+)(?=[^\d.]|$)(?{$min>$1?$min=$1:{}})$/;
....
> Unfortunately, that requires three lines, not two
> which I had hoped for.
Of course, you could combine the max and min into a single expression,
but I don't think that's what you meant...
> I was looking for the form:
> ($max)="@array"=~/regex/;
> ($min)="@array"=~/regex/;
....
> I wanted the regular expression engine bump along
> the numbers... asserting that a number
> higher/lower didn't exist further along. Return
> as soon as that asssertion suceeds.
....
> 1. ...make it work the way I imagine
I believe so; see below.
> My attempt (broken) was:
>
> $max = $array =~ /([\d.]+)(?=([\d.]+)(??{$1>$2?"":"_"})))/;
a. ($max) = to get list context and return the matched part into it.
b. This approach may make spurious matches. You appear to be allowing
decimal points, in which case 1.2345 may be partially matched, thereby
beating, say, "27". You would need to be careful about each match,
possibly using (?>) and boundaries to avoid this.
c. You can use (?!) to mean "always fail" (instead of "_" - (?!) can
be used in any problem, meaning you don't need to disallow the use of
a specific character).
d. You are using a positive lookahead. This means your main match will
succeed as long as there is one number ahead that is less than the
current one. You need negative lookahead and a reversed test.
e. Your lookahead is missing an initial ".*". Lookahead is implicitly
anchored to the current location, just like any concatenated regex
elements. The regex engine just has a licence to start the overall
match at places other than the start of the string.
> Enjoy, but I suspect my diversionary tactics
> won't work... you'll all still manage to do
> better than myself in TPR(0,2) ;-)
Lucky for me I'm not involved.
To simplify the solution (and avoid problem (b) above), I have assumed
integers only for now. The solution works for max, since a full
integer will always be larger than an integer made from a substring of
its digits. To make a min version (which I might get around to) would
require ensuring that a complete number gets matched each time:
--------
#!/usr/local/bin/perl -w
use strict;
my @array = qw(675 3 499 1 2 900 23 45);
my ($max) = "@array"=~/(\d+)(?!.*(\d+)(??{$2>$1?"":"(?!)"}))/;
print "Maximum = $max\n";
--------
I'll try to find time later to do full versions for both max and min
with decimal points, unless someone else does it first.
It's an interesting academic exercise, but for Larry's sake, don't use
it in a real program!
Regards,
Ian