Conte o número de unidades em um número inteiro de 16 bits não assinado

24

Escreva algumas instruções que contarão o número de unidades em um número inteiro de dezesseis bits não assinado.

Por exemplo, se a entrada for 1337, então o resultado é 6devido 1337como um número binário de dezesseis bit é 0000010100111001, que contém seis queridos.

ayane
fonte
2
Dica: assim como a alguns dos dígitos de um número é congruente com o número mod 9, a alguns de bits é igual ao número mod 1.
PyRulez
8
@PyRulez Qualquer número é zero módulo 1.
Thomas
11
Olá, você escolheu uma resposta errada como resposta aceita (por padrão, a lógica do desempatador da publicação mais antiga).
Optimizer
4
@ Thomas Eu nunca disse que era uma dica útil.
PyRulez
2
Por que esta pergunta está atraindo votos próximos APÓS a maioria das respostas ter sido publicada? Fechar os eleitores, por favor indique o seu motivo nos comentários. Se for a aceitação da resposta de 4 bytes do es1024 (muito inteligente) que não está em conformidade com as brechas padrão (porque usa um embutido), indique que esse é o motivo. Caso contrário, o que é isso?
Level River St

Respostas:

37

80386 Código da máquina, 4 bytes

F3 0F B8 C1

que recebe o número inteiro cxe gera a contagem axe é equivalente a:

popcnt ax, cx     ; F3 0F B8 C1

E aqui está uma solução de 11 10 bytes que não usa POPCNT:

31 C0 D1 E9 10 E0 85 C9 75 F8

que é equivalente 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
es1024
fonte
Isso está no modo de 32 ou 16 bits (real ou protegido)?
FUZxxl 17/03/2015
2
@FUZxxl A montagem é fornecida para 16 bits, embora substituindo axe cxcom eaxe ecxmuda-a para 32 bits. O bytecode é o mesmo para ambos.
es1024
11
@ es1024 O código de bytes é o mesmo se este tiver sido compilado no modo de 16 bits e a versão de 32 bits no modo de 32 bits.
Cole Johnson
2
O popcnt não é incorporado e, portanto, está em falta de brechas comuns? Ainda assim, crédito pela segunda solução.
Alchymist
5
Quando você reivindica o comprimento do código da máquina , o título não deve ser "Código da Máquina 80386" e não "Montador 80386"?
Kevin Reid
14

Python 2, 17 bytes

bin(s).count('1')

O bininterno retorna o número inteiro convertido em uma seqüência de caracteres binária. Contamos então os 1dígitos:

>>> s=1337
>>> bin(s)
'0b10100111001'
>>> bin(s).count('1')
6
Cavaleiro Lógico
fonte
11

J (5 caracteres)

J não tem tipos explícitos. Isso faz a coisa certa para todos os números inteiros.

+/@#:
  • +/ a soma
  • @ do
  • #: a representação de base dois
FUZxxl
fonte
11

C, 21

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

você disse "escreva algumas instruções" (não "uma função"), portanto, assumi que o número é fornecido xe o número de 1 é retornado n. Se não precisar inicializar n, posso salvar 3 bytes.

Esta é uma adaptação da famosa expressão x&x-1para testar se algo é uma potência de 2 (falso se for, verdadeiro se não for).

Aqui está em ação o número 1337 da pergunta. Observe que subtrair 1 vira o 1 bit menos significativo e todos os zeros para a direita.

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

EDIT: para completar, aqui está o algoritmo ingênuo, que é um byte mais longo (e um pouco mais lento).

for(n=0;x;x/=2)n+=x&1;
Level River St
fonte
11
@ edc65, como se vê, reinventei a roda. Pelo menos salvei 2 bytes, omitindo o {}. É uma tarefa tão simples que não deveria me surpreender que alguém já a tenha apresentado.
Level River St
"Publicado pela primeira vez em 1960" , impressionante.
mbomb007
Correção para o algoritmo ingênuo:for(n=0;x;x/=2)n+=x&1;
Helios
11
@nmxprime o OP solicita int não assinado. para -7 = 11111111 11111111 11111111 11111001 no meu compilador de 32 bits, recebo 30 para o algoritmo rápido, que está correto. Para o algoritmo ingênuo, itera através de -7, -7 / 2 = -3, -3 / 2 = -1, -1 / 2 = 0. Isso dá uma resposta incorreta. Alterar x / = 2 para x >> = 1 pode dar a resposta correta em alguns compiladores, mas C é indefinido sobre se um 1 ou 0 é deslocado para o bit vazio para >> em números negativos. Aqueles compiladores que trocam 1 in entrarão em um loop infinito. A solução alternativa é definir x como um int não assinado. Então x = -7 carrega (1 << 32) -7 = 4294967289 em x.
Level River St
5

