Contare il numero di quelli in un numero intero a 16 bit senza segno


24

Scrivi alcune istruzioni che contano il numero di quelle in un numero intero a sedici bit senza segno.

Ad esempio, se l'input è 1337, allora il risultato è 6perché è 1337un numero binario a sedici bit 0000010100111001, che ne contiene sei.


2
Suggerimento: così come alcune cifre in un numero sono congruenti con il numero mod 9, alcune parti sono uguali al numero mod 1.
PyRulez

8
@PyRulez Qualsiasi numero è zero modulo 1.
Thomas

1
Ciao, hai scelto una risposta errata come risposta accettata (per impostazione predefinita, la logica del tie breaker del primo post).
Ottimizzatore

4
@Thomas Non ho mai detto che fosse un consiglio utile.
PyRulez,

2
Perché questa domanda sta attirando voti stretti DOPO che la maggior parte delle risposte è stata pubblicata? Elettori stretti si prega di indicare il motivo nei commenti. Se è l'accettazione della risposta a 4 byte di es1024 (molto intelligente) che non è conforme alle scappatoie standard (perché utilizza un built-in), si prega di indicare che questo è il motivo. Altrimenti, che cos'è?
Level River St

Risposte:


37

80386 Codice macchina, 4 byte

F3 0F B8 C1

che accetta il numero intero cxe genera il conteggio axed equivale a:

popcnt ax, cx     ; F3 0F B8 C1

Ed ecco una soluzione da 11 10 byte che non utilizza POPCNT:

31 C0 D1 E9 10 E0 85 C9 75 F8

che equivale a:

xor ax, ax        ; 31 C0   Set ax to 0
shr cx, 1         ; D1 E9   Shift cx to the right by 1 (cx >> 1)
adc al, ah        ; 10 E0   al += (ah = 0) + (cf = rightmost bit before shifting)
test cx, cx       ; 85 C9   Check if cx == 0
jnz $-6           ; 75 F8   Jump up to shr cx, 1 if not

È in modalità a 32 o 16 bit (reale o protetta)?
FUZxxl

2
@FUZxxl L'assembly fornito è per 16 bit, sebbene lo sostituisca axe cxcon eaxe lo ecxcambi in 32 bit. Il bytecode è lo stesso per entrambi.
es1024

1
@ es1024 Il codice byte è lo stesso se questo è stato compilato in modalità 16 bit e la versione a 32 bit in modalità 32 bit.
Cole Johnson,

2
Il popcnt non è un difetto e quindi un fallo di scappatoie standard? Ancora credito per la seconda soluzione però.
Alchymist

5
Quando si rivendica la lunghezza del codice macchina , il titolo non dovrebbe essere "80386 Codice macchina", non "80386 Assembler"?
Kevin Reid,

14

Python 2, 17 byte

bin(s).count('1')

Il binbuilt-in restituisce il numero intero convertito in una stringa binaria. Quindi contiamo le 1cifre:

>>> s=1337
>>> bin(s)
'0b10100111001'
>>> bin(s).count('1')
6

11

J (5 caratteri)

J non ha tipi espliciti. Questo fa la cosa giusta per tutti i numeri interi.

+/@#:
  • +/ la somma
  • @ di
  • #: la rappresentazione di base due

11

C, 21

for(n=0;x;n++)x&=x-1;

hai detto "scrivi alcune dichiarazioni" (non "una funzione"), quindi ho supposto che il numero sia fornito xe il numero di 1 sia restituito n. Se non devo inizializzare nposso salvare 3 byte.

Questo è un adattamento della famosa espressione x&x-1per verificare se qualcosa è un potere di 2 (falso se lo è, vero se non lo è).

Qui è in azione sul numero 1337 dalla domanda. Si noti che sottraendo 1 si capovolge 1 bit meno significativo e tutti gli zero a destra.

0000010100111001 & 0000010100111000 = 0000010100111000
0000010100111000 & 0000010100110111 = 0000010100110000
0000010100110000 & 0000010100101111 = 0000010100100000
0000010100100000 & 0000010100011111 = 0000010100000000
0000010100000000 & 0000010011111111 = 0000010000000000
0000010000000000 & 0000001111111111 = 0000000000000000

