Número de pasos para una búsqueda binaria.

12

Dada la entrada de un entero positivo, genera el número de pasos necesarios para encontrar la entrada a través de una búsqueda binaria que comienza en 1.

Estamos simulando una búsqueda binaria para el entero que se proporcionó como entrada, en la que el buscador simulado puede adivinar repetidamente un entero y saber si es demasiado alto, demasiado bajo o correcto. La estrategia para encontrar el número entero es la siguiente:

  • Sea n el entero dado como entrada que estamos tratando de encontrar.

  • Comience con una conjetura de 1. (Para cada conjetura, incremente el número de pasos (independientemente de si fue correcto o no) e inmediatamente deténgase y envíe el número total de pasos si la suposición fue correcta).

  • Duplique la suposición repetidamente hasta que la suposición sea mayor que n (el número objetivo). (O si es correcto, pero eso ya está cubierto por nuestra regla de conjetura correcta mencionada anteriormente).

  • Ahora, establezca un límite superior de la primera potencia de 2 que sea mayor que n (es decir, el número que se acaba de adivinar), y establezca un límite inferior de la potencia de 2 directamente debajo de él.

  • Adivine repetidamente el promedio (redondeado hacia abajo) del límite superior y el límite inferior. Si es demasiado alto, configúrelo como el límite superior. Si es demasiado bajo, configúrelo como el límite inferior. Se garantiza que este procedimiento finalmente dará como resultado una suposición correcta.

Aquí hay un ejemplo, para la entrada de n = 21:

1 -> 2 -> 4 -> 8 -> 16 -> 32 -> 24 -> 20 -> 22 -> 21
\__________________________/
   repeated doubling      \________________________/
                             repeated averaging

Como se trata de , el código más corto en bytes ganará.

Aquí están todas las salidas de n = 1 a n = 100:

1
2
4
3
6
5
6
4
8
7
8
6
8
7
8
5
10
9
10
8
10
9
10
7
10
9
10
8
10
9
10
6
12
11
12
10
12
11
12
9
12
11
12
10
12
11
12
8
12
11
12
10
12
11
12
9
12
11
12
10
12
11
12
7
14
13
14
12
14
13
14
11
14
13
14
12
14
13
14
10
14
13
14
12
14
13
14
11
14
13
14
12
14
13
14
9
14
13
14
12

Y aquí hay algunos casos de prueba más grandes:

1234 -> 21
1337 -> 22
3808 -> 19
12345 -> 28
32768 -> 16
32769 -> 32
50000 -> 28
Pomo de la puerta
fuente

Respuestas:

10

Japt, 13 12 bytes

Dios mío, estuve superando a Jelly y Pyth por un tiempo: D

¢a1 ªJ +1+¢l

¡Pruébalo en línea!

Aquí está el que el uso de estrategias: que x es el entero de entrada, y dejar que b sea x 's representación binaria. La salida correcta es 1 + la longitud de b + el último índice de a 1 en b , menos 1 si este índice es 0.

ETHproductions
fuente
2
Te dije que Dennis ganaría.
lirtosiast
7

Jalea, 18 15 10 9 bytes

B>WU;BḄBL

Pruébalo en línea! o verificar los casos de prueba pequeños y los casos de prueba grandes .

Antecedentes

Sea n un número entero positivo ym la potencia más pequeña de 2 que sea mayor o igual o igual que n .

  • La fase de duplicación toma un paso por cada dígito en la representación binaria de m .

  • Tome la representación binaria de n , elimine el primer dígito más significativo (siempre 1 ) y todos los ceros finales. La fase de promedio toma un paso por cada dígito restante.

Para evitar calcular m , observamos que, si n <m , el número de dígitos binarios de n es exactamente uno menos que el número de dígitos binarios de m .

Si reemplazamos el primer dígito binario de n con un 0 , invierta el resultado, agregue los dígitos binarios originales y elimine todos los ceros iniciales, luego sucede lo siguiente:

  • Si n es una potencia de 2 , todos los dígitos de la primera mitad (modificada) se eliminan, dejando solo los dígitos de la representación binaria original de n = m .

  • Si n no es una potencia de 2 , el dígito en la primera mitad que corresponde al dígito más significativo no se elimina, compensando el hecho de que n tiene un dígito binario menor que m .

Cómo funciona

B>WU;BḄBL  Main link. Input: n

B          Compute the binary representation of n.
 >W        Compare it with [n].
           n is positive, so it is not less than the first binary digit and the
           comparison yields zero. When comparing lists of different length, the
           elements in the longer list that do not have a pair remain untouched.
           Therefore, this will just zero out the first binary digit.
   U       Reverse the modified binary representation.
    ;B     Concatenate it with the unmodified binary representation of n.
      ḄB   Convert from binary to integer, and back to binary.
           This removes leading zeroes.
        L  Get the length of the resulting array.
Dennis
fuente
’B;Bt0L(7 bytes) funciona en la última versión de Jelly, utilizando el mismo enfoque que en mi respuesta de Julia .
Dennis
4

ES6, 38 bytes

x=>33-(g=Math.clz32)(x-1)+g(x&-x)-g(x)

Como aluden otras respuestas, puede calcular el número de pasos a partir de las posiciones del primer y último bit.

El número de pasos en la fase de duplicación es n=33-Math.clz32(x-1). Queremos 2ⁿ ≥ x pero n=33-Math.clz32(x)nos da 2ⁿ> x, así que restamos 1 de x para compensar.

El número de pasos en la fase de promedio es más fácil, es simple n=Math.clz32(x&-x)-Math.clz32(x). x&-xes una expresión útil que se evalúa al bit más bajo de x(como una potencia de 2).

Neil
fuente
Como x&-xfunciona Pensé que evaluaría el valor absoluto de x.
ETHproductions
2
Encontré una buena explicación en esta página (ver bit-hack # 7).
ETHproductions
2

Pyth, 15 13 bytes

h-y.ElQ/PPyQ2

He encontrado que el número a calcular es 1 + 2*ceil(log_2(x)) - [number of 2s in x's prime factorization, minus 1 if x is a power of 2 greater than 1].

Pruébalo aquí .

lirtosiast
fuente
2

Julia, 37 35 bytes

n->endof(strip(bin(n-1)bin(n),'0'))

Gracias a @AlexA. para guardar 2 bytes!

Esto sigue las observaciones de mi respuesta de Jelly , pero trata de manera diferente los casos extremos.

Si n> 1 , la representación binaria de n - 1 tiene un dígito menos que el de la siguiente potencia de 2 , que se compensa al no eliminar el primer dígito de la representación binaria de n .

Al eliminar todos los ceros de ambos lados , nos ocupamos también del caso de borde 1 .

Dennis
fuente
0

Haskell, 82 bytes

Esta es una implementación bastante sencilla en Haskell:

f x=[j|j<-[1..],let g i|i<2=1|x>g(i-1)=2*g(i-1)|1<2=div(g(i-1)+g(i-2))2,g j==x]!!0

Menos golfizado:

f x = head [ stepNum | stepNum <- [1..], step stepNum == x]
  where
    prevStep i = step (i-1)
    step i | i == 1         = 1
           | x > prevStep i = 2 * prevStep i
           | otherwise      = div (prevStep i + step (i-2)) 2
Michael Klein
fuente