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

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.)

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.


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)


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
  [-<<<<+>>>>]
  <<<<
]

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.


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.


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


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.


4

Python 2.6, 45 caracteres

b=lambda n:n and n%2+b(n/2) 
print b(input())

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.


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 .


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.)


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


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

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).


É 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.


2

Haskell (60 caracteres)

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

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.


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))  


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



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

1

OCaml, 52 caracteres

let rec o x=if x=0 then 0 else (x mod 2) + (o (x/2))

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))])))

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.


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 :(


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 ...


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


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.


Bem vindo ao site! :)
— DJMcMayhem
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.