Numero di passaggi per una ricerca binaria


12

Dato un input di un numero intero positivo, emettere il numero di passaggi necessari per trovare l'input tramite una ricerca binaria a partire da 1.

Stiamo simulando una ricerca binaria per l'intero che è stato fornito come input, in cui il ricercatore simulato può indovinare ripetutamente un numero intero e sapere se è troppo alto, troppo basso o corretto. La strategia per trovare il numero intero è la seguente:

  • Sia n il numero intero indicato come input che stiamo cercando di trovare.

  • Inizia con un'ipotesi di 1. (Per ogni ipotesi, incrementa il numero di passaggi (indipendentemente dal fatto che fosse corretto o meno), e ferma immediatamente e genera il numero totale di passaggi se l'ipotesi era corretta.)

  • Raddoppia più volte l'ipotesi fino a quando l'ipotesi è maggiore di n (il numero di destinazione). (O se è corretto, ma è già coperto dalla nostra regola di ipotesi corretta sopra menzionata.)

  • Ora, imposta un limite superiore della prima potenza di 2 che è maggiore di n (cioè il numero appena indovinato) e imposta un limite inferiore della potenza di 2 direttamente sotto di esso.

  • Indovina ripetutamente la media (arrotondata per difetto) del limite superiore e del limite inferiore. Se è troppo alto, impostalo come limite superiore. Se è troppo basso, impostarlo come limite inferiore. Questa procedura è garantita per provocare eventualmente un'ipotesi corretta.

Ecco un esempio, per l'input di n = 21:

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

Poiché si tratta di , vincerà il codice più breve in byte.

Ecco tutti gli output da 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

E qui ci sono alcuni casi di test più grandi:

1234 -> 21
1337 -> 22
3808 -> 19
12345 -> 28
32768 -> 16
32769 -> 32
50000 -> 28

Risposte:


10

Japt, 13 12 byte

Oh mio Dio stavo battendo sia Jelly che Pyth per un po ': D

¢a1 ªJ +1+¢l

Provalo online!

Ecco la strategia che uso: lascia che x sia il numero intero di input e che b sia la rappresentazione binaria di x . L'output corretto è 1 + la lunghezza di b + l'ultimo indice di a 1 in b , meno 1 se questo indice è 0.


2
Ti avevo detto che Dennis avrebbe vinto.
lirtosiast,

7

Gelatina, 18 15 10 9 byte

B>WU;BḄBL

Provalo online! oppure verifica i casi di test piccoli e i casi di test di grandi dimensioni .

sfondo

Lasciare n un intero positivo e m la più piccola potenza di 2 che è maggiore o uguale o uguale a n .

  • La fase di raddoppio fa un passo per ogni cifra nella rappresentazione binaria di m .

  • Prendi la rappresentazione binaria di n , rimuove la prima cifra più significativa (sempre 1 ) e tutti gli zero finali. La fase della media fa un passo per ogni cifra rimanente.

Per evitare il calcolo di m , osserviamo che, se n <m , il numero di cifre binarie di n è esattamente uno in meno del numero di cifre binarie di m .

Se sostituiamo la prima cifra binaria di n con uno 0 , invertiamo il risultato, aggiungiamo le cifre binarie originali e rimuoviamo tutti gli zero iniziali, quindi si verifica quanto segue:

  • Se n è una potenza di 2 , tutte le cifre della prima metà (modificata) vengono rimosse, lasciando solo le cifre della rappresentazione binaria originale di n = m .

  • Se n non è una potenza di 2 , la cifra nella prima metà che corrisponde alla cifra più significativa non viene rimossa, compensando il fatto che n ha una cifra binaria inferiore a m .

Come funziona

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.

’B;Bt0L(7 byte) funziona nell'ultima versione di Jelly, usando lo stesso approccio della mia risposta Julia .
Dennis,

4

ES6, 38 byte

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

Come accennato da altre risposte, è possibile calcolare il numero di passaggi dalle posizioni del primo e dell'ultimo bit.

Il numero di passaggi nella fase di raddoppio è n=33-Math.clz32(x-1). Vogliamo 2ⁿ ≥ x ma n=33-Math.clz32(x)ci dà 2ⁿ> x quindi sottraggiamo 1 da x per compensare.

Il numero di passaggi nella fase di calcolo della media è più semplice, è semplicemente n=Math.clz32(x&-x)-Math.clz32(x). x&-xè un'espressione utile che valuta il bit più basso di x(come una potenza di 2).


Come x&-xfunziona? Avrei pensato che avrebbe valutato il valore assoluto di x.
ETHproductions

2
Ho trovato una buona spiegazione in questa pagina (vedi bit-hack # 7).
ETHproductions

2

Pyth, 15 13 byte

h-y.ElQ/PPyQ2

Ho scoperto che il numero da calcolare è 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].

Provalo qui .


2

Julia, 37 35 byte

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

Grazie a @AlexA. per salvare 2 byte!

Questo segue le osservazioni della mia risposta di Jelly , ma si occupa in modo diverso dei casi limite.

Se n> 1 , la rappresentazione binaria di n - 1 ha una cifra in meno di quella della potenza successiva di 2 , che viene compensata non rimuovendo la prima cifra della rappresentazione binaria di n .

Rimuovendo tutti gli zeri da entrambi i lati , ci occupiamo anche del caso limite 1 .


0

Haskell, 82 byte

Questa è un'implementazione piuttosto semplice in 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

Meno golf:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.