计算无符号16位整数中的1


24

编写一些语句,该语句将计算一个无符号的16位整数中的位数。

例如,如果输入为1337,那么结果是6因为133716位二进制数是0000010100111001,所以包含六个1。


2
提示:正如在许多的一些数字是全等与数模9中,一些比特的等于号模1
PyRulez

8
@PyRulez任何数字都是零模1
托马斯

1
嗨,您选择了错误的答案作为接受答案(默认情况下,最早帖子的平局逻辑)。
Optimizer

4
@Thomas我从未说过这是一个有用的提示。
PyRulez

2
为什么在大多数答案发布后,这个问题就吸引了很多票?亲密的选民请在评论中指出您的理由。如果接受的是es1024的(非常聪明的)4字节答案,但不符合标准漏洞(因为它使用了内置方法),请说明这是原因。否则,那是什么?
级圣河

Answers:


37

80386机器代码,4个字节

F3 0F B8 C1

它采用in的整数cx并输出in 的计数ax,它等效于:

popcnt ax, cx     ; F3 0F B8 C1

这是一个不使用POPCNT 的11个10字节的解决方案:

31 C0 D1 E9 10 E0 85 C9 75 F8

等效于:

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

这是32位还是16位(实数或受保护)模式?
FUZxxl 2015年

2
组件提供@FUZxxl的是16位,但替换axcxeaxecx它改变到32位。两者的字节码相同。
es1024 2015年

1
@ es1024如果字节码是在16位模式下编译的,而32位版本是在32位模式下编译的,字节码相同。
科尔·约翰逊

2
popcnt是不是内置的,从而犯了标准漏洞吗?仍然归功于第二种解决方案。
Alchymist 2015年

5
声明机器代码的长度,标题不应该是“ 80386 Machine Code”,而不是“ 80386 Assembler”吗?
凯文·里德

14

Python 2,17个字节

bin(s).count('1')

bin内置返回整数转换为二进制字符串。然后,我们计算1数字:

>>> s=1337
>>> bin(s)
'0b10100111001'
>>> bin(s).count('1')
6

11

J(5个字符)

J没有显式类型。这对所有整数都是正确的。

+/@#:
  • +/ 总和
  • @
  • #: 基数二表示

11

C,21

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

您说过“写一些语句”(不是“函数”),所以我假设已提供,x返回了1 n。如果不需要初始化n,则可以节省3个字节。

这是对著名表达式的改编,x&x-1用于测试某物是否为2的幂(如果为2,则为false,否则为true)。

这是问题中编号为1337的数字的作用。请注意,相减1会将最低有效位1翻转,并将所有零向右翻转。

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

编辑:为了完整起见,这是朴素的算法,它长了一个字节(并且慢了很多)。

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


1
@ edc65结果证明,我重新发明了轮子。至少我省去了2个字节{}。这是一个简单的任务,我不应该惊讶于有人已经提出了它。
级圣河

“ 1960年首次出版”,令人印象深刻。
mbomb007'3

更正幼稚算法:for(n=0;x;x/=2)n+=x&1;
Helios 2015年

1
OP要求@nmxprime,要求提供无符号的int。对于我的32位编译器上的-7 = 11111111 11111111 11111111 11111001,我得到30的快速算法,这是正确的。对于朴素算法,它迭代-7,-7 / 2 = -3,-3 / 2 = -1,-1 / 2 = 0。那给出了错误的答案。在某些编译器上,将x / = 2更改为x >> = 1可能会给出正确的答案,但是对于在负数上>>,是否将1或0转换为空位,C仍未定义。那些将1移入的编译器将进入无限循环。解决方法是将x定义为无符号int。然后x = -7将(1 << 32)-7 = 4294967289加载到x中。
水平河圣

5

果冻,不竞争

该答案是非竞争性的,因为该语言是在发布挑战后创建的。

2个字节:

BS

Jelly是@Dennis编写的一种新语言,具有类似J的语法。

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

在这里尝试。


4

Pyth,4个字节

sjQ2

该程序采用在STDIN上可以找到汉明权重的数字。


4

朱莉娅29 27 19字节

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

这将创建一个接受单个参数的匿名函数n。要使用它,请将其分配给like f=n->...并调用like f(1337)

digits()当使用2个参数调用该函数时,该函数以给定的基数返回输入数字的数组。因此digits(n, 2)返回的二进制数字n。取数组的总和,您有的二进制表示形式的个数n


这可能会短很多:朱莉娅(Julia)有一个功能count_ones
安德鲁(Andrew)说,请恢复莫妮卡(Monica)2015年

