Imprima a quantidade de unidades em um número binário sem usar operadores bit a bit

14

Descrição

Dado um número, imprima a quantidade de 1s que possui na representação binária.

Entrada

Um número >= 0na base 10 que não excederá o número mais alto que o seu idioma pode manipular.

Resultado

A quantidade de 1s na representação binária.

Condição vencedora

O código mais curto vence.

Não permitido

  • Operadores bit a bit. Outros operadores, como adição e multiplicação, são permitidos.
  • Funções de conversão de base incorporadas.

Exemplos

Input:     Ouput:

56432      8


Input:     Output:

45781254   11


Input:     Output:

0          0
pimvdb
fonte
As funções são permitidas? Eu quero fazer uma solução Java, mas escrever código completo é muito tedioso ...: /
HyperNeutrino 13/02/16
1
Eu acho que não vai usar sábio para este desafio ... :)
MildlyMilquetoast

Respostas:

16

APL, 9 12 caracteres

+/2|⌊⎕÷2*⍳32

Isso pressupõe que o intérprete use números inteiros de 32 bits e que ⎕IOseja definido como 0 (o que significa que o monádico começa com 0, em vez de 1). Eu usei a versão de 32 bits do Dyalog APL .

Explicação, da direita para a esquerda:

  • ⍳32gera um vetor dos primeiros 32números inteiros (como explicado anteriormente, porque ⎕IOé 0, esse vetor começa com 0).
  • *é a função de poder. Nesse caso, gera 2a potência de cada elemento do vetor fornecido como argumento correto.
  • ÷é a função dividida por. Ele nos fornece (entrada do usuário avaliada) dividida por cada elemento do vetor à sua direita (cada potência de dois).
  • coloca cada elemento do argumento à sua direita.
  • 2|nos dá o restante de cada elemento à sua direita dividido por 2.
  • /reduz (dobra) seu argumento correto usando a função à esquerda +,.

Não são mais 9 caracteres. :(

Versão antiga e de quebra de regras:

+/⎕⊤⍨32/2

Explicação, da direita para a esquerda:

  • 32/2: Replicar 2, 32horários.
  • comuta a função diádica para a esquerda, que neste caso é (isto X⊤⍨Yé , é equivalente a Y⊤X).
  • é a função de codificação. Ele codifica o número inteiro à sua direita na base dada à sua esquerda. Observe que, devido ao operador de comutação, os argumentos direito e esquerdo são alternados. A base é repetida para o número de dígitos necessários, portanto 32/2.
  • é uma função niládica que aceita a entrada do usuário e a avalia.
  • +/reduz (dobra) seu argumento correto usando +. (Adicionamos os zeros e zeros.)
Dillon Cower
fonte
2
Isso não quebra o Built-in base conversion functionscontraint?
Gareth
Ops! Perdeu esse.
Dillon Cower
Gah! Pensei que tinha me dado uma chance de lutar com o meu programa J! :-) Bom trabalho.
Gareth
@Gareth: Eu não percebi até ler sua explicação agora, mas minha resposta é praticamente idêntica à sua! Eu acho que poderia ser esperado de APL e J. :)
Dillon Cower
11

Brainbool , 2

,.

A interpretação mais razoável, na minha opinião (e o que a maioria das respostas usa) de "número mais alto que seu idioma é capaz de lidar" é "número maior que seu idioma suporta nativamente ". Brainbool é um derivado cerebral que usa bits em vez de bytes, e recebe entrada e saída em binário ( 0e 1caracteres) em vez de códigos de caracteres. O maior número suportado nativamente é, portanto,1 , , e o menor é 0, que tem pesos de Hamming 1e, 0respectivamente.

Brainbool foi criado em 2010, de acordo com Esolang.

lirtosiast
fonte
9
Eu sabia que deveria ter existido, mas levei uma hora para classificar os derivados Brainfuck na Esolang para encontrar o Brainbool.
lirtosiast
8

J, 13 caracteres

(+ o número de dígitos no número)

+/2|<.n%2^i.32

