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.
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.
Risposte:
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
axe cxcon eaxe lo ecxcambi in 32 bit. Il bytecode è lo stesso per entrambi.
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
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;
{}. È un compito così semplice che non dovrei essere sorpreso che qualcuno l'abbia già inventato.
for(n=0;x;x/=2)n+=x&1;
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 .
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.
count_ones
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";
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.
sum(intToBits(scan()))sarebbe lo stesso?
sum()non è possibile accettare input di tipo raw, da cui è stato restituito intToBits().
: 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.
Grazie ad alephalpha per avermelo ricordato DigitCount.
DigitCount[#,2,1]&
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
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!
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
-vversione bandiera funziona ancora.)
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>.
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.
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)));
<?=substr_count(decbin(1337),"1");(34 byte)
<?=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ò!
<?=substr_count(decbin($argv[1]),1);(o $_GET[n]; 36 byte)
¢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.
¢¬x.
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.
Opere per byte, short, char, e int. Usa come lambda.
Integer::bitCount
Senza usare i built-in:
42 byte
s->{int c=0;for(;s!=0;c++)s&=s-1;return c}
sum(dec2bin(s)-48)
Esempio:
octave:1> s=1337
s = 1337
octave:2> sum(dec2bin(s)-48)
ans = 6
"$([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)
-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
#(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
#(count(filter #{\1}(Integer/toString% 2)))
#(count(filter #{\1}(Integer/toString % 2)))
CompilerException java.lang.IllegalArgumentException: No matching method: toString_PERCENT_
Integer/toString. Ha funzionato un secondo fa però.
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.
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ù.
⨭⟦ïⓑ
Converte l'input in binario, si divide lungo i caratteri e ottiene la somma dell'array risultante.