#! perl -slw use strict; use List::Util qw[ shuffle ]; our $MAX ||= 20; our $N = defined $N ? $N : 5; my @values = shuffle( 1 .. $MAX ); my @top = topNbsAB_p( $N, sub { $_[ 0 ] <=> $_[ 1 ] }, \@values ); print join(" ", @top); @top = topNbsAB_p( $N, sub { $_[ 1 ] <=> $_[ 0 ] }, \@values ); print join(" ", @top); @values = shuffle( 'A' .. 'Z' ); @top = topNbsAB_p( $N, sub { $_[ 0 ] cmp $_[ 1 ] }, \@values ); print join(" ", @top); @top = topNbsAB_p( $N, sub { $_[ 1 ] cmp $_[ 0 ] }, \@values ); print join(" ", @top); sub topNbsAB_p { my( $n, $CMP, $data ) = @_; return unless $n > 0; my @ST; my $selected = 0; for my $val ( @$data ) { $ST[ $selected++ ] = $val if $selected < $n; next if( $CMP->( $val, $ST[ $selected-1 ] ) < 0 ); my $left = 0; my $right = ($selected >1) ? $selected -1 : $selected; while( $left < $right ) { my $middle = ( $left + $right ) >> 1; if( $CMP->( $val, $ST[ $middle ] ) <= 0 ) { $left = $middle + 1; } else { $right = $middle; } } for( my $k = $selected; $k >= $left; $k-- ) { $ST[ $k ] = $ST[ $k - 1 ] }; $ST[ $left ] = $val; } return @ST[ 0 .. $selected-1 ]; } __END__ P:\test>junk3 -MAX=10 -N=0 P:\test>junk3 -MAX=10 -N=1 10 1 Z A P:\test>junk3 -MAX=10 -N=2 10 9 1 2 Z Y A B P:\test>junk3 -MAX=10 -N=10 10 9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9 10 Z Y X W V U T S R Q A B C D E F G H I J P:\test>junk3 -MAX=10 -N=11 10 9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9 10 Z Y X W V U T S R Q P A B C D E F G H I J K P:\test>junk3 -MAX=10 -N=26 10 9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9 10 Z Y X W V U T S R Q P O N M L K J I H G F E D C B A A B C D E F G H I J K L M N O P Q R S T U V W X Y Z P:\test>junk3 -MAX=10 -N=27 10 9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9 10 Z Y X W V U T S R Q P O N M L K J I H G F E D C B A A B C D E F G H I J K L M N O P Q R S T U V W X Y Z