Как напечатать строки в STDIN в произвольном порядке на Perl?

Я хочу сделать обратный sort (1): рандомизировать каждую строку stdin до stdout в Perl.

Ответ 1

Бьюсь об заклад, реальные хакеры Perl разорвут это на части, но здесь все равно.

use strict;
use warnings;
use List::Util 'shuffle';

my @lines = ();
my $bufsize = 512;
while(<STDIN>) {
    push @lines, $_;
    if (@lines == $bufsize) {
        print shuffle(@lines);
        undef @lines;
    }
}
print shuffle(@lines);

Разница между этим и другим решением:

  • Не будет потреблять все входные данные, а затем рандомизировать его (память hog), но будет рандомизировать каждую строку $bufsize (не по-настоящему случайную и медленную, как собака по сравнению с другой опцией).
  • Использует модуль, который возвращает новый список вместо редактирования Fisher-Yates. Они взаимозаменяемы (за исключением того, что вам придется отделять печать от перетасовки). Для получения дополнительной информации введите perldoc -q rand в свою оболочку.

Ответ 2

Этот фрагмент perl делает трюк:

#! /usr/bin/perl
# randomize cat

# fisher_yates_shuffle code copied from Perl Cookbook 
# (By Tom Christiansen & Nathan Torkington; ISBN 1-56592-243-3)

use strict;

my @lines = <>;
fisher_yates_shuffle( \@lines );    # permutes @array in place
foreach my $line (@lines) {
    print $line;
}

# fisher_yates_shuffle( \@array ) : generate a random permutation
# of @array in place
sub fisher_yates_shuffle {
    my $array = shift;
    my $i;
    for ($i = @$array; --$i; ) {
        my $j = int rand ($i+1);
        next if $i == $j;
        @$array[$i,$j] = @$array[$j,$i];
    }
}

__END__

Ответ 3

use List::Util 'shuffle';
print shuffle <>

Или, если вы беспокоитесь о последних строках, не имеющих \n,

chomp(my @lines = <>);
print "$_\n" for shuffle @lines;