Brainflak Multiplication Metagolf

17

Cette question est la première de plusieurs défis d'anniversaire de Brain-flak conçus pour célébrer le premier anniversaire de Brain-Flak! Vous pouvez trouver plus d'informations sur l'anniversaire de Brain-Flak ici

L'été dernier, nous avons eu le Brain-flak Integer Metagolf , et les réponses qu'il a générées ont été très utiles à la communauté Brain-Flak depuis. La principale chose qui rend le Metagolf Integer si efficace est une technique appelée codage en dur de la multiplication.

Dans Brain-Flak, la multiplication de l'exécution est extrêmement coûteuse. L'extrait de multiplication le plus court connu est:

({}<>)({<({}[()])><>({})<>}{}<><{}>)

Découvert par Megatom

Cependant, il existe un moyen très simple de créer une multiplication du temps de compilation. Par exemple, le code suivant se multipliera par 5:

 (({})({})({})({}){})

Essayez-le en ligne!

Cela fonctionne car les expressions consécutives sont ajoutées ensemble. Chacun ({})ne fait rien à la pile ( {}apparaît et la (..)repousse immédiatement) et évalue ce qui se trouve au-dessus de la pile. Toutes ces expressions totalisent jusqu'à cinq fois ce qui était sur le dessus de la pile.

Pour tout, nl'expression de chaîne suivante fera un extrait qui multipliera le haut de la pile par n:

"("+"({})"*(n-1)+"{})"

Cela fonctionne en créant des nexpressions qui évaluent toutes en haut de la pile. Le premier n-1ne change rien et le dernier supprime le haut de la pile avant le push.

Pour les nombres composites, vous pouvez chaîner plusieurs expressions plus petites ensemble pour économiser des octets. Par exemple, vous pouvez multiplier par 25 en multipliant par 5 deux fois:

(({})({})({})({}){})(({})({})({})({}){})

C'est assez simple, et pour certains chiffres, cela fonctionne assez bien, mais il existe de meilleures façons de le faire. Par exemple, une méthode que j'ai trouvée utilise la représentation binaire du nombre. ( Voici une implémentation de python ) Cette nouvelle méthode est beaucoup plus efficace que la simple expression de chaîne montrée précédemment, mais ce n'est pas la fin, il existe toutes sortes de façons intéressantes de multiplier le code en dur et probablement une tonne que personne n'a encore découvert.

Je pense donc qu'il est temps de voir à quel point nous pouvons être bons.

Bref aperçu de Brain-Flak

Voici une description de tout ce que vous devez savoir sur Brain-Flak pour ce défi.

Brain-Flak a des "nilades" et des "monades". Les nilades sont des parenthèses qui n'ont rien en elles. Chaque nilade fait une chose et retourne une valeur. Pour ce défi, les deux nilades qui nous intéressent sont {}et <>. {}fait apparaître le haut de la pile active et renvoie sa valeur. <>bascule la pile active et la pile active, de sorte que la pile active devienne inactive et que la pile inactive devienne active, elle renvoie zéro.

Les monades sont des parenthèses avec des trucs à l'intérieur. Ils prennent un seul argument, la somme de tout ce qu'ils contiennent, effectuent parfois une action, puis renvoient une valeur. Les trois qui nous intéressent sont (...), <...>et [...]. La monade la plus importante pour ce défi (...)prend la valeur de l'intérieur et la pousse vers la pile active. Il renvoie ensuite l'argument. <...>et [...]sont toutes les deux des monades "inertes", c'est-à-dire qu'elles n'exécutent aucune action mais modifient plutôt la valeur à laquelle elles sont transmises. <...>renvoie toujours zéro quel que soit l'argument passé. Pendant ce temps, [...]renvoie toujours les temps d'argument -1.


Exemples de programmes avec explication

Si vous n'avez jamais programmé dans Brain-Flak, il peut être judicieux de regarder quelques exemples de programmes en utilisant les opérations décrites

({}{})

Cela ajoute les deux premiers chiffres de la pile. Chacun {}sort une valeur de la pile et (...)repousse sa somme.

({}[{}])

De même, cela soustrait le deuxième élément de la pile du premier. Comme avant, chaque {}valeur apparaît, mais [..]autour de la seconde, elle est ajoutée. Encore une fois, le (...)pousse la somme.

({}<{}>)

Cela supprime la deuxième valeur de la pile en conservant la valeur supérieure intacte. Cela fonctionne exactement comme les deux derniers, sauf que la deuxième valeur est réduite au silence par <...>le poussoir, ce qui ne fait que repousser la première valeur.

(({}))

Cela crée une deuxième copie de la valeur en haut de la pile. Il le fait en faisant sauter le haut de la pile avec {}sa valeur, le premier (..)le repousse ensuite en évaluant sa valeur. Le second (...)prend la valeur renvoyée par le premier et la pousse également dans la pile. créer une deuxième copie.

Tâche

Étant donné un entier, ncréez un extrait de cerveau-Flak propre à la pile qui multiplie le haut de la pile actuelle par n.

Vous êtes autorisé à utiliser les opérations Brain-Flak suivantes

(...) -> Push Monad, Pushes the result of its contents
<...> -> Zero Monad, Returns zero
[...] -> Negative Monad, Returns the opposite of its contents result
{}    -> Pop nilad, Pops the TOS and returns its value
<>    -> Switch nilad, Switches the active and inactive stack

Les autres opérations sont interdites aux fins du défi.

Notation

Votre score sera la durée cumulée de tous les programmes du n=2au n=10000. Assurez-vous d'inclure un lien vers la sortie de votre programme pour vérification.

Post Rock Garf Hunter
la source
1
Par intérêt, pourquoi les opérations 1 et boucle sont-elles interdites?
Neil
@Neil L'opérateur de hauteur de pile est également interdit.
Erik the Outgolfer le
1
@EriktheOutgolfer J'avais déjà interdit celui-là dans le métagolf entier de toute façon.
Neil
7
Les informaticiens sont bizarres. Ils inventent des langages de programmation impossibles à utiliser, intrinsèquement anti-golf, puis se mettent au défi d'écrire du code golfé pour résoudre des problèmes simples dans ce langage. Rien de plus ésotérique que cela. +1 bon monsieur.
Draco18s ne fait plus confiance au SE
1
@ Qwerp-Derp J'ai cherché à optimiser la sortie du programme Python lié (score actuel 681950) et j'ai trouvé une économie triviale de 4492 en utilisant [...], donc c'est un début.
Neil

Réponses:

2

Rubis, 669856

$answers = Hash.new{|hash,n|
  valid = []
  2.upto(n**0.5){|i|
    valid.push("("+hash[n/i]+")"+"({})"*(i-2)+"{}") if n%i == 0
  }
  valid.push("({})"+hash[n-1])
  (hash[n] = valid.min_by{|s| s.length})
}
$answers[1] = "{}"

def full_answer n
  "("+$answers[n]+")"
end

Ceci est une réponse de base rapide. 1000 premiers programmes min trouvés ici . (J'ai essayé de les publier tous, mais cela a surchargé la taille maximale de la boîte à colles.) Je peux ajouter une explication de code plus tard.

Exemples:

360:    ((((((({})(({}){}){})({}){})({}){}){}){}){})
4608:   (((((((((((({})({}){})({}){}){}){}){}){}){}){}){}){}){})
9991:   (({})((({})(((((((({})((({})({}){}){}){}){}){}){}){}){}){}){})({}){}){})
MegaTom
la source