Imprimer le nombre de uns dans un nombre binaire sans utiliser d'opérateurs au niveau du bit


14

La description

Étant donné un nombre, imprimez la quantité de 1s qu'il a en représentation binaire.

Contribution

Un nombre >= 0en base 10 qui ne dépassera pas le nombre le plus élevé que votre langue est capable de gérer.

Production

La quantité de 1s dans la représentation binaire.

Condition gagnante

Le code le plus court gagne.

Rejeté

  • Opérateurs au niveau du bit. D'autres opérateurs, comme l'addition et la multiplication, sont autorisés.
  • Fonctions de conversion de base intégrées.

Exemples

Input:     Ouput:

56432      8


Input:     Output:

45781254   11


Input:     Output:

0          0

Les fonctions sont-elles autorisées? Je veux faire une solution Java, mais écrire du code complet est trop fastidieux ...: /
HyperNeutrino

1
Je suppose que je n'utiliserai pas Wise pour ce défi ... :)
MildlyMilquetoast

Réponses:


16

APL, 9 12 caractères

+/2|⌊⎕÷2*⍳32

Cela suppose que l'interpréteur utilise des entiers 32 bits et qu'il ⎕IOest défini sur 0 (ce qui signifie que le monadique commence par 0, plutôt que 1). J'ai utilisé la version 32 bits de Dyalog APL .

Explication, de droite à gauche:

  • ⍳32génère un vecteur des premiers 32entiers (comme expliqué précédemment, car ⎕IOétant 0, ce vecteur commence par 0).
  • *est la fonction de puissance. Dans ce cas, il génère 2à la puissance de chaque élément du vecteur fourni comme argument de droite.
  • ÷est la fonction divisée par. Il nous donne (entrée utilisateur évaluée) divisé par chaque élément du vecteur à sa droite (chaque puissance de deux).
  • pose chaque élément de l'argument à sa droite.
  • 2| nous donne le reste de chaque élément de sa droite divisé par 2 .
  • /réduit (replie) son argument de droite en utilisant la fonction à sa gauche +,.

