Il est temps de faire le calcul

14

introduction

Ceci est l'un de mes puzzles mathématiques préférés.

Étant donné un chiffre (disons 3) et le nombre de fois où utiliser ce chiffre (disons 5), générez 10 expressions qui donnent 1, 2, 3, 4, 5, 6, 7, 8, 9 et 10 en utilisant seulement +, -, ×, ÷, ^ et √ (racine) (les crochets sont autorisés pour regrouper les opérations).

Par exemple:

(3^3 + 3)/(3 + 3) = (33 - 3)/(3 + 3) = 3 + 3/3 + 3/3 = 5

Notez que tout ce qui précède utilise cinq 3 et les opérations mathématiques et aboutissent à 5. Vous pouvez également utiliser un 3 avant √ pour désigner une racine de cube. Il en va de même pour l'utilisation de 4 avant √ pour désigner une quatrième racine.

Notez également que deux 3 peuvent être utilisés pour former 33, ou trois 3 peuvent être utilisés pour former 333 et ainsi de suite.

Défi

  • Vous recevrez deux nombres (tous deux compris entre 1 et 5) comme argument de fonction, STDIN ou argument de ligne de commande.
  • Le premier nombre indique le chiffre à utiliser et le deuxième nombre indique le nombre de fois que ce chiffre doit être utilisé dans l'expression.
  • Votre programme doit générer un tableau de taille 10 (ou 10 nombres séparés par des espaces) où chaque élément indique si une expression mathématique (en utilisant uniquement les opérateurs autorisés) résultant en (index + 1)nombre est possible ou non en utilisant une valeur de vérité / fausse.

Par exemple, si l'entrée est

1 3

Ensuite, la sortie doit être

[1, 1, 1, 0, 0, 0, 0, 0, 0, 1]

car seuls 1, 2, 3 et 10 peuvent être exprimés à l'aide de trois 1.

But

  • Il s'agit d'un donc la longueur minimale du code en octets l'emporte.

Prime

Print-em-all [−50]

Soustrayez 50 de votre score si les éléments du tableau de sortie sont égaux au nombre total de combinaisons plausibles pour obtenir le (index + 1) valeur au lieu des valeurs véridiques ou fausses.

Par exemple, s'il n'y a que trois combinaisons possibles de cinq 3 années qui aboutissent à 5, puis 4 du tableau de sortie e entrée doit être 3.

Mathématiques extrêmes [−100]

Soustrayez 100 de votre score si les éléments du tableau de sortie contiennent au moins une des expressions réelles qui résultent de la (index + 1)valeur.

Par exemple, si vous utilisez cinq 3 de la 4 du tableau de sortie e entrée peut être (3^3 + 3)/(3 + 3), (33 - 3)/(3 + 3)ou3 + 3/3 + 3/3

Overkilled [−200]

Soustrayez 200 de votre score si les éléments du tableau de sortie contiennent toutes les combinaisons possibles (séparées par |). Ce bonus est ajouté au bonus Extreme Maths , vous obtenez donc -300 au total.

Par exemple, si vous utilisez cinq 3 de 4 du tableau de sortie e l'élément doit être(3^3 + 3)/(3 + 3)|(33 - 3)/(3 + 3)|3 + 3/3 + 3/3

Remarque: deux expressions quelconques pour obtenir le même résultat doivent être logiquement différentes avec une approche différente dans les deux.

Par exemple, pour obtenir 5 en utilisant cinq 3, 3 + 3/3 + 3/3c'est la même chose 3/3 + 3 + 3/3ou 3/3 + 3/3 + 3parce que la même approche est adoptée pour chacun d'eux. (3^3 + 3)/(3 + 3)et (33 - 3)/(3 + 3)diffèrent, car le 30 dans le numérateur est obtenu via différentes approches.

MISE À JOUR : Après avoir parcouru toutes les réponses, il a été constaté que toutes les réponses avaient des imperfections dues à des cas marginaux d'unaire- et √. Ainsi, l'absence de ces cas marginaux a été jugée acceptable dans la mesure où l'intégralité des réponses est impliquée.

C'est une question difficile, mais plutôt intéressante.

Bon golf!

