Compter le nombre de uns dans un entier 16 bits non signé

24

Écrivez une ou plusieurs instructions qui compteront le nombre d'un dans un entier de seize bits non signé.

Par exemple, si l'entrée est 1337, alors le résultat est 61337au fait qu'un nombre binaire de seize bits est 0000010100111001, qui en contient six.

ayane
la source
2
Astuce: tout comme certains chiffres d'un nombre sont congruents au nombre mod 9, certains bits sont égaux au nombre mod 1.
PyRulez
8
@PyRulez Tout nombre est zéro modulo 1.
Thomas
1
Bonjour, vous avez choisi une mauvaise réponse comme réponse acceptée (par défaut, la logique de départage du premier message).
Optimizer
4
@Thomas Je n'ai jamais dit que c'était un conseil utile.
PyRulez
2
Pourquoi cette question attire-t-elle des votes serrés APRÈS que la plupart des réponses aient été publiées? Électeurs proches, veuillez indiquer votre raison dans les commentaires. Si c'est l'acceptation de la réponse à 4 octets (très intelligente) d'es1024 qui n'est pas conforme aux failles standard (car elle utilise une fonction intégrée), veuillez indiquer que c'est la raison. Sinon, c'est quoi?
Level River St

Réponses:

37

80386 Code machine, 4 octets

F3 0F B8 C1

qui prend l'entier cxet sort le nombre ax, et est équivalent à:

popcnt ax, cx     ; F3 0F B8 C1

Et voici une solution de 11 10 octets n'utilisant pas POPCNT:

31 C0 D1 E9 10 E0 85 C9 75 F8

ce qui équivaut à:

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
la source
Est-ce en mode 32 bits ou 16 bits (réel ou protégé)?
FUZxxl
2
@FUZxxl L'assembly fourni est pour 16 bits, bien que le remplacement axet cxavec eaxet le ecxchange en 32 bits. Le bytecode est le même pour les deux.
es1024
1
@ es1024 Le code d'octet est le même s'il a été compilé en mode 16 bits et la version 32 bits en mode 32 bits.
Cole Johnson
2
La popcnt n'est-elle pas une fonction intégrée et tombe-t-elle ainsi dans les failles standard? Encore du crédit pour la deuxième solution.
Alchymist
5
Lorsque vous revendiquez la longueur du code machine , le titre ne doit-il pas être "80386 Machine Code", pas "80386 Assembler"?
Kevin Reid
14

Python 2, 17 octets

bin(s).count('1')

La fonction binintégrée renvoie l'entier converti en chaîne binaire. On compte ensuite les 1chiffres:

>>> s=1337
>>> bin(s)
'0b10100111001'
>>> bin(s).count('1')
6
Logic Knight
la source
11

J (5 caractères)

J n'a pas de types explicites. Cela fait la bonne chose pour tous les entiers.

+/@#:
  • +/ la somme
  • @ de
  • #: la représentation de base deux
FUZxxl
la source
11

C, 21

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

vous avez dit "écrire quelques instructions" (pas "une fonction") donc j'ai supposé que le nombre était fourni xet que le nombre de 1 était retourné n. Si je n'ai pas à l'initialiser, nje peux économiser 3 octets.

Il s'agit d'une adaptation de la célèbre expression x&x-1pour tester si quelque chose a une puissance de 2 (faux si c'est le cas, vrai si ce n'est pas le cas.)

Le voici en action sur le numéro 1337 de la question. Notez que la soustraction de 1 inverse le bit le moins significatif et tous les zéros vers la droite.

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

EDIT: pour être complet, voici l'algorithme naïf, qui est un octet de plus (et un peu plus lent.)

for(n=0;x;x/=2)n+=x&1;
Level River St
la source
1
@ edc65 alors en fin de compte, j'ai réinventé la roue. Au moins, j'ai économisé 2 octets en omettant le {}. C'est une tâche tellement simple que je ne serais pas surpris que quelqu'un l'ait déjà imaginé.
Level River St
"Première publication en 1960" , impressionnant.
mbomb007
Correction d'un algorithme naïf:for(n=0;x;x/=2)n+=x&1;
Helios
1
@nmxprime, l'OP demande un entier non signé. pour -7 = 11111111 11111111 11111111 11111001 sur mon compilateur 32 bits, j'obtiens 30 pour l'algorithme rapide, ce qui est correct. Pour l'algorithme naïf, il itère jusqu'à -7, -7 / 2 = -3, -3 / 2 = -1, -1 / 2 = 0. Cela donne une réponse incorrecte. Changer x / = 2 en x >> = 1 peut donner la bonne réponse sur certains compilateurs, mais C n'est pas défini si un 1 ou un 0 est décalé dans le bit vide pour >> sur des nombres négatifs. Les compilateurs qui décalent un 1 entreront dans une boucle infinie. La solution consiste à définir x comme un entier non signé. Alors x = -7 charge (1 << 32) -7 = 4294967289 dans x.
Level River St
5

