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 è 6
perché è 1337
un 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 è 6
perché è 1337
un numero binario a sedici bit 0000010100111001
, che ne contiene sei.
Risposte:
F3 0F B8 C1
che accetta il numero intero cx
e genera il conteggio ax
ed 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
ax
e cx
con eax
e lo ecx
cambi in 32 bit. Il bytecode è lo stesso per entrambi.
bin(s).count('1')
Il bin
built-in restituisce il numero intero convertito in una stringa binaria. Quindi contiamo le 1
cifre:
>>> 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 x
e il numero di 1 sia restituito n
. Se non devo inizializzare n
posso salvare 3 byte.
Questo è un adattamento della famosa espressione x&x-1
per 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 raw
contenente gli zeri e quelli della rappresentazione binaria dell'input.
intToBits(scan())>0
restituisce un vettore logico in cui si trova ogni elemento TRUE
se 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 TRUE
elementi, quindi sommare il vettore dei logici come sopra ci dà quello che vogliamo.
Si noti che sum()
non è possibile gestire raw
direttamente 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 var
motivo 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 -v
bandiera, ad es
py -3 fish.py ones.fish -v 1337
-v
versione 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_globals
era impostata di Off
default da PHP4.2 fino a PHP5.4 (che è stata rimossa da allora).
Se crei un php.ini
file 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 l
funzionerebbe anche. Un altro approccio interessante è -¢¬r-0
; ¢¬
si divide in una matrice di cifre binarie, r-0
riduce 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
|iex
somma la stringa inoltrata (ovvero. "+1 +0 +1 +1 +0 +1 +0 +0" = 4)
-join
operatore inline e un implicito .ToString()
per raggiungere 45 byte con [char[]][convert]::ToString($s,2)-join'+'|iex
... OPPURE, come approccio diverso usa l' -replace
operatore 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 1
s 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 2
s invece di crearne un elenco e usando div
invece di quot
: t 0=0
t n=t(div n 2)+rem n 2
- no f
più.
⨭⟦ïⓑ
Converte l'input in binario, si divide lungo i caratteri e ottiene la somma dell'array risultante.