Les entiers sont fastidieux à représenter dans Brain-Flak . Il y a 8 opérateurs:
() Evaluates to 1, but does not push anything on any stack
[] Evaluates to an indeterminate value for the purposes of this question
{} Removes the top of the stack and evaluates to it
<> Switches to or back from the alternate stack and evaluates to zero
(foo) Pushes the value of the expression foo to the stack and evaluates to it
[foo] Evaluates to the negation of foo
{foo} Evaluates the expression foo until the top of the stack is zero
<foo> Evaluates to zero but executes foo anyway
foo
peut être composé de plusieurs opérateurs, auquel cas ils sont évalués et additionnés. Par exemple, (()())
pousse 2
vers la pile (et évalue 2
aussi).
De toute évidence, le (()...())
mécanisme n'est pas utile dans Code Golf car un grand nombre prendrait des n*2+2
octets à représenter. Votre défi est donc d'écrire un programme ou une fonction qui produira en aussi peu d'octets que possible un programme Brain-Flak qui poussera un entier positif donné n
vers la pile active. Ce programme ne doit pas faire d'hypothèses sur le contenu existant des piles, il ne doit donc pas laisser les piles échangées ni ajouter ou supprimer des valeurs supplémentaires des piles.
Bien que votre programme ou fonction doit être capable de renvoyer un programme Brain-Flak fonctionnel pour toutes les entrées de 1 à 1 000 000, le gagnant sera le programme ou la fonction qui génère le plus petit ensemble de programmes Brain-Flak appropriés pour tous les 1061 nombres premiers compris entre 1 000 et 1 000. 10 000 . Vous devez noter la taille totale de vos sorties pour ces 1061 entrées dans le cadre de votre soumission. Votre programme ou fonction peut accepter l'entier et renvoyer le programme (chaîne) Brain-Flak dans l'un des formats d'E / S acceptables habituels. Les liens seront rompus en fonction de la taille de votre programme ou fonction.
la source
2n
est4^n catalan(n)
.(()()()...())
. De plus, si vous utilisez simplement des nombres premiers, cela pourrait manquer certaines optimisations possibles pour les composites.[]
pas défini pour ce défi? Je trouve étrange de mettre en œuvre 7 des 8 opérateurs. Quoi qu'il en soit, défi cool, je suis honoré que quelqu'un écrive un défi inspiré de ma propre langue![]
dans leur réponse.Réponses:
Python 2,
593945924458534584165839458250Ok voici ma solution.
La fonction pertinente est
push(n)
. Pour l'appeler, appuyez simplement sur l'entier que vous souhaitez représenter.Explication
La principale optimisation effectuée par le programme est le codage en dur de la multiplication. L'idée du codage en dur de la multiplication est assez simple. Vous poussez le nombre a, puis sautez et poussez-le pour créer une nouvelle valeur. Par exemple, pour multiplier par deux, vous pouvez utiliser le code suivant
((n){})
où n code produisant un nombre spécifique. Cela fonctionne parce que les deux(n)
et{}
ont une valeur de n.Cette idée simple peut être rendue plus complexe pour de plus grands nombres. Prenez par exemple 5, il a été découvert il y a quelque temps que la meilleure façon de multiplier par cinq était
(((n)){}){}{}
. Ce code fait deux copies du n multiplie une par 4 et ajoute les deux. En utilisant la même stratégie, je fais chaque multiplication basée sur la représentation binaire d'un nombre. Je n'entrerai pas dans les détails de la façon dont cela fonctionne en ce moment, mais je le fais en coupant la première de la représentation binaire et en remplaçant 0 par){}
et 1 par){}{}
. Il s'assure ensuite que n est poussé le nombre approprié de fois et équilibre toutes les parenthèses. (Si vous voulez savoir comment cela se fait, vous pouvez consulter mon code). Si vous voulez savoir pourquoi cela fonctionne, demandez-moi simplement un commentaire. Je ne pense pas que quiconque lise réellement toutes les mises à jour de mon message, j'ai donc laissé les explications.Lorsque l'algorithme tente de trouver un code dur de multiplication, il tente tous les facteurs premiers d'un nombre. Il ignore les facteurs composites car, à un moment donné, les facteurs composites pourraient toujours être exprimés de manière plus concise comme ses propres facteurs premiers, on ne sait pas si cela est toujours vrai.
L'autre mécanisme d'économie d'octets est un chercheur de solution polynomiale. Il existe certaines formes de polynômes faciles à représenter avec des boucles de décrémentation. Ces polynômes comprennent, mais sans s'y limiter, des nombres polygonaux. Cette optimisation trouve des polynômes qui correspondent au formulaire et crée le code qui les crée.
Sortie
bac à pâte
la source
n
est plus grande ou plus petite quen+1
if n % 3 == 2:
la fin de cette fonction d'un niveau.Brain-Flak, 64664
Essayez-le en ligne!
Voici mon code annoté
Explication
Cela ne met en œuvre que deux règles à partir de maintenant:
Si n est divisible par deux, retournez
(n/2){}
Si n n'est pas divisible par deux, retournez
n-1()
Il code également en dur tous les nombres inférieurs à 6.
la source
Perl,
592225915658460 caractèresn()
(11322660 caractères)(n){}()
(64664 caractères)((n)){}{}
(63610 caractères)((n)()){}{}
(63484 caractères) - ceci est un nouveau calcul(n){({}[()])}{}
(60748 caractères)n[m]
(62800 caractères)(n){m({}[l])}{}
(58460 caractères) - ceci est un nouveau calculLa formule pour ce dernier calcul est
n(n/l+1)/2+mn/l
. J'ai essayé d'autres calculs, mais ils ne sont plus utiles pour la sortie donnée. Le programme génère en fait toutes les valeurs jusqu'à 9999 mais répertorie ensuite les nombres premiers donnés et leur longueur totale.la source
&try($i * $i, "$numbers[$i]{({})({}[()])}{}");
, ce qui descend à 58032 quand j'ajoute également&try((3 * $i * $i - $i) / 2, "$numbers[$i]{({})({}[()])({})}{}");
(nombres carrés / pentagonaux) - c'est d' iciPython,
5913658676 caractèresFonction golf Brainflak Number:
Itération du nombre premier:
Sortie:
Pastebin
Explication:
Nous préremplissons une liste R de représentation de Brain-flak évaluant en entiers individuels sur une plage plus grande que nécessaire [1, m -1] pour définir notre fonction f . Les représentations sont formées en prenant la représentation inutilisée la plus basse (indexée par l ) et en en formant de nombreuses représentations nouvelles, en ne gardant que la plus courte. La représentation inutilisée la plus basse suppose que tous les numéros 1 à 1 ont reçu une représentation et que ces représentations ont déjà été utilisées pour produire de nouveaux nombres. Si une valeur inférieure à l obtient une représentation plus courte, nous devons revenir en arrière et reproduire les nombres à partir de ce point. La fonction f produit un programme enregistrant le nombre dans la pile en ajoutant des parenthèses.
Je ne connaissais aucun Brainflak lorsque j'ai commencé cela, et j'apprécie grandement la réponse d'Eamon Olive pour avoir souligné la formule des nombres triangulaires. La plupart du temps, j'ai généralisé la sommation et je me suis efforcé de vérifier les sommes et les différences. Ajouter beaucoup de multiples de sommes a eu un grand effet.
Pour ceux qui s'en soucient, voici le code à gratter que j'ai utilisé pour voir quelles formules en valaient la peine.
Formules de représentation:
(X){}
((X)){}{}
((((X)))){}{}{}{}
((((((X)))))){}{}{}{}{}{}
XY
X[Y]
(X){({}[Y])}{}
(X)({({}[Y])}{}){}
(X)(({({}[Y])}{})){}{}
(X)(({({}[Y])}{}){}){}
etc ...
la source
Lua 5.3, 57522
En fait, j'ai commencé à travailler là-dessus lorsque la question a été publiée, mais je l'ai oublié jusqu'à l'anniversaire de Brain-Flak.
Idée similaire aux autres réponses où des fonctions utiles connues sont utilisées pour construire de plus grands nombres à partir de bonnes représentations de nombres plus simples.
Une différence est qu'au lieu de résoudre des sous-problèmes en termes de nombres plus petits, je résous des sous-problèmes en termes de nombres avec des représentations plus courtes. Je pense que cela rend plus élégant de tirer parti des nombres négatifs ainsi que de gérer le cas où les petits nombres sont représentés en termes de plus grands nombres.
De plus, essayer de trouver tous les nombres qui peuvent être représentés dans une certaine taille plutôt que de représenter un nombre particulier le plus rapidement possible simplifie en fait certains calculs. Au lieu de travailler une formule à l'envers pour voir si elle peut être appliquée à un nombre, la formule peut être travaillée vers l'avant et appliquée à chaque nombre.
Une autre différence est que les solutions connues sont stockées en deux parties - un "préfixe" (facultatif) et un "suffixe" (plus comme un infixe). L'évaluation du préfixe devrait être ignorée lors du calcul du nombre donné - le préfixe ne contient que du code qui configure le suffixe à exécuter (généralement en poussant une ou plusieurs choses dans la pile). Donc, étant donné un préfixe et un suffixe, le nombre correspondant peut être poussé sur la pile avec
prefix(suffix)
.Cette division résout essentiellement le même problème que la
unpack
fonction dans la réponse de Wheat Wizard. Au lieu d'encapsuler le code avec<...>
uniquement pour l'annuler ultérieurement, ce code est simplement ajouté au préfixe.Dans quelques cas, le préfixe est en fait évalué (principalement pour l'opération de pseudo-exponentiation), donc son évaluation est également stockée. Cependant, cela ne pose pas vraiment de gros problème, car le générateur n'essaie pas de construire des nombres spécifiques. Cela semble impliquer théoriquement qu'il pourrait y avoir deux morceaux de code de la même longueur et générant le même nombre qui ne seraient pas redondants dans le cache en raison de différentes évaluations de préfixe. Je n'ai pas pris la peine de rendre compte de cela, car cela ne semble pas avoir beaucoup d'importance (au moins dans ce domaine).
J'imagine qu'il serait facile de réduire le nombre d'octets simplement en ajoutant plus de cas, mais j'en ai assez pour le moment.
J'ai couru à 1000000, mais j'ai seulement vérifié la santé mentale jusqu'à 100000.
Pastebin de sortie sur des nombres premiers donnés.
la source
k_limit
etk_max_len
faire? Je ne suis pas sûr de comprendre l'en-tête.k_max_len
. Il pourrait aussi facilement vérifier qu'il a trouvé tous les nombres que vous avez demandés après avoir traité chaque longueur, mais il m'a été utile de pouvoir limiter la longueur maximale pendant les tests afin que le programme s'exécute plus rapidement. (Le traitement de plus grandes longueurs peut être très lent.)k_limit
Est fondamentalement le paramètre d'entrée - il produira des programmes pour des nombres allant jusqu'à cela - en supposant qu'ilk_max_len
était suffisamment grand pour les trouver.rubis, 60246 octets
J'utilise un hachage. Je trouve le meilleur golf pour un nombre donné et utilise les plus petits pour trouver les plus grands.
Les hachages récursifs sont tellement amusants!
la source
Python, 64014 caractères
Je ne connaissais rien à brainflak avant ce défi et je ne l'ai joué qu'un peu sur tryitonline, donc il pourrait y avoir des raccourcis évidents que j'ai ratés. C'est une solution assez ennuyeuse, divise simplement l'entrée en
x=x/2+x%2
oux=x/3+x%3
, selon la plus courte des deux.Appelez-le ainsi:
b(42)
sortie sur pastebin
la source
Lua, 64664 octets
Le programme imprime la longueur totale des programmes et le programme pour le 203e premier (il y a une ligne que vous pouvez changer pour changer celle qui est imprimée, ou décommenter une ligne pour imprimer tous les programmes)
À l'heure actuelle, la seule optimisation est x = 2 * n + 1
J'espère que j'aurai le temps d'ajouter quelques optimisations supplémentaires pour réduire le score.
la source