#!/usr/local/bin/perl -w use Benchmark qw(cmpthese); use List::Util qw(shuffle); use Time::HiRes qw(gettimeofday tv_interval); @matrix = 1..20_000_000; # big enough $t0 = [gettimeofday]; @smatrix = shuffle(@matrix); $elapsed = tv_interval ( $t0 ); print "El tiempo fijo de sin_r_con_shuffle es $elapsed\n"; cmpthese(-1, { 'con_reemplaz' => sub { $x = return $matrix[int rand(@matrix)]; }, 'sin_reemplaz' => sub { $x = return sinreemplazamiento(); }, 'sin_reemp_2' => sub { $x = return sinreemp(); }, 'sin_r_con_shuffle' => sub { $x = return pop(@smatrix); }, 'splice' => sub { $x = return extract(); }, # 'extract_r' => sub { WRONG! # extract_r(); # }, }); sub sinreemplazamiento{ # WINNER # if (@matrix){ $ind = int rand (@matrix); ($matrix[$ind],$matrix[-1]) = ($matrix[-1],$matrix[$ind]); return pop @matrix; # }else{ # return undef; # } } sub sinreemp{ my $ind = int rand @matrix; @matrix[$ind,-1] = @matrix[-1,$ind]; return pop @matrix; } sub extract { # too slow my $index = int rand(@matrix); return splice(@matrix, $index, 1); } sub extract_r { # WRONG my $ind = int rand @matrix; my $rv = $matrix[$ind]; $matrix[$ind] = pop @matrix; # not valid, $ind could be == $#matrix return $rv; } __END__ Esto es una comparación de cuánto más cuesta extraer aleatorios sin posibilidad de repetición sobre el caso normal. La tercera posibilidad es hacer la trampa de barajar la matriz entera e ir extrayendo, pero esto sólo merecerá la pena si se van a extraer muchos elementos. BUGS No estoy muy seguro de que no haya otros algoritmos mejores o que la comparación este bien hecha, dado que depende del % a extraer de la matriz.