Этот гольф требует, чтобы факторный расчет был разделен между несколькими потоками или процессами.
В некоторых языках это легче координировать, чем в других, поэтому это не зависит от языка. Приведен пример кода без правил, но вы должны разработать свой собственный алгоритм.
Цель конкурса - выяснить, кто может предложить самый короткий (в байтах, а не секундах) многоядерный факториальный алгоритм для вычисления N! по результатам голосования после закрытия конкурса. Должно быть многоядерное преимущество, поэтому нам потребуется, чтобы оно работало за N ~ 10000. Избиратели должны проголосовать, если автор не предоставит достоверного объяснения того, как это распределяет работу между процессорами / ядрами, и голосовать на основе лаконичности гольфа.
Для любопытства, пожалуйста, оставьте некоторые номера производительности. В какой-то момент может быть компромисс между игрой в гольф и игрой в гольф, если она соответствует требованиям. Мне было бы интересно узнать, когда это произойдет.
Вы можете использовать обычно доступные одноядерные библиотеки больших целых чисел. Например, perl обычно устанавливается вместе с bigint. Однако обратите внимание, что простой вызов предоставляемой системой факториальной функции обычно не распределяет работу между несколькими ядрами.
Вы должны принять от STDIN или ARGV вход N и вывести STDOUT значение N !. При желании вы можете использовать второй входной параметр, чтобы также указать количество процессоров / ядер для программы, чтобы она не выполняла то, что вы увидите ниже :-) Или вы можете явно указать 2, 4, что у вас есть.
Ниже я опубликую свой собственный пример Perl, который ранее был представлен в Переполнении стека в разделе Факторные алгоритмы на разных языках . Это не гольф. Было представлено множество других примеров, многие из них - гольф, но многие нет. Из-за общего лицензирования, не стесняйтесь использовать код в любых примерах по ссылке выше в качестве отправной точки.
Производительность в моем примере невелика по ряду причин: она использует слишком много процессов, слишком много преобразования строк / больших чисел. Как я уже сказал, это намеренно странный пример. Это будет рассчитывать 5000! менее чем за 10 секунд на 4-ядерном компьютере здесь. Тем не менее, более очевидные два цикла для / следующего цикла могут сделать 5000! на одном из четырех процессоров в 3.6s.
Вам определенно придется сделать лучше, чем это:
#!/usr/bin/perl -w
use strict;
use bigint;
die "usage: f.perl N (outputs N!)" unless ($ARGV[0] > 1);
print STDOUT &main::rangeProduct(1,$ARGV[0])."\n";
sub main::rangeProduct {
my($l, $h) = @_;
return $l if ($l==$h);
return $l*$h if ($l==($h-1));
# arghhh - multiplying more than 2 numbers at a time is too much work
# find the midpoint and split the work up :-)
my $m = int(($h+$l)/2);
my $pid = open(my $KID, "-|");
if ($pid){ # parent
my $X = &main::rangeProduct($l,$m);
my $Y = <$KID>;
chomp($Y);
close($KID);
die "kid failed" unless defined $Y;
return $X*$Y;
} else {
# kid
print STDOUT &main::rangeProduct($m+1,$h)."\n";
exit(0);
}
}
Мой интерес к этому просто (1) облегчение скуки; и (2) узнать что-то новое. Для меня это не домашняя работа или исследование.
Удачи!
