Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Generating ranges of numbers

by nandymamith (Novice)
on Jun 30, 2016 at 10:03 UTC ( [id://1166921]=perlquestion: print w/replies, xml ) Need Help??

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

Can anybody help in getting the solution for me. Below are the INPUT and the OUTPUT elements that I am expecting is as shown below :

INPUT @array = ("1","2","3","5","6","7",9"); OUTPUT @ranges = ("1:3","5:7","9");

Please Note: Do not use any CPAN libraries to extract the OUTPUT

Replies are listed 'Best First'.
Re: Generating ranges of numbers
by Anonymous Monk on Jun 30, 2016 at 10:09 UTC

    Sounds like homework.

    Can you describe the algorithm you would use in your own words?

    But most importantly: Why is "1 2 3" turned into "1:3" but "5 6 7" turned into "5:6 7"? What rule does that follow?

      Sorry Monk, my mistake. The OUTPUT should be in the below format :

      OUTPUT @ranges = ("1:3","5:7","9");
Re: Generating ranges of numbers
by thezip (Vicar) on Jun 30, 2016 at 18:00 UTC

    It is definitely more fun if you *don't* use Set::IntSpan...

    #!/usr/bin/perl use strict; use warnings; use Set::IntSpan; my @array = ("1", "2", "3", "5", "6", "7", "9"); my $set = Set::IntSpan->new(\@array); my $out = join(',', $set->D($set->holes())); print $out, "\n";
    OUTPUT: 1-3,5-7,9

    *My* tenacity goes to eleven...
Re: Generating ranges of numbers
by choroba (Cardinal) on Jun 30, 2016 at 11:24 UTC
    I changed the input and output to avoid the issue mentioned by Anonymous Monk.

    #! /usr/bin/perl use warnings; use strict; my @input = (1, 2, 3, 5, 6, 8, 10); my @ranges = ($input[0]); for my $i (1 .. $#input) { warn "\t@ranges"; if ($input[ $i - 1 ] + 1 == $input[$i]) { $ranges[-1] = (split /:/, $ranges[-1])[0] . ":$input[$i]"; } else { push @ranges, $input[$i]; } } use Test::More tests => 1; is_deeply \@ranges, [ '1:3', '5:6', '8', '10' ];

    And, for the sake of TIMTOWTDI:

    my @input = (1, 2, 3, 5, 6, 8, 10); my $last = $input[0]; my @ranges = map { ($_ > $#input || $input[$_] != 1 + $input[ $_ - 1 ]) ? do { my $s = $last . (":$input[ $_ - 1 ]") x ($last != $input[ +$_ - 1 ]); $last = $input[$_]; $s } : (); } 1 .. $#input + 1;

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: Generating ranges of numbers
by Anonymous Monk on Jun 30, 2016 at 13:43 UTC
    #!/usr/bin/perl -l # http://perlmonks.org/?node_id=1166921 use strict; use warnings; my @array = ("1","2","3","5","6","7","9"); my @ranges = split ' ', "@array" =~ s/\b(\d+)\K (?=(\d+)(??{$1 != $2 - 1 && 'fail' }))/:/gr =~ s/:[\d:]+:/:/gr; print "@ranges";
Re: Generating ranges of numbers
by hdb (Monsignor) on Jul 01, 2016 at 08:06 UTC

    Another version:

    use warnings; use strict; my @input = (-1, 1, 2, 3, 5, 6, 8, 10, 11, 12, 13 ); my @ranges = ( [ $input[0] ] ); for (@input[1..$#input]) { if( $_ == $ranges[-1][-1]+1 ) { $ranges[-1][1] = $_; } else { push @ranges, [ $_ ]; } } $" = ":"; print "@$_\n" for @ranges;

    Update: replaced "eq" with "==" above.

Re: Generating ranges of numbers
by Marshall (Canon) on Jun 30, 2016 at 15:49 UTC
    Also in the interest of TIMTOWTDI. A bit more wordy than other solutions, but straightforward...
    #!usr/bin/perl use strict; use warnings; my @array = ("1","2","3","5","6","7","9"); my @working = @array; #copy to "consume" my $start = shift @working; my $current= $start; my @output; while (my $next = shift @working) { if ($next == $current+1) { $current = $next; } else { got_result(); $start = $current = $next; } } got_result(); print join ",",@output; #prints: 1:3,5:7,9 sub got_result { if ($start == $current ) { push @output, "$start"; } else { push @output, "$start:$current"; } }
Re: Generating ranges of numbers
by Anonymous Monk on Jun 30, 2016 at 14:10 UTC
    #!/usr/bin/perl -l # http://perlmonks.org/?node_id=1166921 use strict; use warnings; my @array = ("1","2","3","5","6","7","9"); my @ranges = "@array" =~ s/\b(\d+)\K (?=(\d+)(??{$1 != $2 - 1 && 'fail' }))/:/gr =~ s/:\S+:/:/gr =~ /\S+/g; print "@ranges";
Re: Generating ranges of numbers
by Anonymous Monk on Jun 30, 2016 at 17:43 UTC

    More TIMTOWTDI hehehe

    #!/usr/bin/perl -l # http://perlmonks.org/?node_id=1166921 use strict; use warnings; my @array = ("1","2","3","5","6","7","9"); my @ranges = "@array" =~ s/\b(\d+)(?{$1})\K(?: (\d+)\b(??{++$^R!=$2}))+/:$2/gr =~ /\S+/g; print "@ranges";

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1166921]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (7)
As of 2024-04-19 09:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found