编写一些语句,该语句将计算一个无符号的16位整数中的位数。
例如,如果输入为1337
,那么结果是6
因为1337
16位二进制数是0000010100111001
,所以包含六个1。
编写一些语句,该语句将计算一个无符号的16位整数中的位数。
例如,如果输入为1337
,那么结果是6
因为1337
16位二进制数是0000010100111001
,所以包含六个1。
Answers:
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
ax
和cx
与eax
和ecx
它改变到32位。两者的字节码相同。
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;
{}
。这是一个简单的任务,我不应该惊讶于有人已经提出了它。
for(n=0;x;x/=2)n+=x&1;
n->sum(digits(n,2))
这将创建一个接受单个参数的匿名函数n
。要使用它,请将其分配给like f=n->...
并调用like f(1337)
。
digits()
当使用2个参数调用该函数时,该函数以给定的基数返回输入数字的数组。因此digits(n, 2)
返回的二进制数字n
。取数组的总和,您有的二进制表示形式的个数n
。
count_ones
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()))
一样?
sum()
不能接受type的输入raw
,这是从返回的intToBits()
。
n.to_s(2).count'1'
n.to_s(2).count ?1
也可以,但是长度相同
感谢alephalpha使我想起了DigitCount
。
DigitCount[#,2,1]&
这是一个简单的递归函数,可以缩短一点。它只需要一点时间并再次运行:
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:
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,并使其递归缩短了很多!
0$11.>~n;
2,:?!^:2%:{+}-
该程序只是重复执行mod 2,减去并除以输入数字为零,然后输出mod 2s的总和。
用-v
标志测试,例如
py -3 fish.py ones.fish -v 1337
-v
标记版本仍然有效。)
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>
.
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.
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)));
<?=substr_count(decbin(1337),"1");
(34 bytes)
<?=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!
<?=substr_count(decbin($argv[1]),1);
(or $_GET[n]
; 36 bytes)
¢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.
¢¬x
.
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.
Works for byte
, short
, char
, and int
. Use as a lambda.
Integer::bitCount
Without using built-ins:
42 bytes
s->{int c=0;for(;s!=0;c++)s&=s-1;return c}
sum(dec2bin(s)-48)
Example:
octave:1> s=1337
s = 1337
octave:2> sum(dec2bin(s)-48)
ans = 6
"$([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)
-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
#(count(filter #{\1}(Long/toString % 2)))
Reading right to left, convert to a binary string, convert to a sequence of characters, filter on 1
s and count how many you have.
EDITED With help from Sieg
#(count(filter #{\1}(Integer/toString% 2)))
#(count(filter #{\1}(Integer/toString % 2)))
CompilerException java.lang.IllegalArgumentException: No matching method: toString_PERCENT_
Integer/toString
. It worked a second ago though.
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.
rem n 2
s 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.
⨭⟦ïⓑ
Converts input to binary, splits along chars, and gets sum of resulting array.