> time perl dupsort.pl u 1e6 "1e9-1-int(rand(1e9))"
999498 unique items sorted.(9)
51.254s sort, 0.891s init.
real 0m52.371s
user 0m52.059s
sys 0m0.284s
> time perl dupsort.pl d 1e6 "1e9-1-int(rand(1e9))"
1000000 total items sorted.(9)
53.015s sort, 0.929s init.
real 0m54.151s
user 0m53.411s
sys 0m0.640s
> time perl dupsort.pl u 1e6 "1e9-1-int(rand(1e9))"
999459 unique items sorted.(9)
51.574s sort, 0.863s init.
real 0m52.634s
user 0m52.119s
sys 0m0.480s
> time perl dupsort.pl d 1e6 "1e9-1-int(rand(1e5))"
1000000 total items sorted.(9)
47.990s sort, 1.017s init.
real 0m49.207s
user 0m48.675s
sys 0m0.512s
> time perl dupsort.pl u 1e6 "1e9-1-int(rand(1e5))"
99998 unique items sorted.(9)
43.938s sort, 0.938s init.
real 0m44.949s
user 0m44.639s
sys 0m0.296s
> time perl dupsort.pl u 1e6 "1e9-1-int(rand(1e4))"
10000 unique items sorted.(9)
36.991s sort, 0.869s init.
real 0m37.921s
user 0m37.398s
sys 0m0.416s
> time perl dupsort.pl d 1e6 "1e9-1-int(rand(1e4))"
1000000 total items sorted.(9)
47.022s sort, 0.893s init.
real 0m48.104s
user 0m47.619s
sys 0m0.464s
> time perl dupsort.pl d 1e6 "1e9-1-int(rand(1e3))"
1000000 total items sorted.(9)
45.959s sort, 0.879s init.
real 0m47.030s
user 0m46.555s
sys 0m0.448s
> time perl dupsort.pl u 1e6 "1e9-1-int(rand(1e3))"
1000 unique items sorted.(9)
29.405s sort, 0.876s init.
real 0m30.344s
user 0m30.106s
sys 0m0.232s
> time perl dupsort.pl u 1e6 "1e9-1-int(rand(1e2))"
100 unique items sorted.(9)
22.611s sort, 0.909s init.
real 0m23.581s
user 0m23.201s
sys 0m0.244s
> time perl dupsort.pl d 1e6 "1e9-1-int(rand(1e2))"
1000000 total items sorted.(9)
41.071s sort, 0.907s init.
real 0m42.182s
user 0m41.619s
sys 0m0.500s
> time perl dupsort.pl d 1e6 "1e9-1-int(rand(1e1))"
1000000 total items sorted.(9)
39.703s sort, 0.886s init.
real 0m40.794s
user 0m39.874s
sys 0m0.524s
> time perl dupsort.pl u 1e6 "1e9-1-int(rand(1e1))"
10 unique items sorted.(9)
15.511s sort, 0.906s init.
real 0m16.479s
user 0m16.305s
sys 0m0.160s
> time perl dupsort.pl u 1e6 "1e9-1-int(rand(1e0))"
1 unique items sorted.(9)
10.219s sort, 0.861s init.
real 0m11.145s
user 0m10.961s
sys 0m0.180s
> time perl dupsort.pl d 1e6 "1e9-1-int(rand(1e0))"
1000000 total items sorted.(9)
36.356s sort, 0.857s init.
real 0m37.483s
user 0m36.978s
sys 0m0.508s
####
uniqmergesort mergesort
52.6s (~1e6) 54.1s (1e6)
44.9s (~1e5) 49.2s
37.8s (10k) 48.1s (third line, described below)
30.3s (1k) 47.0s
23.4s (100) 42.1s
16.5s (10) 40.4s
11.1s (1) 37.5s
####
#!/usr/bin/perl -l
use strict;
use Time::HiRes qw< time >;
sub compare {
$_[1] cmp $_[0]
}
sub mergesort {
my( $av )= @_;
_mergesort( $av, 0, $#$av );
return $av;
}
sub uniqmergesort {
my( $av )= @_;
$#$av -= _uniqmergesort( $av, 0, $#$av );
return $av;
}
sub _mergesort {
my( $av, $beg, $end )= @_;
if( $beg < $end-1 ) {
my $mid= int( ($beg+$end)/2 );
_mergesort( $av, $beg, $mid );
_mergesort( $av, $mid+1, $end );
merge( $av, $beg, $mid, $mid+1, $end );
} elsif( $beg == $end-1 ) {
my $cmp= compare( $av->[$beg], $av->[$end] );
if( -1 == $cmp ) {
@$av[$beg,$end]= @$av[$end,$beg];
}
}
}
sub _uniqmergesort {
my( $av, $beg, $end )= @_;
if( $beg < $end-1 ) {
my $mid= int( ($beg+$end)/2 );
my $d1= _uniqmergesort( $av, $beg, $mid );
my $d2= _uniqmergesort( $av, $mid+1, $end );
$d1 += uniqmerge( $av, $beg, $mid-$d1, $mid+1, $end-$d2 );
return $d1+$d2;
}
if( $beg == $end-1 ) {
my $cmp= compare( $av->[$beg], $av->[$end] );
if( -1 == $cmp ) {
@$av[$beg,$end]= @$av[$end,$beg];
return 0;
}
return 1 if 0 == $cmp;
}
return 0;
}
sub merge {
my( $av, $a, $b, $c, $d )= @_;
my $beg= $a;
my @i;
while( $a <= $b && $c <= $d ) {
my $cmp= compare( $av->[$a], $av->[$c] );
push @i, $a++
if -1 != $cmp;
push @i, $c++
if 1 != $cmp;
}
@$av[$beg..$d]= @$av[ @i, $a..$b, $c..$d ];
}
sub uniqmerge {
my( $av, $a, $b, $c, $d )= @_;
my $beg= $a;
my $end= $d;
my @i;
while( $a <= $b && $c <= $d ) {
my $cmp= compare( $av->[$a], $av->[$c] );
push @i, $a++
if -1 != $cmp;
push @i, $c++
if -1 == $cmp;
$c++, $end--
if 0 == $cmp;
}
@$av[$beg..$end]= @$av[ @i, $a..$b, $c..$d ];
return $d-$end;
}
if( 3 != @ARGV || $ARGV[0] !~ /^[ud]$/ ) {
print join ' ', @{mergesort([@ARGV])};
print join ' ', @{uniqmergesort([@ARGV])};
} else {
my $t= time();
my( $u, $n, $e )= @ARGV;
my $s= eval "package x; no strict; sub { $e }"
or die "Can't compile ($e): $@\n";
my @l;
$#l= $n-1;
@l= ();
push @l, $s->()
for 1..$n;
my $m= time();
if( 'u' eq $u ) {
uniqmergesort( \@l );
print 0+@l, " unique items sorted.(", length($l[0]), ")";
} else {
mergesort( \@l );
print 0+@l, " total items sorted.(", length($l[0]), ")";
}
my $e= time();
printf "%.3fs sort, %.3fs init.\n", $e-$m, $m-$t;
}