Gelée , non compétitive

Cette réponse n'est pas concurrente, car la langue a été créée après la publication du défi.

2 octets:

BS

Jelly est un nouveau langage écrit par @Dennis, avec une syntaxe de type J.

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

Essayez-le ici .

lirtosiast
la source
4

Pyth, 4 octets

sjQ2

Le programme prend le numéro dont le poids de hamming se trouve sur STDIN.

isaacg
la source
4

Julia, 29 27 19 octets

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

Cela crée une fonction anonyme qui accepte un seul argument, n . Pour l'utiliser, affectez-le à quelque chose comme f=n->...et appelez-le comme f(1337).

La digits()fonction, lorsqu'elle est appelée avec 2 arguments, retourne un tableau des chiffres de l'entrée dans la base donnée. Renvoie donc digits(n, 2)les chiffres binaires de n. Prenez la somme du tableau et vous avez le nombre de ceux dans la représentation binaire de n.

Alex A.
la source
Cela peut être beaucoup plus court: Julia a une fonctioncount_ones
Andrew dit Reinstate Monica
@AndrewPiliser: Merci pour la suggestion, mais les fonctions intégrées qui accomplissent exactement la tâche sont considérées comme une faille standard et sont désapprouvées lorsqu'elles ne sont pas explicitement interdites.
Alex A.
3

CJam, 6 octets

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

Essayez-le en ligne ici

Optimiseur
la source
3

Joe , 4 octets

/+Ba

Il s'agit d'une fonction anonyme. Badonne la représentation binaire d'un nombre et la /+somme.

   (/+Ba)13
3
   (/+Ba)500
6
seequ
la source
3

R, 24 octets

sum(intToBits(scan())>0)

scan() lit l'entrée de stdin.

intToBits()prend un entier et retourne un vecteur de type rawcontenant les zéros et ceux de la représentation binaire de l'entrée.

intToBits(scan())>0renvoie un vecteur logique où chaque élément est TRUEsi l'élément vectoriel binaire correspondant est un 1 (puisque tous les éléments sont 0 ou 1 et 1> 0), sinon FALSE.

Dans R, vous pouvez additionner un vecteur logique pour obtenir le nombre d' TRUEéléments, donc la somme du vecteur de logique comme ci-dessus nous donne ce que nous voulons.

Notez que sum()ne peut pas gérer l' rawentrée directement, d'où la solution de contournement à l'aide de logiques.

Alex A.
la source
Ce ne serait pas sum(intToBits(scan()))pareil?
seequ
@Sieg: Malheureusement non car sum()ne peut pas prendre d'entrée de type raw, ce qui est ce qui est retourné intToBits().
Alex A.
C'est vraiment bizarre pour moi.
seequ
1
@Sieg: Oui, c'est bizarre pour moi aussi. Tant pis. Si chaque porc était parfait, nous n'aurions pas de hot-dogs.
Alex A.
Et c'est la métaphore la plus étrange de tous les temps.
seequ
3

Rubis, 18 octets

n.to_s(2).count'1'

GreyCat
la source
1
n.to_s(2).count ?1fonctionne également, mais est de la même longueur
Piccolo
Version 2019: n.digits (2) .sum / 15 octets
GB
3

Forth, 48 49 octets

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

Si une fonction réelle est nécessaire, la deuxième ligne devient

: c 0 swap c ;

et vous l'appelez par "1337 c". Les mots de contrôle relativement verbeux de Forth rendent cela difficile (en fait, ils en rendent beaucoup).

Modifier: ma version précédente ne gérait pas correctement les nombres négatifs.

Nagora
la source
3

Mathematica, 22 18 octets

Merci à alephalpha de me l'avoir rappelé DigitCount.

DigitCount[#,2,1]&
Martin Ender
la source
@alephalpha merci, mais DigitCount prend un autre paramètre :)
Martin Ender
3

ES6 (34 22 21 octets):

Il s'agit d'une simple fonction récursive qui peut être raccourcie un peu plus. Cela prend simplement un peu et s'exécute à nouveau:

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

Essayez-le sur http://www.es6fiddle.net/imt5ilve/ (vous en avez besoin à varcause de 'use strict';).

Je ne peux pas croire que j'ai battu des poissons !!!

Le vieux:

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

ES5 (39 octets):

Les deux fonctions peuvent être facilement adaptées à 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;
    }
}

Le vieux:

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

@ user1455003 m'a donné une très bonne idée, qui a "déclenché" la plus petite:

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