EDIT: per completezza, ecco l'algoritmo ingenuo, che è un byte più lungo (e un po 'più lento).

for(n=0;x;x/=2)n+=x&1;


1
@ edc65 così come ho scoperto, ho reinventato la ruota. Almeno ho salvato 2 byte omettendo il {}. È un compito così semplice che non dovrei essere sorpreso che qualcuno l'abbia già inventato.
Level River St

"Pubblicato per la prima volta nel 1960" , impressionante.
mbomb007,

Correzione all'algoritmo ingenuo:for(n=0;x;x/=2)n+=x&1;
Helios

1
@nmxprime l'OP richiede int non firmato. per -7 = 11111111 11111111 11111111 11111001 sul mio compilatore a 32 bit, ottengo 30 per l'algoritmo veloce, che è corretto. Per l'algoritmo ingenuo, scorre tra -7, -7 / 2 = -3, -3 / 2 = -1, -1 / 2 = 0. Questo dà una risposta errata. La modifica di x / = 2 in x >> = 1 può dare la risposta corretta su alcuni compilatori, ma C non è definito se uno o uno 0 viene spostato nel bit vuoto per >> su numeri negativi. Quei compilatori che spostano un 1 in entreranno in un ciclo infinito. La soluzione alternativa è definire x come int senza segno. Quindi x = -7 carica (1 << 32) -7 = 4294967289 in x.
Level River St

5

Gelatina , non competitiva

Questa risposta non è competitiva, poiché la lingua è stata creata dopo che la sfida è stata pubblicata.

2 byte:

BS

Jelly è una nuova lingua scritta da @Dennis, con sintassi simile a quella di J.

         implicit: function of command-line arguments
B        Binary digits as list
 S       Sum

Provalo qui .


4

Pyth, 4 byte

sjQ2

Il programma prende il numero il cui peso di battuta si trova su STDIN.


4

Julia, 29 27 19 byte

n->sum(digits(n,2))

Questo crea una funzione anonima che accetta un singolo argomento, n. Per usarlo, assegnalo a qualcosa di simile f=n->...e chiamalo come f(1337).

La digits()funzione, quando viene chiamata con 2 argomenti, restituisce una matrice delle cifre dell'input nella base specificata. Quindi digits(n, 2)restituisce le cifre binarie di n. Prendi la somma dell'array e hai il numero di quelli nella rappresentazione binaria di n.


Questo può essere molto più breve: Julia ha una funzionecount_ones
Andrew dice Reinstate Monica il

@AndrewPiliser: grazie per il suggerimento, ma le funzioni integrate che svolgono esattamente l'attività sono considerate una scappatoia standard e sono disapprovate quando non esplicitamente vietate.
Alex A.

3

CJam, 6 byte

ri2b:+

ri         "Read the input and convert it to integer";
  2b       "Convert the integer into base 2 format";
    :+     "Sum the digits of base 2 form";

Provalo online qui


3

Joe , 4 byte

/+Ba

Questa è una funzione anonima. Badà la rappresentazione binaria di un numero e lo /+somma.

   (/+Ba)13
3
   (/+Ba)500
6

3

R, 24 byte

sum(intToBits(scan())>0)

scan() legge input da stdin.

intToBits()accetta un numero intero e restituisce un vettore di tipo rawcontenente gli zeri e quelli della rappresentazione binaria dell'input.

intToBits(scan())>0restituisce un vettore logico in cui si trova ogni elemento TRUEse l'elemento vettore binario corrispondente è 1 (poiché tutti gli elementi sono 0 o 1 e 1> 0), altrimenti FALSE.

In R, puoi sommare un vettore logico per ottenere il numero di TRUEelementi, quindi sommare il vettore dei logici come sopra ci dà quello che vogliamo.

Si noti che sum()non è possibile gestire rawdirettamente l'input, quindi la soluzione alternativa utilizzando i logici.


Non sum(intToBits(scan()))sarebbe lo stesso?
Seequ,

@Sieg: Sfortunatamente no dato che sum()non è possibile accettare input di tipo raw, da cui è stato restituito intToBits().
Alex A.

Questo è davvero strano per me.
seequ