@AndrewPiliser:感谢您的建议,但是可以完全完成任务的内置函数被视为标准漏洞,并且在未明确禁止时会被忽略。
Alex A.

3

CJam,6个字节

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

在这里在线尝试


3

,4个字节

/+Ba

这是一个匿名函数。Ba给出数字的二进制表示形式并将其/+求和。

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

3

R,24个字节

sum(intToBits(scan())>0)

scan() 从stdin读取输入。

intToBits() 接受一个整数并返回一个类型的向量 raw,该包含零和输入的二进制表示形式。

intToBits(scan())>0 返回一个逻辑向量,其中每个元素是 TRUE如果相应的二进制向量元素为1(因为所有元素均为0或1且1> 0),否则FALSE

在R中,您可以对逻辑向量求和以获得 TRUE元素,因此如上所述对逻辑向量求和就可以得到我们想要的。

请注意,sum()它不能raw直接处理输入,因此使用逻辑方法来解决。


会不会sum(intToBits(scan()))一样?
seequ

@Sieg:不幸的是,因为sum()不能接受type的输入raw,这是从返回的intToBits()
Alex A.

对我来说真的很奇怪。
seequ

1
@Sieg:是的,我也很奇怪。那好吧。如果每个猪排都很完美,我们就不会有热狗。
Alex A.

那是有史以来最奇怪的隐喻。
Seequ 2015年

3

Ruby,18个字节

n.to_s(2).count'1'


1
n.to_s(2).count ?1也可以,但是长度相同
Piccolo 2015年

2019版本:n.digits(2).sum / 15个字节
GB

3

48个 49字节

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

如果需要实际功能,则第二行变为

: c 0 swap c ;

然后用“ 1337 c”来称呼它 Forth相对冗长的控制词使它变得很难理解(实际上,它们使这些变得很难理解)。

编辑:我以前的版本不能正确处理负数。


3

Mathematica,22个 18字节

感谢alephalpha使我想起了DigitCount

DigitCount[#,2,1]&

@alephalpha谢谢,但是DigitCount需要另一个参数:)
Martin Ender

3

ES6(34 22 21个字节):

这是一个简单的递归函数,可以缩短一点。它只需要一点时间并再次运行:

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

http://www.es6fiddle.net/imt5ilve/上尝试(您需要使用的var原因'use strict';)。

我不敢相信我已经打败了鱼!!!

旧的:

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

ES5(39个字节):

两种功能均可轻松适用于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;
    }
}

旧的:

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

@ user1455003给了我一个非常好的主意,“触发”了最小的主意:

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

我将其调整为适用于ES6,并使其递归缩短了很多!


1
这是一个较小的“常规” JavaScript函数。函数B(n,x){for(x = 0; n; n >> = 1)x + = n&1; return x}
Wolfhammer

@ user1455003非常感谢您或您的建议!我已经使用过它并将其适应于ES6,并缩短了很多时间。谢谢!
Ismael Miguel

别客气!我喜欢你的所作所为。通过递归,常规javascript降至39!函数B(n){返回n?(1&n)+ B(n >> 1):0}
Wolfhammer

@ user1455003如果需要,您可以编辑ES5部分并将字节数添加到高尔夫球版本中。(我认为您通过编辑赢得声誉)。
Ismael Miguel

@ user81655哇!有用!!!非常感谢!我真的知道这可以做得更短
Ismael Miguel

2

> <>(Fish),24字节+ 2 = 26

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

该程序只是重复执行mod 2,减去并除以输入数字为零,然后输出mod 2s的总和。

-v标志测试,例如

py -3 fish.py ones.fish -v 1337

对于16位整数,代码点输入可能不足。(-v标记版本仍然有效。)
randomra 2015年

@randomra该死的,你是对的。尽管Unicode输入确实起作用,但16位只是超出范围几个数量级...
Sp3000 2015年

2

PHP(38字节):

This uses the same aproach as my ES6 answer

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

This is a full code, you only need to put it in a file and access it over the browser, with the parameter n=<number>.

PHP <4.2 (32 bytes):

This is a little shorter:

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

This only works reliably on PHP<4.2 because the directive register_globals was set to Off by default from PHP4.2 up to PHP5.4 (which was removed by then).

If you create a php.ini file with register_globals=On, this will work.

To use the code, access the file using a browser, with either POST or GET.

@ViniciusMonteiro's suggestion (38/45 bytes):

He gave 2 really good suggestions that have a very interesting use of the function array_sum:

38 bytes:

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

45 bytes:

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

This is a really great idea and can be shortened a bit more, to be 36 bytes long:

