Es hora de hacer los cálculos.


14

Introducción

Este es uno de mis acertijos matemáticos favoritos.

Dado un dígito (digamos 3) y la cantidad de veces que se usará ese dígito (digamos 5), genere 10 expresiones que resulten en 1, 2, 3, 4, 5, 6, 7, 8, 9 y 10 usando solo +, -, ×, ÷, ^ y √ (raíz) (los paréntesis pueden agrupar operaciones).

Por ejemplo:

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

Tenga en cuenta que todo lo anterior usa cinco 3 y las operaciones matemáticas y el resultado a 5. También puede usar un 3 antes de √ para denotar una raíz cúbica. Lo mismo ocurre con el uso de 4 antes de √ para denotar una cuarta raíz.

También tenga en cuenta que se pueden usar dos 3 para formar 33, o tres 3 para formar 333 y así sucesivamente.

Desafío

  • Se le darán dos números (ambos del 1 al 5) como argumento de función, STDIN o argumento de línea de comando.
  • El primer número denota qué dígito usar y el segundo número denota el número de veces que ese dígito se usará en la expresión.
  • Su programa debería generar una matriz de tamaño 10 (o 10 números separados por espacios) donde cada elemento denota si una expresión matemática (usando solo los operadores permitidos) que resulta en el (index + 1)número es posible o no usando un valor verdadero / falso.

Por ejemplo, si la entrada es

1 3

Entonces la salida debería ser

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

porque solo 1, 2, 3 y 10 se pueden expresar usando tres 1's.

Puntuación

  • Este es un por lo que gana la longitud mínima del código en bytes.

Prima

Print-em-all [−50]

Reste 50 de su puntaje si los elementos de la matriz de salida son iguales al número total de combinaciones plausibles para obtener el (index + 1)valor en lugar de valores verdaderos o falsos.

Por ejemplo, si sólo hay 3 posibles combinaciones de cinco 3 de que resultan a 5, a continuación, de la matriz de salida 4 º entrada debe ser 3.

Matemáticas extremas [−100]

Reste 100 de su puntaje si los elementos de la matriz de salida contienen al menos una de las expresiones reales que resultan del (index + 1)valor.

Por ejemplo, si el uso de cinco 3'S, 4 de la matriz de salida ésimo entrada puede ser (3^3 + 3)/(3 + 3), (33 - 3)/(3 + 3)o3 + 3/3 + 3/3

Overkilled [−200]

Resta 200 de tu puntaje si los elementos de la matriz de salida contienen todas las combinaciones posibles (separadas por |). Este bono se agrega además del bono Extreme Maths , por lo que obtienes −300 en total.

Por ejemplo, si usa cinco 3, el elemento de la matriz de salida debe ser(3^3 + 3)/(3 + 3)|(33 - 3)/(3 + 3)|3 + 3/3 + 3/3

Nota: Cualquiera de las dos expresiones para lograr el mismo resultado debe ser lógicamente diferente con un enfoque diferente en ambas.

Por ejemplo, obtener 5 usando cinco 3 3 + 3/3 + 3/3es igual 3/3 + 3 + 3/3o 3/3 + 3/3 + 3porque se toma el mismo enfoque para cada uno de ellos. (3^3 + 3)/(3 + 3)y (33 - 3)/(3 + 3)difieren, ya que el 30 en el numerador se logra a través de diferentes enfoques.

ACTUALIZACIÓN : Después de revisar todas las respuestas, se descubrió que todas las respuestas tenían imperfecciones debido a los casos límite de unario -y √. Por lo tanto, perder esos casos límite se consideró correcto en lo que respecta a la integridad de las respuestas.

Esta es una pregunta difícil, pero bastante interesante.

¡Feliz golf!


1
Lo siento, esto puede ser tonto, pero ¿cómo obtienes 10 con solo tres 1s?
FryAmTheEggman

3
@FryAmTheEggman 11-1
Optimizer

1
Ah, así que era tonto: p
FryAmTheEggman

44
Esa es una regla muy vaga. Puedo decidir que la raíz cuadrada de 1, la raíz cuadrada de la raíz cuadrada de 1, etc. son enfoques diferentes y tengo un número infinito de respuestas. ¿Es a + b diferente de b + a? ¿Es (-a) * (-b) diferente de b * a?
feersum

2
Soy consciente de esto, pero no puedo representar 4 ^ (4 ^ (4 ^ (4 ^ 4))) en ningún formato de número regular: almacenar 4 ^ (4 ^ (4 ^ 4)) ya que un entero ya necesita más bits que hay átomos en el universo). Entonces, a menos que use un sistema de álgebra computacional capaz de manejar tales números (si es que existe alguno), necesito tratarlos como casos especiales. Sin embargo, esto casi seguramente requiere más personajes de los que gano por exceso. Por lo tanto, estos premios no tienen sentido a menos que excluya un tanto las raíces cuadradas múltiples.
Wrzlprmft

Respuestas:


1

Python 3 (imperfecto), 449 - 300 = 149

Sufre de las mismas deficiencias que la solución de KSab : ningún operador unario, entre paréntesis, contiene expresiones equivalentes como (1+1)+1y 1+(1+1). Eliminé duplicados exactos pasando los resultados a set(). La salida podría ser un poco más fea para guardar algunos bytes, pero me gusta de esta manera. Tampoco hice raíces enésimas porque no parece que te compren mucho en este problema.

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 _]