Gelatina , não concorrente

Essa resposta não é competitiva, pois o idioma foi criado após o lançamento do desafio.

2 bytes:

BS

Jelly é uma nova linguagem escrita por @Dennis, com sintaxe semelhante a J.

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

Experimente aqui .

lirtosiast
fonte
4

Pitão, 4 bytes

sjQ2

O programa leva o número cujo peso do hamming pode ser encontrado no STDIN.

isaacg
fonte
4

Julia, 29 27 19 bytes

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

Isso cria uma função anônima que aceita um único argumento n,. Para usá-lo, atribua-o a algo como f=n->...e chame-o como f(1337).

A digits()função, quando chamada com 2 argumentos, retorna uma matriz dos dígitos da entrada na base fornecida. Então, digits(n, 2)retorna os dígitos binários de n. Pegue a soma da matriz e você terá o número de unidades na representação binária de n.

Alex A.
fonte
Isso pode ser bem mais curto: Julia tem uma funçãocount_ones
Andrew diz Reinstate Monica
@AndrewPiliser: Obrigado pela sugestão, mas as funções internas que realizam exatamente a tarefa são consideradas uma brecha padrão e são mal vistas quando não são explicitamente proibidas.
Alex A.
3

CJam, 6 bytes

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";

Experimente online aqui

Optimizer
fonte
3

Joe , 4 bytes

/+Ba

Esta é uma função anônima. Bafornece a representação binária de um número e o /+soma.

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

R, 24 bytes

sum(intToBits(scan())>0)

scan() lê a entrada de stdin.

intToBits()pega um número inteiro e retorna um vetor do tipo que rawcontém os zeros e os da representação binária da entrada.

intToBits(scan())>0retorna um vetor lógico onde cada elemento está TRUEse o elemento do vetor binário correspondente for 1 (já que todos os elementos são 0 ou 1 e 1> 0), caso contrário FALSE.

Em R, você pode somar um vetor lógico para obter o número de TRUEelementos, portanto, somar o vetor de lógicos como acima nos dá o que queremos.

Observe que sum()não é possível manipular a rawentrada diretamente, portanto, a solução alternativa usando lógicas.

Alex A.
fonte
Não sum(intToBits(scan()))seria o mesmo?
seequ
@ Sii: Infelizmente não, uma vez sum()que não pode receber entrada do tipo raw, que é o que é retornado intToBits().
Alex A.
Isso é realmente estranho para mim.
seequ
11
@ Sii: Sim, é estranho para mim também. Ah bem. Se todas as costeletas de porco fossem perfeitas, não teríamos cachorro-quente.
Alex A.
E essa é a metáfora mais estranha de todas.
seequ
3

Ruby, 18 bytes

n.to_s(2).count'1'

GreyCat
fonte
11
n.to_s(2).count ?1também funciona, mas é o mesmo comprimento
Piccolo
Versão 2019: n.digits (2) .sum / 15 bytes
GB
3

Quarto, 48 49 bytes

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

Se uma função real for necessária, a segunda linha se tornará

: c 0 swap c ;

e você chama "1337 c". As palavras de controle relativamente detalhadas da Forth fazem com que seja difícil (na verdade, elas tornam muito difícil).

Editar: minha versão anterior não lidava com números negativos corretamente.

Nagora
fonte
3

Mathematica, 22 18 bytes

Obrigado a alephalpha por me lembrar DigitCount.

DigitCount[#,2,1]&
Martin Ender
fonte
@alephalpha obrigado, mas DigitCount leva outro parâmetro :)
Martin Ender
3

ES6 (34 22 21 bytes):

Esta é uma função recursiva simples que pode ser reduzida um pouco mais. Simplesmente demora um pouco e roda novamente:

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

Experimente em http://www.es6fiddle.net/imt5ilve/ (você precisa do varmotivo 'use strict';).

Não acredito que derrotei o peixe !!!

O antigo:

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

ES5 (39 bytes):

Ambas as funções podem ser facilmente adaptadas ao 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;
    }
}

Antigo:

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

O @ user1455003 me deu uma ótima idéia, que 'desencadeou' a menor:

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

