Lunghezza del conto alla rovescia binaria


18

ispirato al conto alla rovescia dall'infinito

Dato un numero intero non negativo N, genera il numero di ripetizioni dei seguenti passaggi necessari per raggiungere 0:

  1. Converti Nin binario ( 4812390 -> 10010010110111001100110)
  2. Capovolgi ogni bit ( 10010010110111001100110 -> 01101101001000110011001)
  3. Taglia zeri iniziali ( 01101101001000110011001 -> 1101101001000110011001)
  4. Converti indietro in decimale ( 1101101001000110011001 -> 3576217)

Regole

  • L'input e l'output possono essere in qualsiasi formato non ambiguo e coerente
  • L'input sarà compreso nell'intervallo intero rappresentabile nativo per la tua lingua (se la tua lingua supporta numeri interi arbitrariamente grandi, non c'è limite)

Casi test

0 -> 0
1 -> 1
42 -> 6
97 -> 3
170 -> 8
255 -> 1
682 -> 10
8675309 -> 11
4812390 -> 14
178956970 -> 28
2863311530 -> 32

Questa sequenza è A005811 nell'OEIS.


6
Il passaggio 3 non è affatto utile
edc65,

@ edc65 Sembra che potresti fare il passaggio 3 o il passaggio 4, a seconda di come è strutturato l'algoritmo
Brian J,

@ edc65 Forse per te non serve a niente. Un semplice operatore inverso non taglia gli zeri iniziali per te. ~(~a) == a
Colpisce il

@Poke Bitwise NOT inverte tutti i bit della rappresentazione binaria, compresi gli zeri iniziali (e una quantità infinita di essi in linguaggi con interi di precisione arbitrari). Ciò non equivale al passaggio 2.
Dennis,

@Poke Una semplice operazione inversa è diversa dall'applicazione dei passaggi 1..4. Se si desidera applicare questi passaggi, il passaggio 3 non è di alcuna utilità, poiché il passaggio al passaggio 2 (come mostrato) non modifica gli 0 iniziali. Se il passo 2 non cambia gli 0 che portano a maggiori 1s, poi obviuosly è necessario rimuovere i principali 1s al punto 3, non i leader 0s
edc65

Risposte:


14

Gelatina , 6 4 byte

^HBS

Provalo online! o verifica tutti i casi di test .

sfondo

Sia n un numero intero non negativo.

I passaggi 2 e 3 del processo descritto nelle specifiche possono in alternativa essere indicati come la rimozione di tutti gli 1 iniziali e la commutazione dei bit rimanenti.

Ciò significa che rimuoveremo esattamente un gruppo di cifre binarie adiacenti e uguali in ogni iterazione, quindi la Lunghezza del conto alla rovescia binaria di n è solo il numero di questi gruppi nella rappresentazione binaria di n . Ai fini di questa sfida, pensa a 0 come non avere cifre.

Per n = 8675309 , il processo appare come segue in binario.

100001000101111111101101
 11110111010000000010010
     1000101111111101101
      111010000000010010
         101111111101101
          10000000010010
           1111111101101
                   10010
                    1101
                      10
                       1
                       0

Invece di contare questi gruppi (che fallirebbero per il caso limite 0 ), facciamo quanto segue.

n e n: 2 hanno le seguenti rappresentazioni binarie.

n   = 8675309 = 100001000101111111101101_2
n:2 = 4337654 =  10000100010111111110110_2

Si noti che la rappresentazione binaria di n: 2 è semplicemente n ', spostata di un bit a sinistra.

Se XOR n e n: 2 , otterremo un 1 (MSB) e un ulteriore 1 per ogni coppia di diverse cifre adiacenti. Il numero di gruppi è quindi uguale al numero di bit impostati in n ⊻ n: 2 .

Come funziona

^HBS  Main link. Argument: n

 H    Halve; yield n:2.
^     XOR n with n:2.
  B   Convert the result to binary.
   S  Compute the sum of the resulting binary digits.

1
Sorprendente! Un ragionamento totalmente diverso
edc65,

9

Python 2, 30 byte

lambda n:bin(n^n/2).count('1')

Provalo su Ideone .

sfondo

Sia n un numero intero non negativo.

I passaggi 2 e 3 del processo descritto nelle specifiche possono in alternativa essere indicati come la rimozione di tutti gli 1 iniziali e la commutazione dei bit rimanenti.

Ciò significa che rimuoveremo esattamente un gruppo di cifre binarie adiacenti e uguali in ogni iterazione, quindi la Lunghezza del conto alla rovescia binaria di n è solo il numero di questi gruppi nella rappresentazione binaria di n . Ai fini di questa sfida, pensa a 0 come non avere cifre.

Per n = 8675309 , il processo appare come segue in binario.

100001000101111111101101
 11110111010000000010010
     1000101111111101101
      111010000000010010
         101111111101101
          10000000010010
           1111111101101
                   10010
                    1101
                      10
                       1
                       0

Invece di contare questi gruppi (che fallirebbero per il caso limite 0 ), facciamo quanto segue.

n e n: 2 hanno le seguenti rappresentazioni binarie.

n   = 8675309 = 100001000101111111101101_2
n:2 = 4337654 =  10000100010111111110110_2

Si noti che la rappresentazione binaria di n: 2 è semplicemente n ', spostata di un bit a sinistra.

Se XOR n e n: 2 , otterremo un 1 (MSB) e un ulteriore 1 per ogni coppia di diverse cifre adiacenti. Il numero di gruppi è quindi uguale al numero di bit impostati in n ⊻ n: 2 .


9

Python 2, 29 byte

f=lambda n:n and-n%4/2+f(n/2)

Conta il numero di alternanze tra 0 e 1 nell'espansione binaria, contando il 1 iniziale come alternanza. Lo fa controllando se le ultime due cifre binarie sono diverse, quindi ricorre sul numero con l'ultima cifra rimossa. Le ultime due cifre sono diverse esattamente se n%4è 1 o 2, che può essere verificato come -n%4/2.


6

JavaScript (ES6), 26 byte

f=n=>n&&(n^(n>>=1))%2+f(n)

Funziona contando le transizioni tra 0 e 1. Funziona solo fino a 31 bit. 29 byte per supportare 53 bit:

f=n=>1<=n&&(n%2^n/2%2)+f(n/2)

5

Haskell, 34 byte

b 0=0
b n|x<-b$div n 2=x+mod(x+n)2

Mi piace come dice "0 = 0" :)
AlexR,