Uso: substitua o nno programa pelo número a ser testado.

Exemplos:

+/2|<.56432%2^i.32
8
+/2|<.45781254%2^i.32
11
+/2|<.0%2^i.32
0

Provavelmente existe uma maneira de reorganizar isso para que o número possa ser colocado no início ou no fim, mas esta é a minha primeira entrada em J e minha cabeça está doendo um pouco agora.

Explicação (principalmente para que eu entenda no futuro)

i.32 - cria uma matriz dos números de 1 a 32

2^ - transforma a lista nas potências de dois 1 a 4294967296

n% - divide o número de entrada por cada elemento da lista

<. - arredonda todos os resultados da divisão até o próximo número inteiro

2|- o mesmo que %2na maioria dos idiomas - retorna 0 se for par e 1 se for ímpar

+/ - totaliza os itens da lista (que agora são apenas 1s ou 0s)

Gareth
fonte
Ficarei feliz em votar novamente assim que ler a partir de stdin (ou qualquer outro J equivalente).
Steven Rumbalski
O melhor que pude fazer (talvez, dependendo de descobrir como) é mover a entrada para o final do programa. A entrada padrão não é mencionada na pergunta?
Gareth
Sinto muito por não especificar o caminho da entrada. Seria injusto mudar as regras agora, então vou aceitar essa. Vou mencionar na próxima vez!
Pimvdb
@pimvdb Sem problemas, não foi uma reclamação. Eu acho que com os programas J, embora tudo o que você possa fazer é definir um verbo que opere na entrada fornecida. Não tenho certeza de como eu reorganizaria isso para fazer isso. Talvez JB ou um dos outros especialistas J poderia me ajudar com isso ...
Gareth
... e depois de ler um pouco mais, agora vejo que estava completamente errado sobre a entrada padrão.
Gareth
8

Brainfuck, 53 caracteres

Faltava uma solução obrigatória da Brainfuck, então fiz esta:

[[->+<[->->>>+<<]>[->>>>+<<]<<<]>>>>[-<<<<+>>>>]<<<<]

Pega o número da célula 1 e coloca o resultado na célula 6.

Versão não registrada e comentada:

[  while n != 0
  [  div 2 loop
    -
    >+<  marker for if/else
    [->->>>+<<]  if n != 0 inc n/2
    >
    [->>>>+<<]  else inc m
    <<<
  ]
  >>>>  move n/2 back to n
  [-<<<<+>>>>]
  <<<<
]
cópia de
fonte
6

Python 2.6, 41 caracteres

t,n=0,input()
while n:t+=n%2;n/=2
print t

Nota: Minha outra resposta usa lambda e recursão e esta usa um loop while. Eu acho que eles são diferentes o suficiente para justificar duas respostas.

Steven Rumbalski
fonte
6

Ruby, 38 caracteres

f=->u{u<1?0:u%2+f[u/2]}
p f[gets.to_i]

Outra solução usando ruby ​​e a mesma abordagem recursiva que Steven.

Howard
fonte
5

GolfScript, 17 16 caracteres

~{.2%\2/.}do]0-,

Editar: a nova versão salva 1 caractere usando a operação de lista em vez da dobra (a versão original era ~{.2%\2/.}do]{+}*, versão de contagem direta:) ~0\{.2%@+\2/.}do;.

Howard
fonte
5

C, 45

f(n,c){for(c=0;n;n/=2)c+=n%2;printf("%d",c);}

Nada realmente especial aqui para jogar golfe em C: tipo de retorno implícito, tipo inteiro implícito para parâmetros.

Mr. Llama
fonte
4

Python 2.6, 45 caracteres

b=lambda n:n and n%2+b(n/2) 
print b(input())
Steven Rumbalski
fonte
1
Pode ser reduzido por dois caracteres usando em defvez de uma lambda.
Konrad Rudolph
1
@KonradRudolph: Na verdade, você perde a vantagem depois de incluir a declaração de retorno.
Steven Rumbalski
Opa, eu esqueci isso. Estúpido.
Konrad Rudolph
Você não precisa do print b(input()). É aceitável retornar o valor e receber "input" como argumentos para funções.
caird coinheringaahing
4

