sub rangext {
    my $str = join ' ', @_;
    1 while $str =~ s{([+-]?\d+) ([+-]?\d+)}
        {$1.(abs($2 - $1) == 1 ? '~' : ',').$2}eg; 
    $str =~ s/(\d+)~(?:[+-]?\d+~)+([+-]?\d+)/$1-$2/g;
    $str =~ tr/~/,/;
    return $str;
}


my @test = qw(0  1  2  4  6  7  8 11 12 14
             15 16 17 18 19 20 21 22 23 24
             25 27 28 29 30 31 32 33 35 36
             37 38 39);
print rangext(@test), "\n";