Ten golf wymaga obliczeń czynnikowych podzielonych na wiele wątków lub procesów.
Niektóre języki ułatwiają koordynację niż inne, więc jest to język agnostyczny. Podano przykładowy kod bez golfa, ale należy opracować własny algorytm.
Celem konkursu jest sprawdzenie, kto może wymyślić najkrótszy (w bajtach, nie sekundach) wielordzeniowy algorytm czynnikowy do obliczania N! mierzona liczbą głosów po zakończeniu konkursu. Powinna istnieć wielordzeniowa przewaga, więc będziemy musieli działać dla N ~ 10 000. Głosujący powinni głosować za odrzuceniem, jeśli autor nie dostarczy prawidłowego wyjaśnienia, w jaki sposób rozkłada pracę na procesory / rdzenie i głosuje w oparciu o zwięzłość golfa.
Dla ciekawości proszę zamieścić kilka numerów wyników. W pewnym momencie może wystąpić kompromis między wynikami a golfem, idź z golfem, o ile spełnia on wymagania. Byłbym ciekawy, kiedy to nastąpi.
Możesz użyć normalnie dostępnych pojedynczych bibliotek dużych liczb całkowitych. Na przykład, Perl jest zwykle instalowany z bigintem. Należy jednak pamiętać, że zwykłe wywołanie funkcji systemowej udostępnianej przez system zwykle nie dzieli pracy na wiele rdzeni.
Musisz zaakceptować ze STDIN lub ARGV wejście N i wyjście do STDOUT wartości N !. Opcjonalnie możesz użyć drugiego parametru wejściowego, aby podać liczbę procesorów / rdzeni do programu, więc nie robi to, co zobaczysz poniżej :-) Lub możesz zaprojektować jawnie dla 2, 4, cokolwiek masz dostępne.
Poniżej opublikuję własny przykład perlowego nieparzystego, poprzednio przesłany na Przepełnienie stosu w ramach algorytmów czynnikowych w różnych językach . To nie jest golf. Przedstawiono wiele innych przykładów, wiele z nich to golf, ale wiele nie. Ze względu na licencje podobne do akcji, możesz użyć kodu we wszystkich przykładach w powyższym linku jako punkcie wyjścia.
Wydajność w moim przykładzie jest słaba z wielu powodów: używa zbyt wielu procesów, zbyt dużej konwersji łańcucha / biginta. Jak powiedziałem, jest to celowo nieparzysty przykład. Obliczy 5000! w niecałe 10 sekund na 4-rdzeniowej maszynie tutaj. Jednak bardziej oczywista dwuwarstwowa pętla dla / następnej pętli może zrobić 5000! na jednym z czterech procesorów w 3.6s.
Na pewno będziesz musiał zrobić to lepiej:
#!/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);
}
}
Moim zainteresowaniem jest po prostu (1) łagodzenie nudy; i (2) uczenie się czegoś nowego. To nie jest dla mnie zadanie domowe ani badawcze.
Powodzenia!