Perl, 45 43 36 caracteres

$n=<>;while($n){$_+=$n%2;$n/=2}print

Agradecimentos a Howard por 45-> 43 e a User606723 por 43-> 36.

PhiNotPi
fonte
Você pode usar $n=int($n/2)quais 2 caracteres mais curtos.
Howard
Temos certeza de que precisamos do int ()? $n=<>;while($n){$_+=$n%2;$n/=2}printIsso continuará repetindo até que $ n / 2 finalmente chegue perto de 0, mas nos importamos? ;)
user606723
@ user606723 Acabei de experimentar isso e parece funcionar perfeitamente, pelo menos para todos os casos de até 1000. #
PhiNotPi
3

Perl, 30 caracteres

$==<>;1while$_+=$=%2,$=/=2;say

Baseado na solução da PhiNotPi , com um pouco de golfe extra. Execute com perl -M5.010para ativar o sayrecurso Perl 5.10 .

Ilmari Karonen
fonte
A $=variável especial faz algo especial no seu programa ou é apenas outra variável comum?
PhiNotPi
2
@PhiNotPi: $=leva apenas valores inteiros; portanto, usá-lo economiza um int.
Ilmari Karonen
O argumento da linha de comando não deve fazer parte da contagem de caracteres?
Soham Chowdhury
@SohamChowdhury: Não por este meta-thread .
Ilmari Karonen
3

Lisp comum, 12 caracteres

(assumindo um nome de variável com 1 caractere - ou seja: 11 + comprimento do número)

Não é uma função de conversão básica, portanto deve funcionar:

(logcount x)

Exemplos:

[1]> (logcount 0)
0
[2]> (logcount 1)
1
[3]> (logcount 1024)
1
[4]> (logcount 1023)
10
[5]> (logcount 1234567890123456789012345678901234567890)
68

(Usando o GNU CLISP.)

Joanis
fonte
Bem, não é exatamente o que eu tinha em mente para ver como resposta :) Acho que não posso aceitar isso. É basicamente apenas mais um caso disso .
Pimvdb
3

C, 61 60 57 53 caracteres

void f(x){int i=0;for(;x;x/=2)i+=x%2;printf("%u",i);}

O corpo da função possui apenas 38 caracteres. Edit : operador bit a bit removido Edit : coloque printffora do loop conforme sugerido nos comentários Edit : alterne para a declaração K&R; Além disso, isso não é mais específico ao C99

sam hocevar
fonte
Eu vejo bit a bit !!!
Joanis
Sinto muito, mas o operador AND também conta como um operador bit a bit.
Pimvdb
@ M.Joanis: duh, obrigado por perceber. Fixo.
sam hocevar 31/12/11
1
Eu acho que você poderia poupar alguns caracteres se mudasse para K&R C. Se você concorda com isso.
JB
Você pode encurtar isso em quatro caracteres movendo o printf para fora do loop.
Marinus
3

dc - 26 caracteres

Isso é bastante longo, principalmente devido à falta de construções de loop dc.

0?[d2%rsi+li2/d0<x]dsxx+p

Continua adicionando o módulo 2 do número e dividindo o número até até chegar a zero. Pode lidar com números inteiros arbitrariamente longos.

Exemplo:

$ dc -e '0?[d2%rsi+li2/d0<x]dsxx+p' <<< 127
7
$ dc countones.dc <<< 1273434547453452352342346734573465732856238472384263456458235374653784538469120235
138
daniero
fonte
3

C, 66 caracteres

main(int n,char **a){printf("%u",__builtin_popcount(atoi(a[1])))};

Nota: requer o gcc ou o compilador compatível com o gcc (por exemplo, ICC, clang).

Para algumas CPUs, __builtin_popcountcompila com uma única instrução (por exemplo, POPCNTem x86).

