Maths Metagolf Mania!

12

Spécifications Mathemania:

Chaque morceau de code Mathemania commence par le numéro 2. Depuis le 2, vous pouvez effectuer les opérations suivantes:

  • e: Exponentiation. La valeur par défaut de cette commande est la quadrature du nombre.
  • f: Factorielle. La valeur par défaut de cette commande utilise la factorielle unique sur le nombre ( using f on 2 = 2! = 2).
  • r: Racine. La valeur par défaut de cette commande est la racine carrée du nombre.
  • c: Fonction plafond.
  • l: Fonction plancher.

Pour générer un nombre dans Mathemania, vous devez enchaîner ces commandes, qui sont exécutées de gauche à droite sur le nombre 2.

Exemples:

ef = (2^2)! = 4! = 24
rl = floor(sqrt(2)) = floor(1.4...) = 1
er = sqrt(2^2) = sqrt(4) = 2
efrrc = ceil(sqrt(sqrt((2^2)!)))
      = ceil(sqrt(sqrt(24)))
      = ceil(sqrt(4.89...))
      = ceil(2.21...)
      = 3

Les e, fet les rcommandes peuvent être modifiées par des commandes supplémentaires (Esta + qui commencent également hors avec 2comme numéro « de base ») pour générer différents exponentiations, factorielles et des racines en plaçant entre parenthèses après la fonction altérée et en plaçant les commandes Esta + à l' intérieur.

Par exemple, pour cube un nombre au lieu de le mettre au carré, vous pouvez mettre la commande pour 3après ecomme ceci:

e(efrrc) -> cube a number, "efrrc" = 3

REMARQUE: pour notre objectif, la commande factorielle ( f) commence par 2une seule factorielle. Donc, si vous le faites f(efrrc), cela sera évalué à une double factorielle, pas à une triple factorielle.

Pour les nfactorielles (par exemple, factorielles doubles = factorielles 2, factorielles triples = factorielles 3, etc.), le nombre de base est multiplié par le nombre qui est ninférieur à celui-ci, et ninférieur à cela, et ainsi de suite jusqu'à ce que le nombre final ne puisse pas être soustrait par nsans devenir 0ou négatif.

Par exemple:

7!! = 7 * 5 * 3 * 1 = 105 (repeatedly subtract 2, 1 is the last term as
                           1 - 2 = -1, which is negative)
9!!! = 9 * 6 * 3 = 162 (repeatedly subtract 3, 3 is the last term as
                        3 - 3 = 0, which is 0)

Pour plus d'informations, voir ici .

Vous pouvez l'insérer n'importe où et il sera traité par Mathemania comme une fonction unique:

e(efrrc)rc = ceil(sqrt(2^3))
           = ceil(2.82...)
           = 3

Vous pouvez également les imbriquer les uns dans les autres:

e(e(e)) = e(4th power)
        = (2^4)th power
        = 16th power

Pour un interprète du code Mathemania, cliquez ici (cheers, @ BradGilbertb2gills!)

Tâche:

Votre tâche consiste à créer un programme qui, lorsqu'il reçoit un entier positif nen entrée, génère un programme Mathemania qui, une fois exécuté, revient n.

Cependant, les programmes Esta + que vous générez doit être aussi petit (golfed) que possible, et votre score final est déterminé par la somme du nombre d'octets dans les programmes générés Esta + de l'échantillon, qui sont les entiers 10,000à 10,100. Le score le plus bas l'emporte.

Règles et spécifications:

  • Votre programme doit générer un programme Mathemania valide pour tout entier positif, mais seuls les nombres compris entre 10,000et 10,100seront testés.
  • Vous n'êtes pas autorisé à générer des programmes Mathemania qui n'entraînent pas de nombre entier. Si vous le faites, votre programme est disqualifié.
  • Pour les commandes e, fet r, le code Mathemania à l'intérieur de ces fonctions (par exemple e(efrrc), où efrrcest le code à l'intérieur de la fonction) doit correspondre à un entier positif ci-dessus 2. Si votre programme ne respecte pas cette règle, il est également disqualifié.
  • Votre programme doit renvoyer un programme Mathemania pour l'un des 101 nombres entiers de test en 30 minutes maximum sur un ordinateur portable moderne.
  • Votre programme doit renvoyer la même solution pour tout entier à chaque exécution. Par exemple, lorsqu'un programme reçoit une entrée 5et qu'il sort efrc, il doit sortir cela à chaque fois que l'entrée 5est donnée.
  • Vous ne pouvez coder en dur aucune solution pour un entier positif.
  • Afin de maximiser pleinement le potentiel de golf dans votre sortie, votre programme devrait être capable de gérer des entiers arbitrairement grands. Ce n'est pas une exigence, mais bonne chance si votre langue ne le supporte pas.

C'est le , donc le score le plus bas gagne!

