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

Hi Monks, I have some problem in number ranges.

I have tried the following coding, its working fine for three digit ranges (123-135) but it may vary in number of digits(12-14, 1234-1256).

use strict; my $a="123-135, 111-119, 127-130, 140-145"; print "Original : $a\n"; my @a = split (/\, /, $a); eval{s/^(\d{2})(\d+)\-(\d{2})(\d+)$/&digit($1,$2,$3,$4)/egsi;} for (@a +); print "Changed : "; print "$_\t" for @a; sub digit{ my ($f, $f1, $s, $s1)=@_; if ($f == $s){ $s=$s1; } else{ $s=~s/\d//; $s.=$s1; } return qq($f$f1-$s); }

But when i get the input like this, the above coding not works, is there any other way to do?

my $a="9-35, 11-19, 1272-1340, 1430-1435";

Is there any module?

Regards,
Velusamy R.

Replies are listed 'Best First'.
Re: Problem in Number Range
by jasonk (Parson) on Oct 03, 2005 at 15:10 UTC

    Is there any module?

    Yep, try Set::IntSpan.


    We're not surrounded, we're in a target-rich environment!
Re: Problem in Number Range
by ikegami (Patriarch) on Oct 03, 2005 at 15:28 UTC

    I'm nto sure what you are trying to do. If you're trying to extract the numbers, how about:

    $str = "123-135, 111-119, 127-130, 140-145"; @nums = split(/\s*[-,]\s*/, $str);

    or if you want to keep the pairs together:

    $str = "123-135, 111-119, 127-130, 140-145"; @nums = map { [ split(/-/, $_) ] } split(/\s*,\s*/, $str);

    Neither of the above validates. They assume the input is in the appropriate format.

Re: Problem in Number Range
by InfiniteSilence (Curate) on Oct 03, 2005 at 16:03 UTC
    The problem is in the algorithm. Assuming that a<b:

    #!/usr/bin/perl -w use strict; my $str = $ARGV[0]||"123-135, 111-119, 127-130, 140-145"; #borrowed from ikegami print "Original string \n" . $str; print "\nEnding string \n"; print show($_) for map { [ split(/-/, $_) ] } split(/\s*,\s*/, $str); sub show { my (@anums) = split //,$$_[0]; my (@bnums) = split //,$$_[1]; my ($output) = $$_[0] . '-'; my $switch = 0; if ($#anums != $#bnums){ return $$_[0]; } for(0..$#bnums){ if(defined($anums[$_])){ #if same, do nothing #if larger, include if (($bnums[$_] > $anums[$_])|| ($switch)){ $output .= $bnums[$_]; $switch++; } } } return $output . ' '; }

    Celebrate Intellectual Diversity

Re: Problem in Number Range
by cognizant (Pilgrim) on Oct 03, 2005 at 15:30 UTC
    Try this
    use strict; my $a="123-135, 1-119, 1270-1280, 1420-1452"; print "Original : $a\n"; my @a = split (/\, /, $a); eval{s/^([0-9]*)([0-9]+)\-([0-9]*)([0-9]+)$/&digit($1,$2,$3,$4)/egsi;} + for (@a); print "Changed : "; print "$_\t" for @a; sub digit{ my ($f, $f1, $s, $s1)=@_; my ($fs, $se); if($s =~ /([0-9]+)([0-9])/) { $fs = $1; $se = $2; } if ($f == $s) { $s=$s1; } elsif($f=~/^$fs/) { $s=$se.$s1; } else{ $s=~s/\d//; $s.=$s1; } return qq($f$f1-$s); }

      Here, i am getting output as

      Changed  : 123-35       1-19     1270-80 1420-52

      instead of

      Changed  : 123-35       1-119     1270-80 1420-52

      That is, "1-119" is a correct range, but its changed as "1-19". This case happening in all correct ranges like "1-10" also.

      Regards,
      Velusamy R.

        Modify the last snipped of the code as follows:
        else{ #$s=~s/\d//; $s.=$s1; }