1
@Sieg: Sì, è strano anche per me. Oh bene. Se ogni braciola di maiale fosse perfetta, non avremmo gli hot dog.
Alex A.

E questa è la metafora più strana di sempre.
seequ

3

Rubino, 18 byte

n.to_s(2).count'1'


1
n.to_s(2).count ?1funziona anche, ma è della stessa lunghezza
Piccolo

Versione 2019: n.digits (2) .sum / 15 byte
GB

3

Via, 48 49 byte

: c ?dup if dup 1- and recurse 1+ then ;
0 1337 c

Se è necessaria una funzione effettiva, la seconda riga diventa

: c 0 swap c ;

e lo chiami con "1337 c". Le parole di controllo relativamente prolisse di Forth rendono questo difficile (in realtà, ne rendono molti difficili).

Modifica: la mia versione precedente non gestiva correttamente i numeri negativi.


3

Mathematica, 22 18 byte

Grazie ad alephalpha per avermelo ricordato DigitCount.

DigitCount[#,2,1]&

@alephalpha grazie, ma DigitCount accetta un altro parametro :)
Martin Ender il

3

ES6 (34 22 21 byte):

Questa è una semplice funzione ricorsiva che può essere abbreviata un po 'di più. Basta semplicemente un po 'e si esegue di nuovo:

B=n=>n&&(1&n)+B(n>>1)

Provalo su http://www.es6fiddle.net/imt5ilve/ (ti serve il varmotivo di 'use strict';).

Non posso credere di aver battuto Fish !!!

Quello vecchio:

n=>n.toString(2).split(1).length-1

ES5 (39 byte):

Entrambe le funzioni possono essere facilmente adattate a ES5:

function B(n){return n?(1&n)+B(n>>1):0}

//ungolfed:

function B(number)
{
    if( number > 0 )
    {
        //arguments.callee points to the function itself
        return (number & 1) + arguments.callee( number >> 1 );
    }
    else
    {
        return 0;
    }
}

Vecchio:

function(n){return n.toString(2).split(1).length-1}

@ user1455003 mi ha dato un'ottima idea, quella che ha "innescato" il più piccolo:

function B(n,x){for(x=0;n;n>>=1)x+=n&1;return x}

L'ho adattato a ES6 e l'ho reso ricorsivo per abbreviare molto!


1
Ecco una funzione javascript 'reguar' più piccola. funzione B (n, x) {for (x = 0; n; n >> = 1) x + = n & 1; return x}
wolfhammer

@ user1455003 Grazie MOLTO o il tuo suggerimento! L'ho usato e adattato a ES6 e abbreviato molto. Grazie!
Ismael Miguel,

Prego! Mi piace quello che hai fatto. Con la ricorsione regolare javascript è sceso a 39! funzione B (n) {return n? (1 & n) + B (n >> 1): 0}
wolfhammer

@ user1455003 Se lo si desidera, è possibile modificare la parte ES5 e aggiungere il conteggio dei byte alla versione golfata. (Penso che tu vinca la reputazione con le modifiche).
Ismael Miguel,

@ user81655 WOW! Funziona!!! Grazie mille! Sapevo davvero che questo avrebbe potuto essere ridotto
Ismael Miguel,

2

> <> (Pesce) , 24 byte + 2 = 26

0$11.>~n;
2,:?!^:2%:{+}-

Il programma fa semplicemente ripetute mod 2, sottrae e divide fino a quando il numero di input diventa zero, quindi stampa la somma delle mod 2s.

Prova con la -vbandiera, ad es

py -3 fish.py ones.fish -v 1337

Per un numero intero a 16 bit, l'ingresso del punto di codice probabilmente non è adeguato. (La -vversione bandiera funziona ancora.)
randomra

@Randomra Accidenti, hai ragione. Mentre l'ingresso Unicode funziona, a 16 bit è solo qualche ordine di grandezza fuori portata ...
Sp3000

2

PHP (38 byte):

Questo utilizza lo stesso approccio della mia risposta ES6

<?=count(split(1,decbin($_GET[n])))-1;

Questo è un codice completo, devi solo inserirlo in un file e accedervi tramite il browser, con il parametro n=<number>.