Je l'ai adapté à ES6 et l'ai rendu récursif pour raccourcir beaucoup!

Ismael Miguel
la source
1
Voici une petite fonction javascript «reguar». fonction B (n, x) {for (x = 0; n; n >> = 1) x + = n & 1; return x}
wolfhammer
@ user1455003 Merci BEAUCOUP ou votre suggestion! Je l'ai utilisé et l'ai adapté à ES6 et j'ai beaucoup raccourci. Merci!
Ismael Miguel
Vous êtes le bienvenu! J'aime ce que tu en as fait. Avec la récursivité, le javascript normal est tombé à 39! fonction B (n) {return n? (1 & n) + B (n >> 1): 0}
wolfhammer
@ user1455003 Si vous le souhaitez, vous pouvez modifier la partie ES5 et ajouter le nombre d'octets à la version golfée. (Je pense que vous gagnez de la réputation avec des modifications).
Ismael Miguel
@ user81655 WOW! Ça marche!!! Merci beaucoup! Je savais vraiment que cela pourrait être raccourci
Ismael Miguel
2

> <> (Poisson) , 24 octets + 2 = 26

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

Le programme ne fait que répéter le mod 2, soustrait et divise jusqu'à ce que le nombre d'entrée devienne zéro, puis imprime la somme des mod 2.

Test avec le -vdrapeau, par exemple

py -3 fish.py ones.fish -v 1337
Sp3000
la source
Pour un entier de 16 bits, l'entrée du point de code n'est probablement pas adéquate. (La -vversion drapeau fonctionne toujours.)
randomra
@randomra Damn, vous avez raison. Alors que l'entrée Unicode fonctionne, 16 bits n'est que quelques ordres de grandeur hors de portée ...
Sp3000
2

PHP (38 octets):

Cela utilise la même approche que ma réponse ES6

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

Il s'agit d'un code complet, il vous suffit de le mettre dans un fichier et d'y accéder via le navigateur, avec le paramètre n=<number>.

PHP <4,2 (32 octets):

C'est un peu plus court:

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

Cela ne fonctionne que de manière fiable sur PHP <4.2 car la directive a register_globalsété définie Offpar défaut de PHP4.2 à PHP5.4 (qui a été supprimée d'ici là).

Si vous créez un php.inifichier avec register_globals=On, cela fonctionnera.

Pour utiliser le code, accédez au fichier à l'aide d'un navigateur, avec POST ou GET.

Suggestion de @ViniciusMonteiro (38/45 octets):

Il a donné 2 très bonnes suggestions qui ont une utilisation très intéressante de la fonction array_sum:

38 octets:

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

45 octets:

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

C'est une très bonne idée et peut être raccourcie un peu plus, pour une longueur de 36 octets:

<?=array_sum(split(1,decbin(1337)));
Ismael Miguel
la source
2
Ou vous pouvez utiliser echo array_sum (str_split (decbin (1337))); et vous pouvez aussi utiliser echo array_sum (preg_split ('//', decbin (1337)));
Vinicius Monteiro
1
@ViniciusMonteiro Merci beaucoup pour votre suggestion. J'ai vraiment adoré! Je l'ai ajouté à la réponse.
Ismael Miguel
Gagnez quatre octets en utilisant <?=substr_count(decbin(1337),"1");(34 octets)
Cogicero
1
@Cogicero Et vous pouvez économiser encore plus en supprimant les guillemets: <?=substr_count(decbin(1337),1);. C'est un total de 32 octets. Étant donné qu'il s'agit d'un code suffisamment différent, ne voulez-vous pas le publier comme votre propre réponse? Je vais sûrement le voter!
Ismael Miguel
@Cogicero C´est seulement deux octets plus court si vous utilisez le paramétrage: <?=substr_count(decbin($argv[1]),1);(ou $_GET[n]; 36 octets)
Titus
2

C #, 45 octets

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

https://dotnetfiddle.net/kJDgOY

albertjan
la source
b-48est encore plus court, AFAIK
ThreeFx
Correct! :) Je vais mettre à jour.
albertjan
2

Japt, 3 octets (non compétitif)

¢¬x

Essayez-le ici.

Mama Fun Roll
la source
Mec, je ne vois jamais ces dates pour une raison quelconque.
Mama Fun Roll
1
Haha, Japt est le plus court: D BTW, ¢o1 lfonctionnerait aussi. Une autre approche intéressante est -¢¬r-0; ¢¬se divise en tableau de chiffres binaires, r-0réduit par soustraction, en commençant à 0 et -annule le résultat, le rendant positif.
ETHproductions
Depuis hier soir, vous pouvez maintenant utiliser ¢¬x.
ETHproductions
2

cire d'abeille ,31 27 octets