Eu o adaptei ao ES6 e o ​​tornei recursivo para diminuir muito!

Ismael Miguel
fonte
11
Aqui está uma função javascript 'regular' menor. função B (n, x) {para (x = 0; n; n = 1 >>) X + = n & 1; retorno x}
wolfhammer
@ user1455003 Muito obrigado ou sua sugestão! Usei-o e adaptei-o ao ES6 e reduzi muito. Obrigado!
Ismael Miguel
Não há de quê! Eu gosto do que você fez com isso. Com a recursão, o javascript regular cai para 39! função B (n) {return n? (1 & n) + B (n >> 1): 0}
wolfhammer 23/03
@ user1455003 Se desejar, você pode editar a parte ES5 e adicionar a contagem de bytes à versão em golf. (Eu acho que você ganha reputação com edições).
Ismael Miguel
@ user81655 WOW! Funciona!!! Muito obrigado! Eu realmente sabia que isso poderia ser feito mais curto
Ismael Miguel
2

> <> (Peixe) , 24 bytes + 2 = 26

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

O programa apenas repete o mod 2, subtrai e divide até que o número de entrada se torne zero e depois imprime a soma do mod 2s.

Teste com a -vbandeira, por exemplo

py -3 fish.py ones.fish -v 1337
Sp3000
fonte
Para um número inteiro de 16 bits, a entrada do codepoint provavelmente não é adequada. (A -vversão bandeira ainda funciona.)
randomra
@randomra Porra, você está certo. Enquanto a entrada Unicode funciona, 16 bits é apenas algumas ordens de magnitude fora do intervalo ...
Sp3000
2

PHP (38 bytes):

Isso usa a mesma abordagem da minha resposta ES6

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

Este é um código completo, você só precisa colocá-lo em um arquivo e acessá-lo sobre o navegador, com o parâmetro n=<number>.

PHP <4.2 (32 bytes):

Isso é um pouco mais curto:

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

Isso só funciona de maneira confiável no PHP <4.2, porque a diretiva register_globalsfoi definida Offpor padrão do PHP4.2 até o PHP5.4 (que foi removido até então).

Se você criar um php.iniarquivo com register_globals=On, isso funcionará.

Para usar o código, acesse o arquivo usando um navegador, com POST ou GET.

Sugestão de @ViniciusMonteiro (38/45 bytes):

Ele deu duas sugestões muito boas que têm um uso muito interessante da função array_sum:

38 bytes:

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

45 bytes:

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

Essa é realmente uma ótima idéia e pode ser reduzida um pouco mais, para ter 36 bytes de comprimento:

<?=array_sum(split(1,decbin(1337)));
Ismael Miguel
fonte
2
Ou você pode usar echo array_sum (str_split (decbin (1337))); e você também pode usar echo array_sum (preg_split ('//', decbin (1337)));
Vinicius Monteiro
11
@ViniciusMonteiro Muito obrigado pela sua sugestão. Eu realmente adorei! Eu adicionei à resposta.
Ismael Miguel
Ganhe quatro bytes usando <?=substr_count(decbin(1337),"1");(34 bytes)
Cogicero
11
@Cogicero E você pode economizar ainda mais, removendo as aspas: <?=substr_count(decbin(1337),1);. Isso é um total de 32 bytes. Considerando que é um código suficientemente diferente, você não deseja publicá-lo como sua própria resposta? Eu certamente vou votar!
Ismael Miguel
@Cogicero São apenas dois bytes mais curtos se você usar a parametrização: <?=substr_count(decbin($argv[1]),1);(ou $_GET[n]; 36 bytes)
Titus
2

C #, 45 bytes

Convert.ToString((ushort)15,2).Sum(b=>b-48);

https://dotnetfiddle.net/kJDgOY

albertjan
fonte
b-48é ainda mais curto, AFAIK
ThreeFx 19/03/2015
Corrigir! :) eu vou atualizar.
Albertjan 19/03/2015
2

Japt, 3 bytes (não competitivo)

¢¬x

Experimente aqui.

Mama Fun Roll
fonte
Cara, nunca vejo essas datas por algum motivo.
Mama Fun Roll
11
Haha, Japt é o mais curto: D BTW, ¢o1 ltambém funcionaria. Outra abordagem interessante é -¢¬r-0; ¢¬divide em uma matriz de dígitos binários, r-0reduz por subtração, começando em 0 e -nega o resultado, tornando-o positivo.
ETHproductions
Desde a noite passada, agora você pode usar ¢¬x.
ETHproductions
2