PHP <4.2 (32 byte):

Questo è un po 'più breve:

<?=count(split(1,decbin($n)))-1;

Funziona in modo affidabile su PHP <4.2 perché la direttiva register_globalsera impostata di Offdefault da PHP4.2 fino a PHP5.4 (che è stata rimossa da allora).

Se crei un php.inifile con register_globals=On, funzionerà.

Per usare il codice, accedi al file usando un browser, con POST o GET.

@ViniciusMonteiro 's suggerimento (38/45 byte):

Ha dato 2 suggerimenti davvero buoni che hanno un uso molto interessante della funzione array_sum:

38 byte:

<?=array_sum(str_split(decbin(1337)));

45 byte:

<?=array_sum(preg_split('//', decbin(1337)));

Questa è davvero un'ottima idea e può essere abbreviata un po 'di più, per essere lunga 36 byte:

<?=array_sum(split(1,decbin(1337)));

2
Oppure puoi usare echo array_sum (str_split (decbin (1337))); e puoi usare anche echo array_sum (preg_split ('//', decbin (1337)));
Vinicius Monteiro,

1
@ViniciusMonteiro Grazie mille per il tuo suggerimento. L'ho adorato davvero! L'ho aggiunto alla risposta.
Ismael Miguel,

Guadagna quattro byte usando <?=substr_count(decbin(1337),"1");(34 byte)
Cogicero il

1
@Cogicero e si può risparmiare ancora di più, eliminando le virgolette: <?=substr_count(decbin(1337),1);. Questo è un totale di 32 byte. Considerando che si tratta di un codice abbastanza diverso, non vuoi pubblicarlo come risposta personale? Sicuramente lo voterò!
Ismael Miguel,

@Cogicero Sono solo due byte più brevi se usi la parametrizzazione: <?=substr_count(decbin($argv[1]),1);(o $_GET[n]; 36 byte)
Tito


2

Japt, 3 byte (non competitivo)

¢¬x

Provalo qui.


Amico, non vedo mai quelle date per qualche motivo.
Mama Fun Roll

1
Haha, Japt è il più breve: D BTW, ¢o1 lfunzionerebbe anche. Un altro approccio interessante è -¢¬r-0; ¢¬si divide in una matrice di cifre binarie, r-0riduce per sottrazione, a partire da 0 e -annulla il risultato, rendendolo positivo.
ETHproductions

A partire da ieri sera, ora puoi usare ¢¬x.
ETHproductions

2

cera d'api ,31 27 byte

Risposta non competitiva. La cera d'api è più recente di questa sfida.

Questa soluzione utilizza il modo di Brian Kherigan di contare i bit impostati dal sito Web "Bit Twiddling Hacks".

scorre semplicemente attraverso un ciclo, incrementando il conteggio dei bit, mentre scorre ripetutamente number=number&(number-1) fino a number = 0. La soluzione passa attraverso il ciclo tutte le volte che ci sono bit impostati.

Potrei radere 4 byte riorganizzando alcune istruzioni. Sia il codice sorgente che la spiegazione sono stati aggiornati:

