Perl
С проверкой ввода / предварительной сортировкой
Вы можете легко получить результат в виде LoL, если вам нужно сделать что-то более необычное, чем
просто верните строку.
#!/usr/bin/perl -w
use strict;
use warnings;
use Scalar::Util qw/looks_like_number/;
sub adjacenify {
my @input = @_;
# Validate and sort
looks_like_number $_ or
die "Saw '$_' which doesn't look like a number" for @input;
@input = sort { $a <=> $b } @input;
my (@output, @range);
@range = (shift @input);
for (@input) {
if ($_ - $range[-1] <= 1) {
push @range, $_ unless $range[-1] == $_; # Prevent repetition
}
else {
push @output, [ @range ];
@range = ($_);
}
}
push @output, [ @range ] if @range;
# Return the result as a string. If a sequence is size 1, then it's just that number.
# Otherwise, it's the first and last number joined by '-'
return join ', ', map { 1 == @$_ ? @$_ : join ' - ', $_->[0], $_->[-1] } @output;
}
print adjacenify( qw/1 2 3 5 7 9 10 11 12 14/ ), "\n";
print adjacenify( 1 .. 5 ), "\n";
print adjacenify( qw/-10 -9 -8 -1 0 1 2 3 5 7 9 10 11 12 14/ ), "\n";
print adjacenify( qw/1 2 4 5 6 7 100 101/), "\n";
print adjacenify( qw/1 62/), "\n";
print adjacenify( qw/1/), "\n";
print adjacenify( qw/1 2/), "\n";
print adjacenify( qw/1 62 63/), "\n";
print adjacenify( qw/-2 0 0 2/), "\n";
print adjacenify( qw/-2 0 0 1/), "\n";
print adjacenify( qw/-2 0 0 1 2/), "\n";
Выход:
1 - 3, 5, 7, 9 - 12, 14
1 - 5
-10 - -8, -1 - 3, 5, 7, 9 - 12, 14
1 - 2, 4 - 7, 100 - 101
1, 62
1
1 - 2
1, 62 - 63
-2, 0, 2
-2, 0 - 1
-2, 0 - 2
-2, 0 - 2
И хорошее рекурсивное решение:
sub _recursive_adjacenify($$);
sub _recursive_adjacenify($$) {
my ($input, $range) = @_;
return $range if ! @$input;
my $number = shift @$input;
if ($number - $range->[-1] <= 1) {
return _recursive_adjacenify $input, [ @$range, $number ];
}
else {
return $range, _recursive_adjacenify $input, [ $number ];
}
}
sub recursive_adjacenify {
my @input = @_;
# Validate and sort
looks_like_number $_ or
die "Saw '$_' which doesn't look like a number" for @input;
@input = sort { $a <=> $b } @input;
my @output = _recursive_adjacenify \@input, [ shift @input ];
# Return the result as a string. If a sequence is size 1,
# then it's just that number.
# Otherwise, it's the first and last number joined by '-'
return join ', ', map { 2 == @$_ && $_->[0] == $_->[1] ? $_->[0] :
1 == @$_ ? @$_ :
join ' - ', $_->[0], $_->[-1] } @output;
}