Un "schéma de rimes" est une chaîne de lettres a
à z
, de sorte que les premières occurrences des caractères soient dans l'ordre croissant (sans espaces), à partir de a
. Par exemple (avec les premières occurrences marquées):
abccdbebdcfa
^^^ ^ ^ ^
Le nombre de schémas de rimes de longueur N
est donné par les nombres de Bell B(N)
. ( OEIS A000110 )
Le défi
Votre tâche consiste à implémenter une énumération de ces schémas de rimes, c'est-à-dire un mappage bijectif d'entiers aux schémas de rimes. On vous donne un entier positif N <= 26
, ainsi qu'un entier non négatif 0 <= i < B(N)
. Vous pouvez également utiliser la plage 1 <= i <= B(N)
. Vous devez sortir un schéma de rimes de longueur N
, de sorte que chaque i
donne une chaîne différente.
Vous pouvez écrire un programme ou une fonction, en prenant une entrée via STDIN (ou l'alternative la plus proche), un argument de ligne de commande ou un argument de fonction et en sortant le résultat via STDOUT (ou l'alternative la plus proche), une valeur de retour de fonction ou un paramètre de fonction (out).
Vous pouvez utiliser des minuscules ou des majuscules (systématiquement).
Votre code doit être capable de gérer toute entrée valide dans un délai raisonnable (par exemple pas plus de quelques heures pour N = 26
, le pire des cas i
). Cela devrait permettre des solutions qui évoluent de façon exponentielle avec N
(pour les petites bases), même dans des langages lents, mais interdire les solutions qui évoluent de façon linéaire avec i
(c'est-à-dire B(N)
). En particulier, cela signifie que vous ne pouvez pas simplement parcourir tous les schémas de rimes valides N
jusqu'à ce que vous ayez supprimé les i
schémas.
Les règles de code-golf standard s'appliquent.
Exemples
L'affectation exacte des i
schémas à (c'est-à-dire l'ordre des schémas pour une donnée N
) dépend de vous. Mais supposons que vous ayez choisi l'ordre lexicographique, votre solution devrait correspondre au tableau suivant (avec -
une entrée non valide):
N\i 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 a - - - - - - - - - - - - - -
2 aa ab - - - - - - - - - - - - -
3 aaa aab aba abb abc - - - - - - - - - -
4 aaaa aaab aaba aabb aabc abaa abab abac abba abbb abbc abca abcb abcc abcd
Voici un court script CJam qui génère tous les schémas de rimes valides pour une longueur donnée (mais n'essayez pas plus de 10 ou vous attendrez un peu).
Défis liés
la source
N
), à condition que cela ne se révèle pas assez trivial et que j'étais tout simplement trop stupide pour la trouver.Réponses:
CJam,
6866 octetsEssayez-le en ligne.
Ceci est mon premier programme CJam. Il a commencé sa vie en tant que port de ma solution Perl et faisait initialement plus de 130 octets. D'autres suggestions de golf sont les bienvenues.
Comme avec mon programme Perl, il est en deux parties.
Pour déboguer les tableaux créés par add Partie 1
]_`o~
entre les parties 1 et 2. Si n est5
, les tableaux ressemblera à ceci:[[1 1 1 1 1 1] [1 2 3 4 5] [2 5 10 17] [5 15 37] [15 52]]
. Les 0 indices de chaque tableau ne sont pas utilisés, ils facilitent simplement le fait de ne pas avoir à calculer les décalages. Les tableaux sont calculés comme suit:Il conserve une copie de l'ancien tableau lors du calcul du suivant. Les tableaux sont lus et jetés dans l'ordre inverse par la partie 2.
la source
Python 2, 153
Il utilise l'ordre alphabétique et l'indexation basée sur 0.
Soit
l
la longueur d'un suffixe des lettres eta
le nombre de lettres distinctes utilisées dans la partie précédente. Ensuite, une fonctionp(l,a)
qui calcule le nombre de façons de sélectionner les lettres restantes pourrait être de 40 octets:Cependant, cela est trop lent pour le défi, donc à la place, les valeurs nécessaires sont précalculées et stockées dans le
u
tableau. A chaque étape du calcul, si la lettre suivante est celle desa
déjà utilisées, le n = k * p (l - 1, a) + n ' où k est la lettre indexée 0 de l'alphabet et n' est la valeur den
pour le prochain appel de fonction, qui contient les informations sur les lettres restantes. Si une nouvelle lettre est utilisée, alors n = a * p (l - 1, a) + n ' .la source
Haskell (GHC 7.10), 150 octets
L'opérateur
n # i
calcule lei
schéma de rimes de longueur (indexé zéro)n
. Il s'exécute en opérations O (n²) (grand entier), tirant parti des listes infinies paresseuses de Haskell pour la mémorisation automatique. Exemples de cycles:(Si le N maximum était de 25 au lieu de 26, le
.fromEnum
pourrait être supprimé, car B (25) tient dans un 64 bitsInt
.)la source
Perl 257 + 1 (indicateur -p) = 258Perl 182 + 10 (drapeaux -pMbignum) = 192
Merci à dev-nul d' avoir sauvé de nombreux octets! Je l'ai maintenant réécrit sur la base de ce que j'ai appris en faisant la version CJam.
Calcule la rime en ordre alphabétique croissant, 0 indexé.
Deux parties: la partie 1 fait
12890 octets et calcule une matrice pour la partie 2. La partie 2 fait12992 octets et fait quelques calculs simples pour calculer chaque lettre.Si je pouvais me débarrasser de la matrice et la remplacer par deux nombres simples, je pourrais calculer un seul chemin à travers la matrice pour chaque numéro et économiser beaucoup d'octets!Apparemment, cette idée ne fonctionne pas!Malheureusement, il ne produit pas les bonnes rimes pour les valeursi
supérieures à 9007199254740992, mais il fonctionne à merveille pour les valeurs faibles!J'ai ajouté la bibliothèque Bignum au coût de 11 octets.Il est exécuté à partir de la ligne de commande avecperl -pMbignum bell-rhyme.pl
.-pMbignum
= 10 octets. Il est également très rapide pour toute valeur d'entrée.la source
Oracle SQL 11.2,
412284283 octetsMalheureusement, il ne court que jusqu'à une longueur de 8. Toute valeur supérieure entraîne: ORA-01489: le résultat de la concaténation de chaînes est trop long
Non golfé
La vue a génère les: i lettres de la colonne a et leur valeur en b.
La vue récursive v prend la chaîne en cours de construction comme paramètre v, la valeur de la dernière lettre utilisée en c et la valeur de la plus grande lettre utilisée en n. Le paramètre n est égal à la longueur de la chaîne sans lettre en double, c'est à cela que sert l'expression rationnelle.
Une lettre est valide si sa valeur est <= la valeur de la plus grande lettre déjà utilisée ou si c'est la prochaine lettre à utiliser.
D'une manière ou d'une autre, la requête a besoin de la partie LONGUEUR (s) <: n pour s'exécuter, il doit manquer quelque chose dans le fonctionnement de la requête.
Le SELECT principal se charge de filtrer les entrées invalides et les chaînes plus courtes construites avant que la longueur cible ne soit atteinte.
Version 412 octets
N'essayez pas la requête de 412 octets avec 26. Elle met la base de données en mode restreint, au moins sur ma version xe exécutée dans un conteneur docker sur un macbook. Je pourrais essayer les exadata au travail, mais malheureusement, je dois encore travailler pour gagner ma vie.
la source
Mathematica, 136 octets
Pour être complet, voici mon implémentation de référence golfée. Contrairement aux réponses existantes, cela ne s'exécute pas en temps polynomial (il est exponentiel
N
avec la base 2) mais répond à la contrainte de temps (le pire des cas s'exécuterait encore en moins d'une demi-heure).L'idée est la suivante:
Pour chaque schéma de rimes, nous pouvons identifier les positions où le caractère maximal augmente jusqu'à présent:
Nous pouvons traiter ces marquages comme un nombre binaire qui facilite l'itération sur toutes ces structures. Nous devons itérer de 2 n-1 à 2 n (ou l'inverse), d'où la complexité temporelle exponentielle.
i
, nous le soustrayonsi
. Sinon, nous avons trouvé la structure du schéma de rimes demandé.i
(ou ce qui en reste) comme un nombre à base mixte, où les poids des chiffres sont déterminés par le nombre de caractères autorisés dans les positions restantes.Je me demande si cela permettrait une solution plus courte dans certaines des autres langues qui ont été soumises car cela ne nécessite aucune mémoisation ou précalcul.
la source