clismique
la source
2
J'ai écrit un évaluateur pour cette langue en Perl 6 sur TIO Nexus.
Brad Gilbert b2gills
@ BradGilbertb2gills Wow, merci! Je mettrai un lien dans le défi.
clismique
Si l'entrée est efpar exemple, le code est-il autorisé à "sauter" et à simplement sortir le résultat avant l' efopération?
devRicher
@devRicher Si vous voulez dire que le programme "ef" est codé en dur au préalable, alors selon les règles actuelles, oui, vous êtes autorisé à le faire, car "ef" n'est pas compris entre 10 000 et 10 100. Je ne suis pas sûr que c'est ce que vous vouliez dire, et je pourrais changer les règles parce que le codage en dur rend le défi beaucoup trop facile, OMI.
clismique
1
J'écris un programme pour ce défi depuis quelques heures. Je pense que j'ai du code qui fonctionne, mais je ne peux pas exactement le tester correctement parce que certains des nombres générés par les factorielles sont absolument énormes et Python (où j'ai mon programme et mon interprète) ne peut pas prendre leur racine carrée. Je ne sais pas trop quoi faire du programme à ce stade. En passant, j'ai initialement mal lu et pensé que TOUS les 101 cas de test devaient s'inscrire dans le délai, ce qui semblait presque impossible. Tout le monde semble beaucoup plus raisonnable.
notjagan

Réponses:

1

Python 3.5, Score de ??

Pour l'instant, je n'ai pas de sortie pour les 101 entrées, mais une fois que j'exécuterai le programme pour tous les cas de test, je mettrai à jour mon score.

from math import *

memoized = {}
same = {}

def _(mathmania, n):
    memoized[n] = mathmania
    return mathmania

def is_prime(n):
    if n == 2:
        return True
    if n % 2 == 0 or n <= 1:
        return False
    for divisor in range(3, int(sqrt(n)) + 1, 2):
        if n % divisor == 0:
            return False
    return True

def pair_key(pair):
    low, high = pair
    diff = high - low
    if diff == 0:
        return 100
    low_done, high_done, diff_done = low in memoized, high in memoized, diff in memoized
    if high_done and memoized[high] == None or low_done and memoized[low] == None:
        return -1
    return (high_done + diff_done + (diff + 1 == low)) * 33 + low / high

def major_pairs(n):
    for i in range(n, int(sqrt(n)), -1):
        d = n / i
        if i - d < d - 1:
            break
        if d == int(d):
            yield (int(d), i)

def fact_key(pair):
    i, f = pair
    if i in memoized:
        if memoized[i] == None:
            return -1
        return 1
    return i / f

def near_fact(n, level):
    s = 4
    if n in same:
        s = same[n]
    for i in range(s, n ** 2 ** level):
        f = factorial(i)
        if f > (n - 1) ** 2 ** level:
            if f < (n + 1) ** 2 ** level:
                same[n] = i
                yield (i, f)
            else:
                return

def generate_mathmania(n):
    if n in memoized and memoized[n] != None:
        return memoized[n]
    memoized[n] = None
    binx = log(n, 2)
    if binx == int(binx):
        if binx == 2:
            return _("e", n)
        if binx == 1:
            return _("er", n)
        if binx == 0:
            return _("rl", n)
        return _("e(" + generate_mathmania(int(binx)) + ")", n)
    sq = sqrt(n)
    if sq == int(sq):
        return _(generate_mathmania(int(sq)) + "e", n)
    low, high = max(major_pairs(n), key=pair_key)
    if pair_key((low, high)) == -1:
        level = 1
        while True:
            try:
                i, f = max(near_fact(n, level), key=fact_key)
            except:
                level += 1
                continue
            if fact_key((i, f)) == -1:
                return _(generate_mathmania((n - 1) ** 2 + 1) + "rc", n)
            if f == n ** 2 ** level:
                return _(generate_mathmania(i) + "f" + "r" * level, n)
            if f < n ** 2 ** level:
                return _(generate_mathmania(i) + "f" + "r" * level + "c", n)
            return _(generate_mathmania(i) + "f" + "r" * level + "l", n)
    if low != 1:
        if low == high:
            return _(generate_mathmania(low) + "e", n)
        if high - low == 1:
            return _(generate_mathmania(high) + "f", n)
        return _(generate_mathmania(high) + "f(" + generate_mathmania(high - low + 1) + ")", n)
    good = None
    for i in range(n ** 2 - 1, (n - 1) ** 2, -1):
        if i in memoized:
            return _(generate_mathmania(i) + "rc", n)
        if not is_prime(i):
            good = i
    if good:
        return _(generate_mathmania(good) + "rc", n)
    for i in range((n + 1) ** 2 - 1, n ** 2, -1):
        if i in memoized:
            return _(generate_mathmania(i) + "rl", n)
        if not is_prime(i):
            good = i
    if good:
        return _(generate_mathmania(good) + "rl", n)
    return _(generate_mathmania((n - 1) ** 2 + 1), n)

De plus, je n'ai pas pu vérifier les sorties de certains des cas de test que j'ai essayés en raison de la taille du nombre, et à ce moment l'interprète en ligne de @ BradGilbertb2gills a expiré. Espérons que toutes les sorties fonctionnent.

notjagan
la source
J'ai un interprète en Python 2 (peut-être 3) qui devrait être capable de gérer une précision arbitraire ici . Copiez-le et collez-le dans votre IDE pour l'exécuter.
clismique
Quelles étaient certaines des sorties pour que je puisse éventuellement l'optimiser.
Brad Gilbert b2gills