Paul R
fonte
É correto que __builtin_popcountrealmente apenas implemente a contagem de 1si? Em caso afirmativo, embora não seja estritamente errado de acordo com as regras, sinceramente não acho que essa seja uma entrada justa.
Pimvdb
Provavelmente, você deve estipular isso na pergunta se desejar não permitir entradas que aproveitem os recursos internos de um determinado idioma ou compilador.
Paul R
Isso não é legal em C ++, porque em C ++ você não pode omitir o tipo de retorno em main nem usar printfsem inclusão prévia.
Celtschk
@celtschk: fair point - editado oC++
Paul R
2

JavaScript, 78 72 71 caracteres

Vou postar minha solução inicial, que surgiu antes de postar a pergunta também. Já existe uma resposta JavaScript muito melhor :)

for(n=prompt(a=0),j=1;j<=n;j*=2)for(i=j;i<=n;i+=2*j)n<i+j&&a++;alert(a)

http://jsfiddle.net/Mk8zd/1/

A idéia vem de certos "cartões de leitura da mente" que permitem obter o número que alguém mais tem em mente, mostrando-lhes cartões e digam em quais cartões seu número é aparente.

Funciona porque cada número é uma combinação única de 1s / 0s em binário. Minha solução verifica em quais "cartões" o número é aparente para determinar quantos 1s ele possui. Mas não é muito eficiente ...

Encontrei este documento que descreve a técnica de leitura da mente.

pimvdb
fonte
2

Haskell (60 caracteres)

f n=sum[1|x<-[0..n],odd$n`div`2^x]
main=interact$show.f.read
marinus
fonte
2

PHP, 57

$i=$s=0;for(;$i<log($n,2);){$s+=$n/pow(2,$i++)%2;}echo$s;

Isso pressupõe que $n mantém o valor a ser testado.

PHP, 55 (solução alternativa)

function b($i){return$i|0?($i%2)+b($i/2):0;}echo b($n);

Novamente, isso pressupõe que $nmantém o valor a ser testado. Essa é uma alternativa porque usa o operador or parafloor na entrada.

Ambas as soluções funcionam e não causam avisos.

Arjan
fonte
2

Ocaml, 45 caracteres

Com base na solução de @Leah Xue. Três espaços podem ser removidos e é um pouco mais curto (~ 3 caracteres) para usar a função em vez de se-então-outro.

let rec o=function 0->0|x->(x mod 2)+(o(x/2))  
ReyCharles
fonte
2

Mathematica 26

Count[n~IntegerDigits~2,1]
DavidC
fonte
1

Scala, 86 caracteres

object O extends App{def f(i:Int):Int=if(i>0)i%2+f(i/2)else 0
print(f(args(0).toInt))}

Uso: scala O 56432

Gareth
fonte
1

D (70 caracteres)

int f(string i){int k=to!int(i),r;while(k){if(k%2)r++;k/=2;}return r;}
catraca arrepiante
fonte
1

R, 53 caracteres

o=function(n){h=n%/%2;n%%2+if(h)o(h)else 0};o(scan())

Exemplos:

> o=function(n){h=n%/%2;n%%2+if(h)o(h)else 0};o(scan())
1: 56432
2: 
Read 1 item
[1] 8
> o=function(n){h=n%/%2;n%%2+if(h)o(h)else 0};o(scan())
1: 45781254
2: 
Read 1 item
[1] 11
> o=function(n){h=n%/%2;n%%2+if(h)o(h)else 0};o(scan())
1: 0
2: 
Read 1 item
[1] 0

Se a inserção do número não fizer parte da contagem de caracteres, serão 43 caracteres:

o=function(n){h=n%/%2;n%%2+if(h)o(h)else 0}

com casos de teste

> o(56432)
[1] 8
> o(45781254)
[1] 11
> o(0)
[1] 0
Brian Diggs
fonte
1

OCaml, 52 caracteres

let rec o x=if x=0 then 0 else (x mod 2) + (o (x/2))
Leah Xue
fonte
1

Esquema