Optimiseur
la source
1
Je suis désolé, cela peut être stupide, mais comment obtenez-vous 10 avec seulement trois 1s?
FryAmTheEggman
3
@FryAmTheEggman 11-1
Optimizer
1
Ah, donc j'étais stupide: p
FryAmTheEggman
4
C'est une règle très vague. Je peux décider que la racine carrée de 1, la racine carrée de la racine carrée de 1, etc. sont toutes des approches différentes et j'ai un nombre infini de réponses. A + b est-il différent de b + a? (-A) * (-b) est-il différent de b * a?
feersum
2
Je suis conscient de cela, mais je ne peux pas représenter 4 ^ (4 ^ (4 ^ (4 ^ 4))) dans n'importe quel format de nombre normal - le stockage de 4 ^ (4 ^ (4 ^ 4)) car un entier a déjà besoin de plus de bits qu'il n'y a d'atomes dans l'univers). Donc, à moins que j'utilise un système d'algèbre informatique capable de gérer de tels nombres (s'il en existe un), je dois les traiter comme des cas spéciaux. Cependant, cela nécessite presque certainement plus de personnages que je gagne en étant trop qualifié . Par conséquent, ces récompenses sont inutiles, sauf si vous excluez quelque peu plusieurs racines carrées.
Wrzlprmft

Réponses:

1

Python 3 (imparfait), 449 - 300 = 149

Souffre des mêmes défauts que la solution de KSab : aucun opérateur unaire, entièrement entre parenthèses, ne contient des expressions équivalentes comme (1+1)+1et 1+(1+1). J'ai éliminé les doublons exacts en transmettant les résultats à set(). La sortie pourrait être un peu plus moche pour économiser quelques octets, mais j'aime ça. Je n'ai pas non plus fait de racines nième car il ne semble pas qu'ils vous achètent beaucoup dans ce problème.

R=range
E=lambda z:eval(z.replace("^","**"))
def m(d,n):_=R(1,11);s={i:[]for i in _};r=R(1,n);n<2 and s[d].append(str(d));d=str(d);t=[[(d*i,i)for i in r]]+[[]]*n;h=[];[(h.append("("+A+o+B+")"),t[l].append((h[0],a+b))if a+b<n else E(*h)in _ and s[E(*h)].append(h[0]),h.pop())for l in r for j in R(l)for A,a in t[j]for k in R(l)for B,b in t[k]if a+b<=n for o in"+-*/^"if(o=="^"and-~-(0<E(B)<9)or 0==E(B)and"/"==o)-1];[print(i,set(s[i])or'')for i in _]

Cela prendra plusieurs minutes pour s'exécuter si le deuxième argument est 5. Testez en appelant m(digit, number):

>>> m(1,3)
1 {'((1*1)^1)', '(1^(1+1))', '((1-1)+1)', '((1/1)/1)', '((1*1)*1)', '((1^1)/1)', '(1*(1*1))', '(1^(1*1))', '(1+(1-1))', '(1^(1^1))', '((1^1)*1)', '(1^(1/1))', '((1/1)*1)', '(1-(1-1))', '(1/(1^1))', '(1/(1*1))', '(1/(1/1))', '(1*(1^1))', '((1+1)-1)', '((1*1)/1)', '((1^1)^1)', '(1*(1/1))', '((1/1)^1)'}
2 {'(1*(1+1))', '((1^1)+1)', '((1+1)/1)', '((1*1)+1)', '((1+1)^1)', '(1+(1*1))', '((1/1)+1)', '(1+(1^1))', '(1+(1/1))', '((1+1)*1)'}
3 {'((1+1)+1)', '(1+(1+1))'}
4 
5 
6 
7 
8 
9 
10 {'(11-1)'}
>>> m(3,3)
1 {'((3/3)^3)'}
2 {'(3-(3/3))', '((3+3)/3)'}
3 {'(3-(3-3))', '((3-3)+3)', '((3/3)*3)', '(3*(3/3))', '(3/(3/3))', '((3+3)-3)', '(3^(3/3))', '(3+(3-3))', '((3*3)/3)'}
4 {'((3/3)+3)', '(3+(3/3))'}
5 
6 {'((3*3)-3)'}
7 
8 
9 {'(3+(3+3))', '((3+3)+3)', '((3^3)/3)'}
10 
DLosc
la source
4

Python (imparfait) 493 474 - 300 = 174

Il y a un bon nombre de problèmes avec cette solution, premièrement, elle ignore tout exposant trop grand (tout exposant supérieur à 100). En fait, je ne pense pas que cela supprime toutes les possibilités d'entrées inférieures ou égales à 5, mais je ne suis pas sûr à 100%.

Une autre chose est qu'elle ne prend pas en compte les racines carrées unaires, car cela se compliquerait (toute solution avec un terme égal à 0 ou 1 produirait un nombre infini de solutions). Il ne considère pas non plus de négation unaire (le symbole «-») pour la même raison, ainsi que le fait que je ne suis pas vraiment sûr si la question le demandait.