pT_
>"p~0+M~p
d~0~@P@&<
{@<

Spiegazione:

pT_            generate IP, input Integer, redirect
>"             if top lstack value > 0 jump next instruction,
               otherwise continue at next instruction
  p            redirect if top lstack value=0 (see below)
   ~           flip top and 2nd lstack values
    0+         set top lstack value to 0, set top=top+2nd
      M        decrement top lstack value
       ~       flip top and 2nd lstack values
        p      redirect to lower left
        <      redirect to left
       &       top=top&2nd
      @        flip top and 3rd lstack values
    @P         increment top lstack value, flip top and 3rd values
 ~0~           flip top and 2nd values, set top=0, flip top and 2nd again
d              redirect to upper left
>"p~0+M.....   loop back

  p            if top lstack = 0 at " instruction (see above), redirect
  0            set lstack top to zero (irrelevant instruction)
  <            redirect to the left
 @             flip top and 3rd lstack values
{              output top lstack value as integer (bitcount)

Clona il mio repository GitHub contenente l'interprete di cera d'api, le specifiche della lingua e gli esempi.


1

Java, 17 byte

Opere per byte, short, char, e int. Usa come lambda.

Integer::bitCount

Prova qui

Senza usare i built-in:

42 byte

s->{int c=0;for(;s!=0;c++)s&=s-1;return c}

Prova qui


6
questa è una scappatoia standard: sono vietate le funzioni integrate che fanno esattamente ciò che si desidera.
FUZxxl

@FUZxxl L'OP non ha mai proibito le scappatoie standard
Cole Johnson

1
Si presume che le scappatoie standard di
es1024

6
@FUZxxl Mentre es1024 ha ragione sul fatto che le scappatoie standard sono chiuse per impostazione predefinita, l'utilizzo delle funzioni integrate non è attualmente una scappatoia accettata con una suddivisione dei voti di + 43 / -26.
Martin Ender,

1

Clip , 6

2 modi:

cb2nx1

Questa è una traduzione semplice del requisito: il conteggio di quelli nella rappresentazione del numero in base 2.

r+`b2n

Un altro metodo, che prende la somma delle cifre della rappresentazione base-2.


1

Ottava, 18

sum(dec2bin(s)-48)

Esempio:

octave:1> s=1337
s =  1337
octave:2> sum(dec2bin(s)-48)
ans =  6

1

GML (Game Maker Language), 21 byte

for(n=0;x;n/=2)n+=x&1

1

C # 39 byte

Convert.ToString(X,2).Count(C=>C=='1');


1

PowerShell (51 byte)

"$([char[]][convert]::ToString($s,2)|%{"+$_"})"|iex

Spiegazione:
[convert]::ToString($s,2)produce una rappresentazione di stringa binaria da $s.
[char[]]lo lancia come un array di caratteri e ci consente di enumerare ogni carattere.
|%{"+$_"}antepone ogni carattere con un segno +
"$()"chiama in modo implicito .ToString()la sottoespressione risultante
|iexsomma la stringa inoltrata (ovvero. "+1 +0 +1 +1 +0 +1 +0 +0" = 4)


Hiya! Seguendo la stessa logica che hai, perché non usare l' -joinoperatore inline e un implicito .ToString()per raggiungere 45 byte con [char[]][convert]::ToString($s,2)-join'+'|iex... OPPURE, come approccio diverso usa l' -replaceoperatore inline per raggiungere 43 byte con([convert]::ToString($s,2)-replace0).length
AdmBorkBork

1

Clojure, 42 byte

#(count(filter #{\1}(Long/toString % 2)))

Leggendo da destra a sinistra, converti in una stringa binaria, converti in una sequenza di caratteri, filtra su 1s e conta quanti ne hai.

EDITED Con l'aiuto di Sieg


42:#(count(filter #{\1}(Integer/toString% 2)))
seequ,

Hai bisogno di un altro personaggio#(count(filter #{\1}(Integer/toString % 2)))
Neil Masson,

No non lo fai. :)
seequ

Questo è quello che ho ottenuto quando l'ho provato:CompilerException java.lang.IllegalArgumentException: No matching method: toString_PERCENT_
Neil Masson,

L'ho provato in Try Clojure. Apparentemente la pagina improvvisamente non riconosce Integer/toString. Ha funzionato un secondo fa però.
Seequ,

1

Haskell 42 caratteri

t 0=[]
t n=t(quot n 2)++[rem n 2]
f=sum.t

dichiara l' f :: Integer -> Integer
uso della funzione dall'interprete interattivo come f <number>o aggiunge la riga main=print$f <number>alla fine del file.


Puoi salvare molti byte sommando direttamente la rem n 2s invece di crearne un elenco e usando divinvece di quot: t 0=0 t n=t(div n 2)+rem n 2- no fpiù.
nimi

1

Matlab, 13 byte

de2bicrea un vettore di zeri e uno che rappresenta il numero binario e sumrestituisce semplicemente la somma di tutte le voci.

sum(de2bi(n))

1

𝔼𝕊𝕄𝕚𝕟, 4 caratteri / 11 byte (non competitivo)

⨭⟦ïⓑ

Try it here (Firefox only).

Spiegazione

Converte l'input in binario, si divide lungo i caratteri e ottiene la somma dell'array risultante.

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.