4

05AB1E , 7 5 byte

Salvato 2 byte grazie a Dennis .

b0ÛÔg

Senza il caso limite di 0 questo potrebbe essere di 3 byte bÔg.

Provalo online! o come una suite di test

Spiegazione

b      # convert to binary
 0Û    # trim off leading zeroes
   Ô   # remove adjacent duplicates
    g  # length

3

CJam , 14 byte

ri0{2b:!2bj)}j

Provalo online!

ri      e# read integer
0       e# value for terminal case
{       e# recursive function
  2b    e#   create binary representation with no leading zeros
  :!    e#   flip bits
  2b    e#   convert binary back to integer
  j     e#   recursive call
  )     e#   increment from 0 on the way up
}j      e# end

Fondamentalmente un knock off della mia risposta all'altra domanda.


3

Java 7,112 108 100 90 73 byte

int c(int i){int l=1,j=i;for(;(j=j/2)>0;l*=2);return i<1?0:1+c(2*l-1-i);}

Idea base

 Lets take an no 10110(21)
 then you do set all bits in no 21 and you will get 11111
 and after that you would subtract the original number from 11111.
 You will get 01001 and loop it until you will get 0

j=j/2può essere abbreviato in j/=2. A parte ciò un'ottima risposta!
Kevin Cruijssen,

Mmm .. una porta dalla risposta JavaScript di @Neil è però più breve: int c(int i){return i>0?((i^(i>>=1))%2+c(i):0;}( 47 byte ). Lascerei comunque anche la tua risposta attuale, poiché è più originale e le porte di altri utenti sono l'esatto contrario dell'originale. :)
Kevin Cruijssen,

3

J, 14 byte

**1+/@,2~:/\#:

Conta il numero di esecuzioni nelle cifre binarie di n con il caso speciale che restituisce 0 per n = 0.