Eu poli as regras um pouco para adicionar ao desafio. A função não se importa com a base do número porque usa sua própria escala binária. Fui inspirado pela maneira como a conversão analógica para numérica funciona. Eu apenas uso recursão simples para isso:

(define (find-ones n)
  (define (nbits n)
    (let nbits ([i 2])
      (if (< i n) (nbits (* i 2)) i)))
  (let f ([half (/ (nbits n) 2)] [i 0] [n n])
    (cond [(< half 2) i]
      [(< n i) (f (/ half 2) i (/ n 2))]
      [else (f (/ half 2) (+ i 1) (/ n 2))])))
Samuel Duclos
fonte
1

A leitura de um número no binário ou a impressão do número no binário é uma "função de conversão básica interna", invalidando todas as respostas acima desse printnúmero inteiro? Se você permitir ler e imprimir um número inteiro, como quase todas as respostas acima, farei declarações usando uma função internapopcount :

Haskell, 50

Houve uma popCountrotina adicionada ao Data.Bitsmódulo para o GHC v7.2.1 / v7.4.1 neste verão (consulte os tickets sobre o primop e a encadernação ).

import Data.Bits
main=interact$show.popCount.read

Não consigo superar as pontuações acima em Python e Perl usando seus módulos GMPYou GMP::Mpzpara o GMP, infelizmente, embora o GMP ofereça uma função de contagem de pop - ups também.

Jeff Burdges
fonte
1

JavaScript, 49 47 45 42 bytes

for(n=prompt(o=0);n=n/2|0;o+=n%2);alert(o)

Demonstração: http://jsfiddle.net/hcYdx/4/

Editar 1: remova qe use ~~para arredondar, salve 2 caracteres.

Editar 2: use o |0operador de arredondamento em vez de ~~salvar parênteses (2 caracteres).

Editar 3: simplificar n>0a ne combinam com n=n/2|0para fazer a condição inteira; agora desperdiçamos espaço de declaração :(

mellamokb
fonte
3
O |0operador não é um bit a bit?
Vilx-
Tecnicamente sim. Mas eu estou usando isso apenas para arredondar para o int mais próximo, então eu não estou recebendo qualquer benefício bit-wise :)
mellamokb
Cheira a dobrar as regras para mim ... mas eu não sou o juiz.
Vilx-
A entrada 1 fornece a saída 0.
Atreys
1
|é operador bit a bit ... não é permitido. Hora de fazer Math.round:-)
Jamie
1

Java 7, 36 bytes

int b(Long a){return a.bitCount(a);}

Porque é claro que isso, de todas as coisas, é algo que o Java possui para ...

Cutucar
fonte
Isso não se encaixa nas "funções internas de conversão de base", que são proibidas?
FlipTack
@ Flp.Tkc Na verdade, não estou fazendo conversão de base. Não tenho ideia de como bitCountfunciona sob o capô.
puxão
este parece ser apenas usando um bulitin para fazer o trabalho, mas ok ...
FlipTack
@ Flp.Tkc Isso é ... exatamente o que é? Estou incluindo todas as bibliotecas necessárias (não existem). Isso está demonstrando a força da linguagem! meta relacionada
Poke
1

TI-Basic (TI-84 Plus CE), 30 bytes

Prompt X
0→S
While X
S+remainder(2,X→S
int(X/2→X
End
S

O TI-Basic é um idioma tokenizado, todos os tokens, mas remainder(são de um byte , o restante é dois

pizzapants184
fonte
Bem vindo ao site!
DJMcMayhem
1

PHP, 36 bytes

while($n){$o+=$n%2;$n/=2*1;}echo $o;

Assume que $né o número a ser testado, mostra um aviso do PHP $oe não funciona exatamente quando $né 0 (não gera nada).

PHP, 53 bytes

$n=$argv[1];$o=0;while($n){$o+=$n%2;$n/=2*1;}echo $o;

Aceita entrada da linha de comando, não mostra um aviso do PHP e sai corretamente para 0.

jstnthms
fonte
Bem vindo ao site! :)
DJMcMayhem