J'ai également examiné les critères qui devaient décider si deux expressions étaient équivalentes, mais je n'ai pas trouvé de moyen de le définir rigoureusement d'une manière que je trouvais intuitive, donc (pour le moment du moins) je n'ai pas mis en œuvre quelque chose comme ça. Cela signifie qu'il produit pas mal de résultats et qu'il utilise également des parenthèses de manière assez naïve.

Sur une note latérale, je pense que cela pourrait inclure la plus longue ligne de code unique que j'ai écrite, surtout avant qu'elle ne soit entièrement jouée.

R=range
F=lambda s:lambda a,b:eval(s)
L=lambda D,N:[(int(str(D)*N),str(D)*N)]+[(o(u,v),"(%s%s%s)"%(s,c,t))for p in R(1,N)for u,s in L(D,p)for v,t in L(D,N-p)for c,o in[('+',F('a+b')),('-',F('a-b')),('*',F('a*b')),('/',F("1.*a/b if b else''")),('^',F("''if(a<0 and int(b)!=b)|(a and b<0)|(b>99)else a**b")),('v',F("b**(1./a)if a and(a>=0 or b)and(b>=0 or int(1./a)==1./a)&(1./a<99)else''"))]if o(u,v)!='']
A=L(*input())
for i in R(11):
 for v,s in A:
    if v==i:print i,s[1:-1]

Exemple: ('v' représente '√')

2,3

0 2*(2-2)
0 2v(2-2)
0 (2-2)*2
0 (2-2)/2
0 (2-2)^2
1 2^(2-2)
1 2-(2/2)
1 2v(2/2)
1 (2/2)^2
2 2v(2+2)
2 2+(2-2)
2 2-(2-2)
2 2v(2*2)
2 2*(2/2)
2 2/(2/2)
2 2^(2/2)
2 2v(2^2)
2 (2+2)-2
2 (2+2)/2
2 (2-2)+2
2 (2*2)-2
2 (2*2)/2
2 (2/2)*2
2 (2/2)v2
2 (2^2)-2
2 (2^2)/2
3 2+(2/2)
3 (2/2)+2
6 2+(2+2)
6 2+(2*2)
6 2+(2^2)
6 (2+2)+2
6 (2*2)+2
6 (2^2)+2
8 2*(2+2)
8 2*(2*2)
8 2*(2^2)
8 (2+2)*2
8 (2*2)*2
8 (2^2)*2
KSab
la source
J'ai trouvé quelques choses que vous pouvez faire pour raccourcir L:L=lambda D,N:[(int(str(D)*N),str(D)*N)]+[(o(u,v),"(%s%s%s)"%(s,c,t))for p in R(1,N)for u,s in L(D,p)for v,t in L(D,N-p)for c,o in[('+',F('a+b')),('-',F('a-b')),('*',F('a*b')),('/',F("1.*a/b if b else''")),('^',F("''if(a<0 and int(b)!=b)|(a and b<0)or b>100 else a**b")),('v',F("''if a==0 or(b<0 and int(1./a)!=(1./a))or(b or a<0)or(1./a)>100 else b**(1./a)"))]if o(u,v)!='']
FryAmTheEggman
Je suis désolé, ce commentaire semble vraiment mauvais :( Quoi qu'il en soit, pour expliquer: en comparant contre 0, j'ai essayé de nier la déclaration, puis d'échanger les conséquences. J'ai également trouvé quelques endroits à utiliser |et &au lieu de oret and. Ces deux astuces pourrait être utilisé pour raccourcir le dernier appel à F, mais celui-ci nécessiterait des Demorgan et j'ai manqué de temps de bec; p
FryAmTheEggman
@FryAmTheEggman Oh c'est une bonne prise, j'ai mis à jour ma réponse avec ce que vous avez posté et quand j'aurai le temps je regarderai la dernière. Ces conditions pour vérifier la validité de l'entrée sont
devenues
+10 pour l'éclat des lambdas imbriqués et - evalil m'a fallu un certain temps pour comprendre votre deuxième ligne! Je pense que je vous ai battu sur "la plus longue ligne unique", cependant. ;) Je suis d'accord pour ignorer les grands exposants; en fait, je pense que tout exposant supérieur à 9 ne sera pas utile (sauf en tant que non-op lorsque la base est 1).
DLosc
@DLosc Eh bien, le seul scénario que vous pouvez avoir est quelque chose comme 3 = 33 √ (3 ^ 33) . En fait, au moment où j'écris ceci, je me rends compte que deux (probablement les deux seules?) Combinaisons que ma réponse manque sont 4 = (4^4) √ (4 ^ (4^4))et l'expression équivalente avec l' 5art. Certes, les racines ne semblent pas ajouter beaucoup au problème, car la grande majorité d'entre elles sont utilisées comme no-ops sur 0 ou 1, no-ops lorsque la racine est 1, ou simplement pour annuler une puissance.
KSab
3