Réponse non concurrente. La cire d'abeille est plus récente que ce défi.

Cette solution utilise la façon de Brian Kherigan de compter les bits définis sur le site Web «Bit Twiddling Hacks».

il passe simplement par une boucle, incrémentant le nombre de bits, tout en itérant number=number&(number-1)jusqu'à number = 0. La solution ne passe par la boucle que si des bits sont définis.

Je pourrais raser 4 octets en réorganisant quelques instructions. Le code source et l'explication ont été mis à jour:

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

Explication:

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)

Clonez mon référentiel GitHub contenant l'interpréteur de cire d'abeille, les spécifications de langue et des exemples.

ML
la source
1

Java, 17 octets

Travaux pour byte, short, charet int. Utiliser comme lambda.

Integer::bitCount

Testez ici

Sans utiliser les intégrés:

42 octets

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

Testez ici

Le numéro un
la source
6
c'est une faille standard: les fonctions intégrées qui font exactement ce que vous voulez sont interdites.
FUZxxl
@FUZxxl L'OP n'a jamais interdit les échappatoires standard
Cole Johnson
6
@FUZxxl Bien que es1024 ait raison de dire que les échappatoires standard sont fermées par défaut, l'utilisation de fonctions intégrées n'est actuellement pas une échappatoire acceptée avec une répartition des votes de + 43 / -26.
Martin Ender
1

Clip , 6

2 façons:

cb2nx1

Il s'agit d'une traduction simple de l'exigence: le nombre de ceux dans la représentation de base-2 du nombre.

r+`b2n

Une autre méthode, qui prend la somme des chiffres de la représentation en base 2.

Ypnypn
la source
1

Octave, 18

sum(dec2bin(s)-48)

Exemple:

octave:1> s=1337
s =  1337
octave:2> sum(dec2bin(s)-48)
ans =  6
alephalpha
la source
1

GML (Game Maker Language), 21 octets

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

C # 39 octets

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

Perl, 21

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

PowerShell (51 octets)

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

Explication:
[convert]::ToString($s,2)produit une représentation de chaîne binaire à partir de $s.
[char[]]le jette comme un tableau de caractères et nous permet d'énumérer chaque caractère.
|%{"+$_"}ajoute à chaque caractère un signe +
"$()"appelle implicitement .ToString()la sous-expression résultante
|iexadditionne la chaîne canalisée (c.-à-d. "+1 +0 +1 +1 +0 +1 +0 +0" = 4)

Mathias R. Jessen
la source
Salut! Suivant la même logique que vous avez, pourquoi ne pas utiliser l' -joinopérateur en ligne et un implicite .ToString()pour atteindre 45 octets avec [char[]][convert]::ToString($s,2)-join'+'|iex... OU, comme une approche différente, utilisez l' -replaceopérateur en ligne pour atteindre 43 octets avec([convert]::ToString($s,2)-replace0).length
AdmBorkBork
1

Clojure, 42 octets

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

Lire de droite à gauche, convertir en une chaîne binaire, convertir en une séquence de caractères, filtrer sur 1s et compter combien vous en avez.

MODIFIÉ Avec l'aide de Sieg

Neil Masson
la source
42:#(count(filter #{\1}(Integer/toString% 2)))
seequ
Vous avez besoin d'un personnage de plus#(count(filter #{\1}(Integer/toString % 2)))
Neil Masson
Non, non. :)
seequ
Voici ce que j'ai eu quand je l'ai essayé:CompilerException java.lang.IllegalArgumentException: No matching method: toString_PERCENT_
Neil Masson
Je l'ai testé dans Try Clojure. Apparemment, la page ne reconnaît pas soudainement Integer/toString. Cela a fonctionné il y a une seconde cependant.
seequ
1

Haskell 42 caractères

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

déclare l' f :: Integer -> Integer
utilisation de la fonction à partir de l'interpréteur interactif f <number>ou ajoute la ligne main=print$f <number>à la fin du fichier.

HEGX64
la source
Vous pouvez économiser beaucoup d'octets en additionnant directement les rem n 2s au lieu d'en construire une liste et en utilisant à la divplace de quot: t 0=0 t n=t(div n 2)+rem n 2- fplus.
nimi
1

Matlab, 13 octets

de2bicrée un vecteur de zéros et de uns représentant le nombre binaire, et sumrenvoie simplement la somme de toutes les entrées.

sum(de2bi(n))
flawr
la source
1

𝔼𝕊𝕄𝕚𝕟, 4 caractères / 11 octets (non concurrentiel)

⨭⟦ïⓑ

Try it here (Firefox only).

Explication

Convertit l'entrée en binaire, se divise le long des caractères et obtient la somme du tableau résultant.

Mama Fun Roll
la source