use strict; use warnings; use Data::Dumper; use Carp; sub arrange { my $href=shift; my @range=@{$href->{range}}; my @sub=@{$href->{subrange}}; my $ary=$href->{arr}; my @ret; my $extent= $range[1] - $range[0]; croak "Range @range extent ".($extent+1)." different from array length:".scalar(@$ary) if $#$ary!=abs($extent); my $subextent = $sub[1] - $sub[0]; croak "Bad subextent @sub from range @range\n" if abs($subextent)>abs($extent); for (@sub) { croak "Bad subrange @sub from range @range" if ($_<$range[0] and $_<$range[1]) or ($_>$range[0] and $_>$range[1]); } my $dx=$subextent>=0 ? 1 : -1; $dx=-$dx if $extent<0; my $idx=$sub[0]; while ($#ret!=abs($subextent)) { push @ret,$ary->[$idx-$range[0]]; $idx+=$dx; } $href->{ret}=\@ret; unless (defined wantarray) { warn Dumper($href); } else{ return wantarray ? @ret : \@ret; } } foreach my $t ([6,5],[6,7],[8,9],[1,2]) { foreach my $r ([5,8],[8,5]) { eval { arrange({ arr => [qw(cero uno dos tres)], range => $r, subrange =>$t }); 1 } or warn "Test @$t failed on range @$r:\n$@"; } }