Python 3-349 346

r=range
l=lambda s:eval("lambda a"+s)
def T(u,f,X,Y):
    try:return u(f(X,Y))
    except:0
c=l(',x:{x}.union(*[{u(int("1"*a)*x)}|{T(u,f,X,Y)for j in r(1,a)for X in c(j,x)for Y in c(a-j,x)for f in[l(",b:a%sb"%o)for o in{"**"}|set("+-*/")]+[l(",b:a**b**-1")]}for u in[l(":-a")]+[l(":a**.5**%i"%k)for k in r(9)]])')
R=l(",i:[{n+1}<c(i,a)for n in r(10)]")

Voici une version plutôt non golfée:

def R(x,i):
    # Unary Operations
    U = [lambda a:-a] + [eval("lambda a:a**(1/2.**%i)" % j) for j in range(9)]
    # Binary Operations
    F = [eval("lambda a,b:a%sb"%o) for o in ["+","-","*","/","**"]] + [lambda a,b:a**(1./b)]

    def combos(i):
        L = {x}
        for u in U:
            # 3, 33, 333, etc.
            L |= {u(int(str(x)*i))}

            for j in range(1,i):
                for X in combos(j):
                    for Y in combos(i-j):
                        for f in F:
                            # To avoid trouble with division by zero, overflows and similar:
                            try:
                                L |= {u(f(X,Y))}
                            except:
                                pass
        return L

    return [n in combos(i) for n in range(1,11)]

Pour les tests, je recommande de changer (9) à quelque chose de plus petit, car il s'agit du nombre de racines carrées multiples prises en compte, ce qui a un impact énorme sur les performances.

Enfin, cela me fait me demander si le moins unaire est réellement nécessaire dans certains cas…

Wrzlprmft
la source
1
Je pense que vous avez raison à propos de l'unaire '-' n'ajoutant probablement rien (au moins à la question de base sans les bonus). Le seul scénario non trivial auquel je puisse penser serait quelque chose du genre 1 = 3^3 * 3^(-3), mais même en tenant compte de ceux-ci, je doute qu'il existe des chiffres pour lesquels c'est une solution possible lorsqu'il n'y en a pas d'autres.
KSab
1
Vous pouvez enregistrer 3 octets en utilisant a**.5**%iau lieu de a**(1/2**%i)pour calculer les racines carrées multiples.
DLosc
@DLosc: En effet, merci.
Wrzlprmft
Vous pouvez économiser six octets en réduisant le retrait de quatre espaces à un espace.
Beta Decay
@BetaDecay: Je n'utilise jamais de retraits à quatre espaces (frisson), j'utilise des tabulations. Il suffit de regarder la source de mon message. Stack Exchange les rend simplement en quatre espaces.
Wrzlprmft
2

Mathematica - 246 caractères (aucun bonus réclamé)

f[x_,y_]:=x-y
g[x_,y_]:=x/y
h[x_,y_]:=x^(1/y)
j[x_,y_]:=FromDigits@Join[IntegerDigits@x,{y}]
z[{r_,n_,L_}]:=z[{L[[1]][r,n],n,Rest@L}]
z[{r_,n_,{}}]:=r
a[n_,t_]:=Union@Select[z[{n,n,#}]&/@Tuples[{Plus,f,Times,g,Power,h,j},t-1],IntegerQ@#&&0<#<11&]

Explication

Une fonction j concatène deux chiffres en chiffres.

La fonction zprend un résultat r, un nombre net une liste de fonctions L, chacune fonctionnant sur deux arguments. Il applique ensuite la liste des fonctions de manière séquentielle aux arguments [r,n]utilisant la récursivité, jusqu'à ce que la liste soit vide, après quoi il renvoie le résultat.

La fonction aprend un certain nombre net un certain nombre de copies t. Il crée tous les tuples de longueur (t-1) à partir de la liste des fonctions {Plus, f, Times, g, Power, h, j}et envoie chaque tuple via la fonction z, puis retourne une liste de tous les nombres 1 à 10 qui ont été créés.

Exemple d'exécution a[2,3]retournée {1, 2, 3, 6, 8}.

Limites

Étant donné que la liste des fonctions est appliquée séquentiellement, consommant une copie du nombre à chaque fois, certaines combinaisons peuvent manquer. Par exemple, en fonctionnant sur quatre deux, il manquerait 22/22 = 1 en raison de son incapacité à évaluer la liste des fonctions en panne. Bien sûr, 2/2 * 2/2 = 1 couvre ce cas.

phosgène
la source