Contexte
La dernière fois, nous avons compté des groupes d'une taille donnée , ce qui n'est pas un problème trivial.
Cette fois, nous ne compterons que les groupes abéliens , c'est-à-dire les groupes avec une opération commutative. Formellement, un groupe (G, *) est abélien si x * y = y * x pour tous pour x, y dans G .
Le problème devient beaucoup plus simple de cette façon, nous allons donc les compter efficacement.
Tâche
Écrivez un programme ou une fonction qui accepte un entier non négatif n en entrée et imprime ou renvoie le nombre de groupes abéliens non isomorphes d'ordre n .
Une façon de calculer le nombre de groupes - que nous désignerons par A (n) - est d'observer ce qui suit:
A (0) = 0
Si p est un nombre premier, A (p k ) est égal au nombre de partitions entières de k . (cf. OEIS A000041 )
Si n = mk , et m et k sont co-premiers, A (n) = A (m) A (k) .
Vous pouvez utiliser cette méthode ou toute autre méthode de calcul de A (n) .
Cas de test
Input Output
0 0
1 1
2 1
3 1
4 2
5 1
6 1
7 1
8 3
9 2
10 1
11 1
12 2
13 1
14 1
15 1
16 5
17 1
18 2
19 1
20 2
4611686018427387904 1300156
5587736968198167552 155232
9223371994482243049 2
(extrait de OEIS A000688 )
Règles supplémentaires
Avec suffisamment de temps, de RAM et une taille de registre pouvant contenir l'entrée, votre code devrait fonctionner (en théorie) pour des entiers arbitrairement grands.
Votre code doit fonctionner pour tous les entiers compris entre 0 et 2 63 - 1 et se terminer en moins de 10 minutes sur ma machine (Intel i7-3770, 16 Go de RAM, Fedora 21).
Veuillez vous assurer de chronométrer votre code pour les trois derniers cas de test avant de soumettre votre réponse.
Les éléments intégrés qui banalisent cette tâche, comme Mathematica
FiniteAbelianGroupCount
, ne sont pas autorisés.Les fonctions intégrées qui renvoient ou comptent les partitions entières d'un nombre ou les partitions d'une liste ne sont pas autorisées.
Les règles de code-golf standard s'appliquent.
la source
Réponses:
CJam (
3938 octets)Démo en ligne
Cela suit la ligne suggérée de trouver une factorisation première (
mF
) puis de calculer les partitions de chaque puissance et de prendre leur produit.Il existe deux cas particuliers pour
mF
: il tient compte au0
fur0^1
et à1
mesure1^1
. Ce dernier ne nécessite pas de traitement particulier: il existe un groupe abélien de taille 1 et une partition de 1. Cependant, zéro nécessite un cas particulier.Le comptage des partitions utilise une récurrence pour
A008284(n, k)
, le nombre de partitions den
dansk
parties. Dans OEIS, il est donnémais je pense qu'il est plus utile de considérer la somme comme allant de
1
àmin(k, n-k)
.Dissection
la source
CJam,
50494743 octetsUtilise la
mF
factorisation intégrée de CJam et un port mémorisé de cette fonction de numéro de partition Python:ou non golfé:
Comme la réponse de @ RetoKoradi, le dernier cas prend environ 17 secondes sur l'interpréteur hors ligne, car c'est le temps qu'il faut à CJam pour factoriser le nombre. C'est pourquoi je l'ai laissé de côté suite de tests en ligne .
Explication complète
la source
Mathematica,
969488 octetsJe ne suis pas très compétent avec Mathematica, mais j'ai pensé que j'essaierais. Merci à @ MartinBüttner pour -6 octets.
Cela utilise la formule de fonction de génération pour les partitions entières.
la source
CJam, 58 octets
Essayez-le en ligne
Le tout dernier exemple de test prend une éternité (ou au moins plus longtemps que je ne voulais attendre) dans l'interpréteur en ligne, mais se termine en 17 secondes avec la version hors ligne de CJam sur mon ordinateur portable. Tous les autres exemples de test sont à peu près instantanés.
Cela utilise le CJam
mF
opérateur , qui donne la factorisation principale avec les exposants. Le résultat est alors le produit du nombre de partitions pour chaque exposant.La partie principale du code consiste à calculer le nombre de partitions. J'ai implémenté l'algorithme récursif sur la page wikipedia , en utilisant l'
j
opérateur qui prend en charge la récursivité avec la mémorisation.Explication:
la source