Brainflak Multiplication Metagolf

17

¡Esta pregunta es la primera de varios desafíos de cumpleaños de Brain-flak diseñados para celebrar el primer cumpleaños de Brain-Flak! Puede encontrar más información sobre el cumpleaños de Brain-Flak aquí

El verano pasado tuvimos el Brain-flak Integer Metagolf , y las respuestas que generó han sido muy útiles para la comunidad Brain-Flak desde entonces. Lo principal que hace que Integer Metagolf sea tan eficiente es una técnica llamada Multiplicación de hardcoding.

En Brain-Flak, la multiplicación en tiempo de ejecución es extremadamente costosa. El fragmento de multiplicación más corto conocido es:

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

Descubierto por Megatom

Sin embargo, hay una manera muy simple de crear una multiplicación de tiempo de compilación. Por ejemplo, el siguiente código se multiplicará por 5:

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

Pruébalo en línea!

Esto funciona porque las expresiones consecutivas se agregan juntas. Cada uno ({})no hace nada a la pila ( {}aparece y lo (..)empuja hacia atrás) y se evalúa según lo que esté encima de la pila. Todas estas expresiones juntas suman hasta cinco veces lo que haya en la parte superior de la pila.

Para cualquiera de nlas siguientes expresiones de cadena, se creará un fragmento que multiplicará la parte superior de la pila por n:

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

Esto funciona al hacer nexpresiones que todos evalúan en la parte superior de la pila. El primero en n-1realidad no cambia nada y el último elimina la parte superior de la pila antes del empuje.

Para números compuestos, puede encadenar varias expresiones más pequeñas juntas para guardar bytes. Por ejemplo, puedes multiplicar por 25 multiplicando por 5 dos veces:

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

Esto es bastante simple, y para algunos números funciona bastante bien, sin embargo, hay mejores maneras de hacerlo. Por ejemplo, un método que se me ocurrió utiliza la representación binaria del número. ( Aquí hay una implementación de Python ). Este nuevo método es mucho más efectivo que la simple expresión de cadena mostrada anteriormente, pero no es el final, hay todo tipo de formas interesantes para codificar la multiplicación y probablemente una tonelada que aún nadie ha descubierto.

Así que creo que es hora de ver qué tan buenos podemos ser.

Breve descripción de Brain-Flak

Aquí hay una descripción de todo lo que necesitará saber sobre Brain-Flak para este desafío.

Brain-Flak tiene "nilas" y "mónadas". Nilads son paréntesis que no tienen nada dentro de ellos. Cada nilad hace una cosa y devuelve un valor. Para este desafío, las dos nilas que nos interesan son {}y <>. {}abre la parte superior de la pila activa y devuelve su valor. <>cambia la pila activa y la pila activa en, de modo que la pila activa se vuelve inactiva y la pila inactiva se vuelve activa, devuelve cero.

Las mónadas son paréntesis con cosas dentro de ellas. Toman un solo argumento, la suma de todo lo que hay dentro de ellos, a veces realizan una acción y luego devuelven un valor. Los tres de estos que nos interesan son (...), <...>y [...]. La mónada más importante para este desafío (...)toma el valor del interior y lo empuja a la pila activa. Luego devuelve el argumento. <...>y [...]son mónadas "inertes", es decir, no realizan ninguna acción, sino que modifican el valor que se les pasa. <...>siempre devuelve cero independientemente del argumento pasado. Mientras tanto, [...]siempre devuelve los tiempos de discusión -1.


Programas de muestra con explicación

Si nunca ha programado en Brain-Flak, podría ser una buena idea mirar algunos programas de ejemplo utilizando las operaciones descritas

({}{})

Esto agrega los dos números superiores en la pila. Cada uno {}saca un valor de la pila y (...)empuja su suma hacia atrás.

({}[{}])

Del mismo modo, esto resta el segundo elemento de la pila del primero. Al igual que antes de que cada uno {}muestre un valor, pero [..]alrededor del segundo hace que se agregue. Una vez más, (...)empuja la suma.

({}<{}>)

Esto elimina el segundo valor en la pila manteniendo intacto el valor superior. Funciona igual que los dos últimos, excepto que el segundo valor es silenciado por, por <...>lo que el empuje solo empuja el primer valor hacia atrás.

(({}))

Esto hace una segunda copia del valor en la parte superior de la pila. Lo hace haciendo estallar la parte superior de la pila al {}obtener su valor, el primero (..)luego lo empuja hacia atrás evaluando su valor. El segundo (...)toma el valor devuelto por el primero y lo empuja a la pila también. creando una segunda copia.

Tarea

Dado un número entero, ncree un fragmento Brain-Flak limpio de pila que multiplique la parte superior de la pila actual por n.

Se le permite usar las siguientes operaciones de Brain-Flak

(...) -> 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

Las otras operaciones están prohibidas a los efectos del desafío.

Puntuación

Su puntaje será la duración acumulada de todos los programas desde n=2hasta n=10000. Asegúrese de incluir un enlace a la salida de su programa para su verificación.

Post Rock Garf Hunter
fuente
1
Por interés, ¿por qué están prohibidas las operaciones 1 y loop?
Neil
@Neil El operador de altura de pila también está prohibido.
Erik the Outgolfer
1
@EriktheOutgolfer Ya había prohibido ese en el metagolf entero de todos modos.
Neil
77
Los informáticos son raros. Inventan lenguajes de programación que son imposibles de usar, inherentemente anti-golf, y luego se desafían mutuamente a escribir código de golf para resolver problemas simples en este lenguaje. Nada es más esotérico que esto. +1 buen señor.
Draco18s ya no confía en SE
1
@ Qwerp-Derp Busqué optimizar la salida del programa enlazado de Python (puntaje actual 681950) y encontré un ahorro trivial de 4492 usando [...], así que es un comienzo.
Neil

Respuestas:

2

Rubí, 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

Esta es una respuesta de referencia rápida. Primeros 1000 programas min encontrados aquí . (Intenté publicarlos todos, pero eso sobrecargó el tamaño máximo de pastebin.) Puedo agregar una explicación de código más adelante.

Ejemplos:

360:    ((((((({})(({}){}){})({}){})({}){}){}){}){})
4608:   (((((((((((({})({}){})({}){}){}){}){}){}){}){}){}){}){})
9991:   (({})((({})(((((((({})((({})({}){}){}){}){}){}){}){}){}){}){})({}){}){})
MegaTom
fuente