uso

   f =: **1+/@,2~:/\#:
   (,.f"0) 0 1 42 97 170 255 682 8675309 4812390 178956970 2863311530
         0  0
         1  1
        42  6
        97  3
       170  8
       255  1
       682 10
   8675309 11
   4812390 14
 178956970 28
2863311530 32

Spiegazione

**1+/@,2~:/\#:  Input: integer n
            #:  Get the binary digits of n
       2   \    For each overlapping sublist of size 2
        ~:/       Reduce by not-equals
  1   ,         Prepend a 1
   +/@          Reduce by addition
*               Sign(n), returns 0 for n = 0 else 1
 *              Multiply with the previous sum and return

3

CJam , 11 10 byte

Grazie a @Dennis per aver salvato un byte!

ri_2be`,e&

Provalo online!

Spiegazione

ri            #e Read as integer
              #e STACK: 97
  _           #e Duplicate
              #e STACK: 97, 97
   2b         #e Convert to binary
              #e STACK: 97, [1 1 0 0 0 0 1]
     e`       #e Run-length encoding
              #e STACK: 97, [[2 1] [4 0] [1 1]]
       ,      #e Length
              #e STACK: 97, 3
        e&    #e Return first value if 0, or else the second value
              #e STACK: 3

1
e&(AND logico) salva un byte \g*.
Dennis,

@Dennis Grazie! È utile come funzioni AND logico di CJam, non ne avevo idea
Luis Mendo,

2

Racchetta 349 byte

(define(h s)(apply string(map(λ(x)(if(eq? x #\0)#\1 #\0))(string->list s))))(define(g s)(let*
((l(string-length s))(k(for/list((i s)(n l)#:final(not(equal? i #\0)))n)))(substring s(last k))))
(define(f n)(if(= 0 n)0(begin(let loop((n n)(c 1))(define m(string->number(string-append "#b"
(g(h(number->string n 2))))))(if(> m 0)(loop m(add1 c))c))))

Ungolfed:

(define (invertBinary s)
  (apply string
         (map
          (λ(x)(if(eq? x #\0)#\1 #\0))
          (string->list s))))

(define (trimLeading0s s)
  (let* ((l (string-length s))
         (k (for/list ((i s)
                       (n l)
                       #:final (not(equal? i #\0)))
              n)))
    (substring s (last k))))

(define (f n)
  (if (= 0 n) 0
      (begin
        (let loop ((n n)
                   (c 1))
          (define m 
            (string->number
             (string-append
              "#b"
              (trimLeading0s
               (invertBinary
                (number->string n 2))))))

          (if (> m 0)
              (loop m (add1 c))
              c)))))

test:

(f 0)
(f 1)
(f 42)
(f 97)
(f 170)
(f 255)
(f 682)
(f 8675309)
(f 4812390)
(f 178956970)
(f 2863311530)

Produzione:

0
1
6
3
8
1
10
11
14
28
32

È possibile salvare 2 byte modificando tle ibin nomi a 1 byte.
Mego

Fatto. Grazie per il suggerimento
anche il

2

MATL , 7 byte

BY'nwa*

Provalo online!

Spiegazione

          % Implicit input, for example 97
          % STACK: 97
B         % Convert to binary
          % STACK: [1 1 0 0 0 0 1]
 Y'       % Run-length encoding
          % STACK: [1 0 1], [2 4 1]
   n      % Number of elements
          % STACK: [1 0 1], 3
    w     % Swap
          % STACK: 3, [1 0 1]
     a    % Any: gives 1 if any element is nonzero
          % STACK: 3, 1
      *   % Multiply
          % STACK: 3
          % Implicit display

2

Vim, 62 59 byte

-3 byte grazie a DJMcMayhem

C0
<C-r>=pri<Tab>'%b',<C-r>")
<Esc>0qqC<C-r>=tr(@",'01','10')
<Esc>:s/^0\+
k<C-a>j@qq@q

Ecco l'output xxd con i caratteri non stampabili intatti:

0000000: 4330 0d12 3d70 7269 0927 2562 272c 1222  C0..=pri.'%b',."
0000010: 290d 1b30 7171 4312 3d74 7228 4022 2c27  )..0qqC.=tr(@",'
0000020: 3031 272c 2731 3027 290d 1b3a 732f 5e30  01','10')..:s/^0
0000030: 5c2b 0d6b 016a 4071 7140 71              \+.k.j@qq@q

Provalo online!

Spiegazione

C                                   " Delete the number (it goes in @")
0<CR>                               " Print 0 (our counter) and a carriage return
<C-r>=pri<Tab>'%b',<C-r>")<CR><Esc> " Use `printf()` to insert the number as base 2
0qq                                 " Return to column 0, start recording a macro
  C<C-r>=tr(@",'01','10')<CR><Esc>  "   Replace 0s with 1s and vice versa
  :s/^0\+<CR>                       "   Delete leading 0s
  k<C-a>                            "   Increment the number on the line above
  j                                 "   Return to the previous line
  @q                                "   Invoke macro recursively
q@q                                 " Stop recording and invoke macro

1
Bello! Alcuni consigli: :s/^0*è più corto di un byte di :s/^0\+e, mentre ci si trova nel registro "eval", si può fare solo pr<S-tab>'%b',<C-r>")per il completamento automatico. (Salva 4 byte)
DJMcMayhem

Oh, grazie per il suggerimento di completamento automatico! Non posso usarlo :s/^0*perché corrisponde a una riga vuota e ho bisogno che fallisca per svuotare una riga vuota per sfuggire alla macro ricorsiva.
Giordania,

1

Rubino, 26 byte

f=->n{n<1?0:-n%4/2+f[n/2]}

Ispirato dalla risposta Python di xnor.


0

PHP, 64 byte

basato sulla mia soluzione per il conto alla rovescia

for($n=$argv[1];$n;print 1)$n=bindec(strtr(decbin($n),"01",10));

stampa i tempi dei 1caratteri k, dov'è kil numero di iterazioni.


+4 byte per l'output intero: (output vuoto per 0)

for($n=$argv[1];$n;$i++)$n=bindec(strtr(decbin($n),"01",10));echo$i;

0

JavaScript (ES6), 44

Funzione ricorsiva

Limitato all'intero positivo javascript, 31 bit:

f=(a,s=0)=>a?f((-1>>>Math.clz32(a))-a,s+1):s

Gestione di un numero a doppia precisione fino a 53 bit significativi - 59 byte:

F=(a,s=0)=>a?F('0b'+a.toString(2).replace(/./g,1)-a,s+1):s

In un altro modo: usando lo straordinario algoritmo di @Dennis, la funzione non ricorsiva gestisce fino a 53 bit, 43 byte:

a=>a&&a.toString(2).match(/(.)\1*/g).length

0

PHP, 51 byte

<?=preg_match_all('/(1+|0+)/',decbin($argv[1])?:o);

Usa una regex per contare il numero di esecuzioni di 1 o 0. Sfortunatamente questo richiede un caso speciale per l'input 0che richiede 3 byte aggiuntivi (e dà un avviso).


a) Utilizzare una cifra> 1 anziché oper evitare l'avviso. b) È possibile salvare 3 byte con il -Fflag e $argninvece di $argv[1]. c) /1+|0+/dovrebbe bastare per la regex.
Tito,

0

Java 7, 71 byte

int b(Long a){return a==0?0:1+b(~a&-1L>>>64-a.toString(a,2).length());}

So che questo è battuto dalla soluzione di Geobitssplit (che alla fine verrà pubblicata) ma è stato comunque divertente da scrivere


0

Ottava, 47 byte

@(x)(sum(dec2bin(bitxor(x,idivide(x,2)))=='1'))

Secondo la voce OEIS, il valore che stiamo cercando come soluzione a questa sfida è anche uguale al numero di 1s nel codice Gray per l'intero numero dato.

Wikipedia mi dice che il codice Gray può essere calcolato come x ^ (x >> 1), quindi nella funzione sopra calcolo il codice Gray come tale, lo converto in una stringa binaria e conto quante cifre di quella stringa sono 1.


0

Java 7, 64 byte

long g(Long n){return n.toString(n,2).split("0+").length*2-n%2;}

So che questo potrebbe essere battuto da una porta di una delle risposte migliori, ma l'ho trovato in chat e non posso non pubblicarlo dopo che Poke ha detto qualcosa al riguardo :)


0

C, 76 byte

unsigned n,m,i;f(x){for(i=0;x;x^=m-1,i++)for(n=x,m=2;n>>=1;m<<=1);return i;}

Funziona con tutti i casi di test (anche se non voglio includere la parola unsigned o last case test) ...


0

Bash, 57 byte

Pacchetti: Core Utililities, grep, sed, vim (per xxd )

Supponiamo che il numero sia indicato in formato binario. Qualsiasi lunghezza è accettabile :)

xxd -b -c1|cut -d" " -f2|sed s/^0*//|grep -o .|uniq|wc -l


0

Tcl , 119 byte

proc D n i\ 0 {
while \$n {set n [regsub ^0+(?=.) [string map {0 1 1 0} [format %b $n]] ""]
incr i
scan $n %b n}
set i}

Provalo online!

Ancora molto non soddisfatto per i miei gusti

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.