Esto tardará varios minutos en ejecutarse si el segundo argumento es 5. Pruebe llamando 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 

4

Python (imperfecto) 493474-300 = 174

Hay una buena cantidad de problemas con esta solución, en primer lugar, que ignora cualquier exponente que sea demasiado grande (cualquiera en el que el exponente sea mayor que 100). De hecho, no creo que esto elimine ninguna posibilidad de entradas menores o iguales a 5, pero no estoy 100% seguro.

Otra cosa es que no considera ninguna raíz cuadrada unaria, ya que se complicaría (cualquier solución con cualquier término igual a 0 o 1 produciría un número infinito de soluciones). Tampoco considera ninguna negación unaria (el símbolo '-') por la misma razón, así como el hecho de que no estoy realmente seguro de si la pregunta la solicitó.

También consideré qué criterios deberían decidir si dos expresiones eran equivalentes, pero no pude encontrar una manera de definirlo rigurosamente de una manera que me pareció intuitiva, por lo que (al menos por ahora) no implementé nada de eso. Esto significa que arroja bastantes resultados, y también usa paréntesis de una manera bastante ingenua.

En una nota al margen, creo que esto podría incluir la línea de código más larga que he escrito, especialmente antes de que fuera completamente golfizada.

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]

Ejemplo: ('v' representa '√')

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

Encontré un par de cosas que puedes hacer para acortar 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

Lo siento, ese comentario se ve muy mal :( De todos modos, para explicar: al comparar 0, traté de negar la declaración, luego cambiar las consecuencias. También encontré algunos lugares para usar |y en &lugar de ory and. Ambos trucos podría usarse para acortar la última llamada a F, pero eso requeriría un poco de Demorgan's y me quedé sin tiempo de pico; p
FryAmTheEggman

@FryAmTheEggman Oh, esa es una buena captura, he actualizado mi respuesta con lo que publicaste y cuando tenga tiempo, miraré la última. Esos condicionales para verificar la validez de la entrada se
volvieron

¡+10 por la brillantez de las lambdas anidadas y ... evalme tomó bastante tiempo descubrir tu segunda línea! Sin embargo, creo que te he ganado en la "línea más larga". ;) Estoy de acuerdo en ignorar grandes exponentes; de hecho, creo que cualquier exponente mayor que 9 no será útil (excepto como un no-op cuando la base es 1).
DLosc

@DLosc Bueno, el único escenario que puedes tener es algo así 3 = 33 √ (3 ^ 33). En realidad, mientras escribo esto, me doy cuenta de que hay dos (¿probablemente las dos únicas) combinaciones que mi respuesta pierde 4 = (4^4) √ (4 ^ (4^4))y la expresión equivalente con 5s. Es cierto que las raíces no parecen agregar mucho al problema, ya que la gran mayoría de ellas se usan como no-ops en 0 o 1, no-ops cuando la raíz es 1, o simplemente para cancelar una potencia.
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)]")

Aquí hay una versión bastante poco golfista:

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)]

Para probar recomiendo cambiar (9) a algo más pequeño, ya que esta es la cantidad de raíces cuadradas múltiples que se tienen en cuenta, lo que tiene un gran impacto en el rendimiento.

Finalmente, esto me hizo preguntarme si el menos unario es realmente necesario en algún caso ...


1
Creo que tienes razón sobre el '-' unario que probablemente no agrega nada (al menos a la pregunta base sin las bonificaciones). El único escenario no trivial en el que puedo pensar sería algo parecido 1 = 3^3 * 3^(-3), pero incluso teniendo en cuenta estos, dudo que haya números para los que esta sea una posible solución cuando no hay otros.
KSab

1
Puede guardar 3 bytes utilizando en a**.5**%ilugar de a**(1/2**%i)calcular las múltiples raíces cuadradas.
DLosc

@DLosc: De hecho, gracias.
Wrzlprmft

Puede ahorrar seis bytes reduciendo la sangría de cuatro espacios a un espacio.
Beta Decay

@BetaDecay: nunca uso sangrías de cuatro espacios (estremecimiento), uso pestañas. Solo mira la fuente de mi publicación. Stack Exchange solo los representa como cuatro espacios.
Wrzlprmft

2

Mathematica - 246 caracteres (no se reclaman bonos)

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&]

Explicación

Función j concatena dos números a nivel de dígitos.

La función ztoma un resultado r, un número ny una lista de funciones L, cada una de las cuales opera con dos argumentos. Luego aplica la lista de funciones secuencialmente a los argumentos [r,n]usando recursividad, hasta que la lista esté vacía, con lo cual devuelve el resultado.

La función atoma un número ny varias copias t. Crea todas las tuplas de longitud (t-1) de la lista de funciones{Plus, f, Times, g, Power, h, j} y envía cada tupla a través de la función z, luego devuelve una lista de todos los números del 1 al 10 que se crearon.

Ejemplo de ejecución a[2,3]regresando{1, 2, 3, 6, 8} .

Limitaciones

Debido a que la lista de funciones se aplica secuencialmente, consumiendo una copia del número cada vez, puede perder algunas combinaciones. Por ejemplo, cuando se opera en cuatro dos, perdería 22/22 = 1 debido a su incapacidad para evaluar la lista de funciones fuera de servicio. Por supuesto, 2/2 * 2/2 = 1 cubre este caso.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.