Hoy, calcularemos la función binaria más eficiente. Más específicamente, calcularemos la función que, cuando se crea una expresión aplicando la función a la entrada constante 0 o su propia salida, puede representar todos los enteros positivos con las expresiones más cortas posibles, dando mayor prioridad a los enteros más pequeños.
Esta función se construye de la siguiente manera:
Para cada número entero, comenzando en 1 y yendo hacia arriba, elija la expresión más corta a la que aún no le hemos asignado una salida, y haga que ese entero sea la salida de esa expresión. Los lazos en la longitud de la expresión se romperán con un argumento izquierdo más pequeño y luego con un argumento derecho más pequeño. Así es como funciona:
Inicialmente, 1 no está asignado. La expresión sin asignar más corta es
f(0, 0)
, por lo que la estableceremos en 1.Ahora, 2 no está asignado. Las expresiones sin asignar más cortas son
f(f(0, 0), 0)
=f(1, 0)
yf(0, f(0, 0))
=f(0, 1)
. Los lazos se rompen hacia la izquierda argumento más pequeño, por lo quef(0, 1) = 2
.La expresión sin asignar más corta que queda es
f(f(0, 0), 0)
=f(1, 0)
, entoncesf(1, 0) = 3
.Ahora, estamos sin expresiones con solo 2
f
sy 30
s, por lo que tendremos que agregar uno más de cada uno. Romper los lazos por argumento izquierdo, luego argumento derecho, obtenemosf(0, 2) = 4
, desde entoncesf(0, f(0, f(0, 0))) = f(0, f(0, 1)) = f(0, 2)
.Continuando, tenemos
f(0, 3) = 5
,f(1, 1) = 6
,f(2, 0) = 7
,f(3, 0) = 8
,f(0, 4) = 9
, ...
Aquí hay una tabla que completé para los primeros valores:
0 1 2 3 4 5 6 7 8
/---------------------------
0| 1 2 4 5 9 10 11 12 13
1| 3 6 14 15 37 38 39 40 41
2| 7 16 42 43
3| 8 17 44 45
4| 18 46
5| 19 47
6| 20 48
7| 21 49
8| 22 50
Otra forma de verlo es que cada salida tiene un tamaño, igual a la suma de los tamaños de sus entradas más uno. La tabla se completa en orden de tamaño creciente de salida, los vínculos se rompen al minimizar la entrada izquierda y luego la entrada derecha.
Su desafío es, dados dos enteros no negativos como entrada, cálculo y salida del valor de esta función. Este es el código de golf. La solución más corta, en bytes, gana. Las lagunas estándar están prohibidas.
((0, (0, (0, 0))), 0)
es lexicográficamente más pequeño que(((0, 0), 0), (0, 0))
, sin embargo, este último tiene un lado izquierdo más pequeño.Respuestas:
Haskell, 110 bytes
El argumento aquí se toma como la tupla
(x,y)
. Bastante similar a la respuesta anterior, pero la lista de búsqueda contiene solo los pares de índices izquierdo y derecho en lugar de los árboles.fuente
head[...]
es[...]!!0
y(p,i)<-zip(concat c)[0..]
se puede acortar a(i,p)<-zip[0..]$id=<<c
.id=<<
al repertorio :)Python 3, 154 bytes
No es muy rápido ni muy golfista, pero es un comienzo.
fuente
¡Guauu! Realmente logré hacer un algoritmo de computación eficiente. No esperaba esto al principio. La solución es bastante elegante. En repetidas ocasiones deduce más y más, luego recurre hasta el caso base de 0. En esta respuesta, la función C (n) denota los números catalanes .
El primer paso crucial es reconocer que hay C (0) = 1 valores de longitud cero (es decir, 0 en sí mismo), C (1) = 1 valores de longitud uno (es decir, f (0, 0)), C (2) = 2 valores de longitud dos (f (0, f (0, 0)) yf (f (0, 0), 0)).
Esto significa que si estamos buscando la enésima expresión, y encontramos la k más grande tal que C (0) + C (1) + ... + C (k) <= n, entonces sabemos que n tiene longitud k .
¡Pero ahora podemos continuar! Debido a que la expresión que buscamos es la expresión n - C (0) - C (1) - ... - C (k) th en su clase de longitud.
Ahora podemos usar un truco similar para encontrar la longitud del segmento izquierdo, y luego el rango dentro de esa subsección. ¡Y luego volvemos a esos rangos que encontramos!
Encontró que f (5030, 3749) = 1542317211 en un abrir y cerrar de ojos.
Python, sin competencia
Estoy bastante seguro de que estoy haciendo un montón de cálculos innecesarios y se pueden eliminar muchos pasos intermedios.
fuente