Ce golf nécessite un calcul factoriel divisé en plusieurs threads ou processus.
Certaines langues facilitent la coordination que d'autres, c'est donc langagnostique. Un exemple de code non golfé est fourni, mais vous devez développer votre propre algorithme.
Le but du concours est de voir qui peut proposer l'algorithme factoriel multicœur le plus court (en octets, pas en secondes) pour calculer N! tel que mesuré par les votes à la fin du concours. Il devrait y avoir un avantage multicœur, nous allons donc exiger qu'il fonctionne pour N ~ 10 000. Les électeurs devraient voter contre si l'auteur ne fournit pas d'explication valable sur la façon dont il répartit le travail entre les processeurs / noyaux et voter en fonction de la concision du golf.
Par curiosité, veuillez publier quelques numéros de performance. Il peut y avoir un compromis performance / score de golf à un moment donné, optez pour le golf tant qu'il répond aux exigences. Je serais curieux de savoir quand cela se produit.
Vous pouvez utiliser des bibliothèques de gros nombres entiers à noyau unique normalement disponibles. Par exemple, perl est généralement installé avec bigint. Cependant, notez que le simple fait d'appeler une fonction factorielle fournie par le système ne divisera normalement pas le travail sur plusieurs cœurs.
Vous devez accepter de STDIN ou ARGV l'entrée N et la sortie vers STDOUT la valeur N !. Vous pouvez éventuellement utiliser un deuxième paramètre d'entrée pour fournir également le nombre de processeurs / cœurs au programme afin qu'il ne fasse pas ce que vous verrez ci-dessous :-) Ou vous pouvez concevoir explicitement pour 2, 4, tout ce dont vous disposez.
Je posterai mon propre exemple de perl oddball ci-dessous, précédemment soumis sur Stack Overflow sous Algorithmes factoriels dans différentes langues . Ce n'est pas du golf. De nombreux autres exemples ont été soumis, dont beaucoup de golf mais pas beaucoup. En raison de la licence de partage, n'hésitez pas à utiliser le code dans tous les exemples du lien ci-dessus comme point de départ.
La performance dans mon exemple est terne pour un certain nombre de raisons: elle utilise trop de processus, trop de conversion chaîne / bigint. Comme je l'ai dit, c'est un exemple intentionnellement étrange. Il en calculera 5000! en moins de 10 secondes sur une machine à 4 cœurs ici. Cependant, une doublure plus évidente pour la boucle suivante / peut faire 5000! sur l'un des quatre processeurs en 3.6s.
Vous devrez certainement faire mieux que cela:
#!/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);
}
}
Mon intérêt pour cela est simplement (1) de soulager l'ennui; et (2) apprendre quelque chose de nouveau. Ce n'est pas un problème de devoirs ou de recherche pour moi.
Bonne chance!
