perlguy has asked for the wisdom of the Perl Monks concerning the following question:

Given a string such as:

$number_set = "6 7 8 9 10";

I want a regular expression to do a s/// on the string so that $number_set will now contain 6-10. For the curious, this is directly related to MJD's Perl Quiz of the Week.

After about 1600 failed attempts and manipulations, I am seeking the wisdom of the Perl Monks on this question. Here is the code I have so far, that doesn't quite work:

$number_set = "6 7 8 9 10"; $number_set =~ s/ (?>(\d+)) # prevent backtracking, so that # a failed match after a '10' # won't try 1 and 0 individually (?{local $first = $1}) # set $first eq to the number # just matched ( \s # match a space ((??{++$first})) # followed by the number after # the one just matched )+ # as many times as possible, # but at least once /$1-$+/gx; # and replace it with the original $1, # a dash, and the last number matched

As of right now, this sets $number_set to "6-7 8 9 10", which tells me that it matches the 6 first, followed by the 7, but then subsequent matches for 8, 9, and 10 failed.

Any and all tips are welcome.

$sentence[-2] .= 'failed'   # author's req. - dvergin 2002-11-28

Replies are listed 'Best First'.
Re: match-time pattern interpolation
by demerphq (Chancellor) on Nov 27, 2002 at 22:01 UTC
    I believe japhy did this first. No doubt his solution is better than mine. But heres what I did:
    my $str="1 2 3 10 6 7 8 11 12 13 14 15 161"; print "Before : $str\n"; # we use qr to avoid the use re 'eval'; my $rex=qr/(\d+) # match a number put it in $1 (?{$num=$1}) # set $num to be $1 (?: # dont capture all of this, \s+ # must have space between the n +umbers ( # capture into buffer $2 (??{'\b'.++$num.'\b'}) # match only the successor of +$num ) # end of buffer )+ # one or more /x; $str=~s/$rex/$1-$2/g; # and now substitute in print "After : $str\n";
    Outputs
    Before : 1 2 3 10 6 7 8 11 12 13 14 15 161 After : 1-3 10 6-8 11-15 161
    Update: Which really isnt that different to yours (which I actually didnt look at too closely until after I had done mine. Kinda funny :-)

    HTH

    --- demerphq
    my friends call me, usually because I'm late....

      looks like i was really, really close. i just needed a couple of \b's in my interpolation -- ((??{'\b' . ++$first . '\b'}))... thanks for the help!
Re: match-time pattern interpolation
by BrowserUk (Patriarch) on Nov 27, 2002 at 20:04 UTC

    This seems too easy, so it probably means I'm missing some boundary conditions or something??

    $number_set = "6 7 8 9 10"; $number_set =~ s/^(\d+\b).*(\b\d+)$/$1-$2/ and print $number_set; 6-10

    Okay you lot, get your wings on the left, halos on the right. It's one size fits all, and "No!", you can't have a different color.
    Pick up your cloud down the end and "Yes" if you get allocated a grey one they are a bit damp under foot, but someone has to get them.
    Get used to the wings fast cos its an 8 hour day...unless the Govenor calls for a cyclone or hurricane, in which case 16 hour shifts are mandatory.
    Just be grateful that you arrived just as the tornado season finished. Them buggers are real work.

      Oops. To clarify, the string could contain any number of numbers, some that are subsequent and some that are not.

      For example, $number_set could be "6 7 8 9 10 15 20 21", which after regex substitution would be "6-10 15 20-21".