<?=array_sum(split(1,decbin(1337)));

2
Or you can use echo array_sum(str_split(decbin(1337))); and you can use too echo array_sum(preg_split('//', decbin(1337)));
Vinicius Monteiro

1
@ViniciusMonteiro Thank you a lot for your suggestion. I really loved it! I've added it to the answer.
Ismael Miguel

Gain four bytes using <?=substr_count(decbin(1337),"1"); (34 bytes)
Cogicero

1
@Cogicero And you can save even more by removing the quotes: <?=substr_count(decbin(1337),1);. That is a total of 32 bytes. Considering that it is a different-enough code, don't you want to post it as your own answer? I surelly will upvote it!
Ismael Miguel

@Cogicero It´s only two bytes shorter if you use parametrization: <?=substr_count(decbin($argv[1]),1); (or $_GET[n]; 36 bytes)
Titus


2

Japt, 3 bytes (non-competitive)

¢¬x

Try it here.


Man, I never see those dates for some reason.
Mama Fun Roll

1
Haha, Japt is shortest :D BTW, ¢o1 l would work as well. Another interesting approach is -¢¬r-0; ¢¬ splits into array of binary digits, r-0 reduces by subtraction, starting at 0, and - negates the result, making it positive.
ETHproductions

As of last night, you can now use ¢¬x.
ETHproductions

2

beeswax, 31 27 bytes

Non-competing answer. Beeswax is newer than this challenge.

This solution uses Brian Kherigan’s way of counting set bits from the “Bit Twiddling Hacks” website.

it just runs through a loop, incrementing the bit count, while iterating through number=number&(number-1) until number = 0. The solution only goes through the loop as often as there are bits set.

I could shave off 4 bytes by rearranging a few instructions. Both source code and explanation got updated:

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

Explanation:

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 my GitHub repository containing the beeswax interpreter, language spec and examples.


1

Java, 17 bytes

Works for byte, short, char, and int. Use as a lambda.

Integer::bitCount

Test here

Without using built-ins:

42 bytes

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

Test here


6
this is a standard loophole: builtin functions that do exactly what you want are forbidden.
FUZxxl

@FUZxxl The OP never forbade standard loopholes
Cole Johnson


6
@FUZxxl While es1024 is right that the standard loopholes are closed by default, using built-in functions is currently not an accepted loophole at a vote breakdown of +43/-26.
Martin Ender

1

Clip, 6

2 ways:

cb2nx1

This is a straightforward translation of the requirement: the count of ones in the base-2 representation of number.

r+`b2n

Another method, which takes the sum of the digits of the base-2 representation.


1

Octave, 18

sum(dec2bin(s)-48)

Example:

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

1

GML (Game Maker Language), 21 bytes

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



1

PowerShell (51 bytes)

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

Explanation:
[convert]::ToString($s,2) produces a binary string representation from $s.
[char[]] casts it as a char array and allows us to enumerate each char.
|%{"+$_"} prepends each character with a + sign
"$()" implicitly calls .ToString() on the resulting sub expression
|iex sums the piped string (ie. "+1 +0 +1 +1 +0 +1 +0 +0" = 4)


Hiya! Following the same logic you have, why not use the inline -join operator and an implicit .ToString() to achieve 45 bytes with [char[]][convert]::ToString($s,2)-join'+'|iex ... OR, as a different approach use inline -replace operator to achieve 43 bytes with ([convert]::ToString($s,2)-replace0).length
AdmBorkBork

1

Clojure, 42 bytes

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

Reading right to left, convert to a binary string, convert to a sequence of characters, filter on 1s and count how many you have.

EDITED With help from Sieg


42: #(count(filter #{\1}(Integer/toString% 2)))
seequ

You need one more character #(count(filter #{\1}(Integer/toString % 2)))
Neil Masson

No you don't. :)
seequ

This is what I got when I tried it: CompilerException java.lang.IllegalArgumentException: No matching method: toString_PERCENT_
Neil Masson

I tested it in Try Clojure. Apparently the page suddenly doesn't recognize Integer/toString. It worked a second ago though.
seequ

1

Haskell 42 chars

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

declares the function f :: Integer -> Integer
use from the interactive interpreter as f <number> or add the line main=print$f <number> to the end of the file.


You can save a lot of bytes by directly summing the rem n 2s instead of building a list of it and by using div instead of quot: t 0=0 t n=t(div n 2)+rem n 2 - no f anymore.
nimi

1

Matlab, 13 bytes

de2bi creates a vector of zeros and ones representing the binary number, and sum just returns the sum of all the entries.

sum(de2bi(n))

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.