cera de abelha ,31 27 bytes

Resposta não concorrente. A cera de abelha é mais nova que esse desafio.

Esta solução usa a maneira de Brian Kherigan de contar bits definidos no site “Bit Twiddling Hacks”.

apenas percorre um loop, incrementando a contagem de bits, enquanto percorre number=number&(number-1)até number = 0. A solução só passa pelo loop sempre que houver bits definidos.

Eu poderia raspar 4 bytes reorganizando algumas instruções. O código-fonte e a explicação foram atualizados:

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

Explicação:

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)

Clone meu repositório GitHub que contém o intérprete de cera de abelha, especificações de linguagem e exemplos.

ML
fonte
1

Java, 17 bytes

Trabalha para byte, short, chare int. Use como um lambda.

Integer::bitCount

Teste aqui

Sem usar built-ins:

42 bytes

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

Teste aqui

O número um
fonte
6
Esta é uma brecha padrão: funções internas que fazem exatamente o que você deseja são proibidas.
FUZxxl 17/03/2015
@FUZxxl O OP nunca proibiu brechas comuns #
Cole Johnson
6
@FUZxxl Embora es1024 esteja certo de que as brechas padrão estão fechadas por padrão, o uso de funções internas não é atualmente uma brecha aceita em uma discriminação de + 43 / -26.
Martin Ender
1

Clipe , 6

2 maneiras:

cb2nx1

Esta é uma tradução direta do requisito: a contagem de unidades na representação base-2 do número.

r+`b2n

Outro método, que leva a soma dos dígitos da representação base-2.

Ypnypn
fonte
1

Oitava, 18

sum(dec2bin(s)-48)

Exemplo:

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

GML (linguagem do criador de jogos), 21 bytes

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

Bytes em C # 39

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

Perl, 21

$r=grep$v&1<<$_,0..15
nutki
fonte
1

PowerShell (51 bytes)

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

Explicação:
[convert]::ToString($s,2)produz uma representação de sequência binária de $s.
[char[]]lança como uma matriz de caracteres e nos permite enumerar cada caracter.
|%{"+$_"}precede cada caractere com um sinal + que
"$()"implica implicitamente .ToString()na subexpressão resultante,
|iexsomando a cadeia de caracteres canalizada (por exemplo, "+1 +0 +1 +1 +0 +1 +0 +0" = 4)

Mathias R. Jessen
fonte
Hiya! Seguindo a mesma lógica que você tem, por que não usar a linha -joindo operador e um implícito .ToString()para alcançar 45 bytes com [char[]][convert]::ToString($s,2)-join'+'|iex... OU, como o uso abordagem em linha diferente -replaceoperadora a atingir 43 bytes com([convert]::ToString($s,2)-replace0).length
AdmBorkBork
1

Clojure, 42 bytes

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

Lendo da direita para a esquerda, converta em uma seqüência de caracteres binária, converta em uma sequência de caracteres, filtre em se 1conte quantos você possui.

EDITADO Com a ajuda de Sieg

Neil Masson
fonte
42: #(count(filter #{\1}(Integer/toString% 2)))
seequ
Você precisa de mais um personagem #(count(filter #{\1}(Integer/toString % 2)))
Neil Masson
Não, você não. :)
Veja
Isto é o que eu recebi quando tentei: CompilerException java.lang.IllegalArgumentException: No matching method: toString_PERCENT_
Neil Masson
Eu testei no Try Clojure. Aparentemente, a página de repente não reconhece Integer/toString. Funcionou um segundo atrás, no entanto.
seequ
1

Haskell 42 chars

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

declara o f :: Integer -> Integer
uso da função do intérprete interativo como f <number>ou adiciona a linha main=print$f <number>ao final do arquivo.

HEGX64
fonte
Você pode salvar muitos bytes somando diretamente os rem n 2s em vez de criar uma lista deles e usando em divvez de quot: t 0=0 t n=t(div n 2)+rem n 2- não fmais.
N
1

Matlab, 13 bytes

de2bicria um vetor de zeros e uns que representam o número binário e sumapenas retorna a soma de todas as entradas.

sum(de2bi(n))
flawr
fonte
1

4, 4 caracteres / 11 bytes (não competitivo)

⨭⟦ïⓑ

Try it here (Firefox only).

Explicação

Converte a entrada em binário, divide-se ao longo de caracteres e obtém a soma da matriz resultante.

Mama Fun Roll
fonte