Plus tout à fait 9 caractères. :(

Ancienne version sans règles:

+/⎕⊤⍨32/2

Explication, de droite à gauche:

  • 32/2: Répliquer 2, 32fois.
  • commute la fonction dyadique à sa gauche, qui dans ce cas est (c'est-à-dire, X⊤⍨Yest équivalente à Y⊤X).
  • est la fonction d'encodage. Il encode l'entier à sa droite dans la base donnée à sa gauche. Notez qu'en raison de l'opérateur de déplacement, les arguments droit et gauche sont commutés. La base est répétée pour le nombre de chiffres requis, d'où32/2 .
  • est une fonction niladique qui accepte les entrées utilisateur et les évalue.
  • +/réduit (replie) son bon argument en utilisant +. (Nous additionnons les 0 et les 1.)

2
Cela ne rompt-il pas la Built-in base conversion functionscontraint?
Gareth

Oups! Manqué celui-là.
Dillon Cower

Gah! Je pensais m'être donné une chance de me battre avec mon programme J! :-) Bon travail.
Gareth

@Gareth: Je ne m'en suis pas rendu compte avant d'avoir lu votre explication, mais ma réponse est à peu près identique à la vôtre! Je suppose que cela pourrait être attendu de APL et J. :)
Dillon Cower

11

Brainbool , 2

,.

L'interprétation la plus raisonnable, à mon avis (et ce que la plupart des réponses utilisent) du "plus grand nombre que votre langue est capable de gérer" est "le plus grand nombre que votre langue supporte nativement ". Brainbool est un dérivé de brainfuck qui utilise des bits plutôt que des octets, et prend l'entrée et la sortie en binaire ( 0et en 1caractères) plutôt qu'en codes de caractères. Le plus grand nombre soutenu nativement est donc 1, et le plus petit est 0, qui ont des poids de Hamming 1et 0respectivement.

Brainbool a été créé en 2010, selon Esolang.


9
Je savais que cela devait exister, mais il m'a fallu une heure pour trier les dérivés de Brainfuck sur Esolang pour trouver Brainbool.
lirtosiast

8

J, 13 caractères

(+ le nombre de chiffres du nombre)

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

Utilisation: remplacez le ndans le programme par le numéro à tester.

Exemples:

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

Il y a probablement un moyen de réorganiser cela pour que le nombre puisse être placé au début ou à la fin, mais c'est ma première entrée J et ma tête me fait mal maintenant.

Explication (principalement pour que je la comprenne à l'avenir)

i.32 - crée un tableau des nombres 1 à 32

2^ - transforme la liste en pouvoirs de deux 1 à 4294967296

n% - divise le numéro d'entrée par chaque élément de la liste

<. - arrondit tous les résultats de la division au nombre entier suivant

2|- identique %2à la plupart des langues - renvoie 0 si pair et 1 si impair

+/ - totalise les éléments de la liste (qui ne sont plus que des 1 ou des 0)


Je serai heureux de voter pour cela une fois qu'il lira depuis stdin (ou tout autre équivalent de J).
Steven Rumbalski

Le mieux que je puisse faire, je pense (peut-être, en fonction de la façon de le faire) est de déplacer l'entrée à la fin du programme. L'entrée standard n'est pas mentionnée dans la question?
Gareth

Je suis désolé de ne pas avoir spécifié le mode de saisie. Il serait injuste de modifier les règles maintenant, alors j'accepterai celle-ci. Je le mentionnerai la prochaine fois!
pimvdb

@pimvdb Pas de problème, ce n'était pas une plainte. Je pense qu'avec les programmes J, tout ce que vous pouvez faire est de définir un verbe qui fonctionne sur l'entrée qui lui est donnée. Je ne sais pas comment je réorganiserais cela pour le faire. Peut-être que JB ou l'un des autres experts J pourrait m'aider avec ça ...
Gareth

... et après avoir lu un peu plus, je vois maintenant que je me trompais complètement sur l'entrée standard.
Gareth

8

Brainfuck, 53 personnages

Il manquait une solution Brainfuck obligatoire, alors j'ai fait celle-ci:

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

Prend le nombre de la cellule 1 et met le résultat dans la cellule 6.

Version non inscrite et commentée:

[  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 caractères

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

note: Mon autre réponse utilise lambda et récursivité et celle-ci utilise une boucle while. Je pense qu'ils sont suffisamment différents pour justifier deux réponses.


6

Ruby, 38 caractères

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

Une autre solution utilisant ruby ​​et la même approche récursive que Steven.


5

GolfScript, 17 16 caractères

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

Modifier: la nouvelle version enregistre 1 caractère en utilisant l'opération de liste au lieu de plier (la version d'origine était ~{.2%\2/.}do]{+}*, la version à comptage direct:) ~0\{.2%@+\2/.}do;.


5

C, 45

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

Rien de vraiment spécial ici pour jouer au golf en C: type de retour implicite, type entier implicite pour les paramètres.


4

Python 2.6, 45 caractères

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

1
Peut être raccourci de deux caractères en utilisant defau lieu d'un lambda.
Konrad Rudolph

1
@KonradRudolph: En fait, vous perdez l'avantage une fois que vous avez inclus la déclaration de retour.
Steven Rumbalski

Oups, j'ai oublié ça. Stupide.
Konrad Rudolph

Vous n'en avez pas besoin print b(input()). Il est acceptable de renvoyer la valeur et de prendre "input" comme arguments pour les fonctions.
caird coinheringaahing

4

Perl, 45 43 36 caractères

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

Merci à Howard pour 45-> 43 et à User606723 pour 43-> 36.


Vous pouvez utiliser les $n=int($n/2)2 caractères plus courts.
Howard

Sommes-nous sûrs d'avoir besoin de l'int ()? $n=<>;while($n){$_+=$n%2;$n/=2}printCela continuera à boucler jusqu'à ce que $ n / 2 soit finalement assez proche de 0, mais nous en soucions-nous? ;)
user606723

@ user606723 Je viens de l'essayer et cela semble fonctionner parfaitement, au moins pour chaque cas jusqu'à 1000.
PhiNotPi

3

Perl, 30 caractères

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

Basé sur la solution de PhiNotPi , avec un peu de golf supplémentaire. Exécutez avec perl -M5.010pour activer la fonction Perl 5.10 say.


La $=variable spéciale fait-elle quelque chose de spécial dans votre programme, ou s'agit-il simplement d'une autre variable ordinaire?
PhiNotPi

2
@PhiNotPi: $=ne prend que des valeurs entières, donc son utilisation me fait économiser un an int.
Ilmari Karonen

L'argument de ligne de commande ne devrait-il pas faire partie du nombre de caractères?
Soham Chowdhury

@SohamChowdhury: Pas selon ce fil méta .
Ilmari Karonen

3

Lisp commun, 12 caractères

(en supposant un nom de variable de 1 caractère - c'est-à-dire: 11 + longueur de nombre)

Ce n'est pas une fonction de conversion de base, donc cela devrait fonctionner:

(logcount x)

Exemples:

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

(Utilisation de GNU CLISP.)


Eh bien, pas exactement ce que j'avais en tête de voir comme réponse :) Je ne pense pas pouvoir l'accepter. C'est fondamentalement juste un autre cas de cela .
pimvdb

3

C, 61 60 57 53 caractères

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

Le corps de la fonction ne comporte que 38 caractères. Edit : opérateur binaire supprimé Edit : mettre printfhors de la boucle comme suggéré dans les commentaires Edit : passer à la déclaration K&R; aussi, ce n'est plus spécifique au C99


Je vois au niveau du bit !!!
Joanis

Je suis désolé, mais l'opérateur AND compte également comme un opérateur au niveau du bit.
pimvdb

@ M.Joanis: duh, merci d'avoir remarqué. Fixé.
sam hocevar

1
Je pense que vous pourriez épargner quelques caractères si vous passiez à K&R C. Si vous êtes d'accord avec ça.
JB

Vous pouvez raccourcir cela de quatre caractères en déplaçant le printf hors de la boucle.
marinus

3

dc - 26 caractères

C'est assez long, principalement en raison du manque de constructions de boucles dans dc.

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

Continue d'ajouter le modulo 2 du nombre et de diviser le nombre par jusqu'à ce qu'il atteigne zéro. Peut gérer des entiers arbitrairement longs.

Exemple:

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

3

C, 66 caractères

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

Remarque: nécessite gcc ou un compilateur compatible gcc (par exemple ICC, clang).

Pour certains CPU, se __builtin_popcountcompile en une seule instruction (par exemple POPCNTsur x86).


Est-il exact que la mise __builtin_popcounten œuvre du comptage de 1s est elle-même effective ? Si c'est le cas, bien que ce ne soit pas strictement faux selon les règles, je ne pense vraiment pas que ce soit une entrée équitable.
pimvdb

Vous devriez probablement le stipuler dans la question si vous souhaitez interdire les entrées qui tirent parti des capacités intégrées d'un langage ou d'un compilateur donné.
Paul R

Ce n'est pas du C ++ légal car en C ++ vous ne pouvez pas omettre le type de retour sur main, ni l'utiliser printfsans include préalable.
celtschk

@celtschk: fair point - édité leC++
Paul R

2

JavaScript, 78 72 71 caractères

Je publierai ma solution initiale que j'ai trouvée avant de poster la question également. Il existe déjà une bien meilleure réponse JavaScript :)

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/

L'idée vient de certaines "cartes de lecture d'esprit" qui vous permettent d'obtenir le nombre que quelqu'un d'autre a en tête, en leur montrant des cartes et en leur laissant dire sur quelles cartes leur numéro est apparent.

Cela fonctionne parce que chaque nombre est une combinaison unique de 1s / 0s en binaire. Ma solution vérifie sur quelles "cartes" le nombre est apparent afin de déterminer combien1 il en a. Ce n'est tout simplement pas très efficace, cependant ...

J'ai trouvé ce document qui décrit la technique de lecture mentale.


2

Haskell (60 caractères)

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;

Cela suppose que $ndétient la valeur à tester.

PHP, 55 (solution alternative)

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

Encore une fois, cela suppose que $ndétient la valeur à tester. Ceci est une alternative car il utilise l'opérateur or pourfloor the input.

Les deux solutions fonctionnent et ne provoquent pas d'avis.


2

Ocaml, 45 caractères

Basé sur la solution de @Leah Xue. Trois espaces pourraient être supprimés et il est légèrement plus court (~ 3 caractères) pour utiliser la fonction au lieu de if-then-else.

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


1

Scala, 86 characters

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

Usage: scala O 56432



1

R, 53 caractères

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

Exemples:

> 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

Si la saisie du nombre ne fait pas partie du nombre de caractères, il s'agit de 43 caractères:

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

avec des cas de test

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

1

OCaml, 52 caractères

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

1

Schème

J'ai un peu poli les règles pour ajouter au défi. La fonction ne se soucie pas de la base du nombre car elle utilise sa propre échelle binaire. J'ai été inspiré par le fonctionnement de la conversion analogique-numérique. J'utilise simplement la récursion simple pour cela:

(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

La lecture d'un nombre en binaire ou l'impression du nombre à partir du binaire n'est-elle pas une «fonction de conversion de base intégrée», invalidant ainsi chaque réponse ci-dessus qui printest un entier? Si vous autorisez la lecture et l'impression d'un entier, comme presque toutes les réponses ci-dessus, alors je ferai des réclamations en utilisant une fonction intégréepopcount :

Haskell, 50

Un module a été popCountajouté au Data.Bitsmodule pour GHC v7.2.1 / v7.4.1 cet été (voir les tickets concernant le primop et la liaison ).

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

Je ne peux pas battre les scores Python et Perl ci-dessus en utilisant malheureusement leurs modules GMPYou GMP::Mpzpour GMP, bien que GMP offre également une fonction popcount .


1

JavaScript, 49 47 45 42 octets

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

Démo: http://jsfiddle.net/hcYdx/4/

Édition 1: supprimez qet utilisez ~~pour arrondir, enregistrez 2 caractères.

Edit 2: utilisez l' |0opérateur d'arrondi au lieu de ~~pour enregistrer les parenthèses (2 caractères).

Edit 3: simplify n>0 to n and combine with n=n/2|0 to make entire condition; now have wasted statement space :(


3
Isn't the |0 a bitwise operator?
Vilx-

Technically yes. But i'm using it purely to round to the nearest int, so I'm not getting any bit-wise benefit :)
mellamokb

Smells like bending the rules to me... but I'm not the judge.
Vilx-

Input 1 gives output 0.
Atreys

1
| is bitwise operator... it is disallowed. Time to do Math.round :-)
Jamie

1

Java 7, 36 bytes

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

Because of course this, of all things, is something that Java has a builtin for...


Doesn't this fit under "built-in base-conversion functions", which are banned?
FlipTack

@Flp.Tkc I'm not actually doing base-conversion. I have no idea how bitCount operates under the hood.
Poke

this seems like just using a bulitin to do the job, but ok...
FlipTack

@Flp.Tkc That's... exactly what it is? I'm even including all required libraries (there aren't any). This is demonstrating the strength of the language! related meta
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

TI-Basic is a tokenized language, all tokens but remainder( are one-byte, remainder is two


Welcome to the site!
James

1

PHP, 36 bytes

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

Assumes $n is the number to be tested, shows a PHP Notice for $o, and doesn't exactly work when $n is 0 (outputs nothing).

PHP, 53 bytes

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

Accepts command-line input, doesn't show a PHP Notice, and outputs correctly for 0.


Welcome to the site! :)
James
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.