เขียนคำสั่งที่จะนับจำนวนของคำในจำนวนเต็มสิบหกบิตที่ไม่ได้ลงนาม
ตัวอย่างเช่นหากอินพุตคือ1337
ผลลัพธ์จะเป็น6
เพราะ1337
เลขฐานสิบหกบิตเท่ากับ0000010100111001
ซึ่งประกอบด้วยหกรายการ
เขียนคำสั่งที่จะนับจำนวนของคำในจำนวนเต็มสิบหกบิตที่ไม่ได้ลงนาม
ตัวอย่างเช่นหากอินพุตคือ1337
ผลลัพธ์จะเป็น6
เพราะ1337
เลขฐานสิบหกบิตเท่ากับ0000010100111001
ซึ่งประกอบด้วยหกรายการ
คำตอบ:
F3 0F B8 C1
ซึ่งใช้จำนวนเต็มในcx
และเอาท์พุทนับในax
และเทียบเท่ากับ:
popcnt ax, cx ; F3 0F B8 C1
และนี่คือวิธีแก้ปัญหา11 10ไบต์ที่ไม่ได้ใช้ POPCNT:
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 บิต bytecode นั้นเหมือนกันสำหรับทั้งสอง
bin(s).count('1')
bin
ในตัวผลตอบแทนจำนวนเต็มแปลงเป็นสตริงไบนารี จากนั้นเราจะนับ1
ตัวเลข:
>>> s=1337
>>> bin(s)
'0b10100111001'
>>> bin(s).count('1')
6
J ไม่มีประเภทที่ชัดเจน นี่เป็นสิ่งที่ถูกต้องสำหรับจำนวนเต็มทั้งหมด
+/@#:
+/
ผลรวม@
ของ#:
การเป็นตัวแทนฐานสองfor(n=0;x;n++)x&=x-1;
คุณกล่าวว่า "เขียนคำสั่งบาง" (ไม่ใช่ "ฟังก์ชั่น") ดังนั้นฉันได้สันนิษฐานว่าจำนวนจะจำหน่ายในx
และจำนวน 1 n
จะถูกส่งกลับใน หากฉันไม่ต้องเริ่มต้นn
ฉันสามารถบันทึก 3 ไบต์
นี่คือการปรับตัวของนิพจน์ที่มีชื่อเสียงx&x-1
สำหรับการทดสอบว่าบางสิ่งเป็นพลังของ 2 (เท็จถ้าเป็นจริงถ้าไม่ใช่)
ที่นี่มีการใช้งานกับหมายเลข 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;
คำตอบนี้ไม่ใช่การแข่งขันเนื่องจากภาษาถูกสร้างขึ้นหลังจากการโพสต์ความท้าทาย
2 ไบต์:
BS
Jelly เป็นภาษาใหม่ที่เขียนโดย @Dennis พร้อมกับไวยากรณ์คล้าย J
implicit: function of command-line arguments
B Binary digits as list
S Sum
sjQ2
โปรแกรมใช้หมายเลขที่จะพบน้ำหนักการขัดขวางบน STDIN
n->sum(digits(n,2))
n
นี้จะสร้างฟังก์ชั่นที่ไม่ระบุชื่อที่ยอมรับอาร์กิวเมนต์เดียว ที่จะใช้มันกำหนดให้สิ่งที่ชอบและเรียกมันเหมือนf=n->...
f(1337)
digits()
ฟังก์ชั่นที่เรียกว่าเมื่อมี 2 ข้อโต้แย้งกลับอาร์เรย์ของตัวเลขของการป้อนข้อมูลในฐานที่กำหนด ดังนั้นจะส่งกลับตัวเลขไบนารีของdigits(n, 2)
ใช้ผลรวมของอาร์เรย์และคุณมีจำนวนคนที่อยู่ในฐานเป็นตัวแทนของn
n
count_ones
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";
/+Ba
นี่คือฟังก์ชั่นที่ไม่ระบุชื่อ Ba
ให้การแทนเลขฐานสองของจำนวนและ/+
ผลรวม
(/+Ba)13
3
(/+Ba)500
6
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()
ไม่สามารถใช้ใส่ของชนิดซึ่งเป็นสิ่งที่กลับมาจากraw
intToBits()
: c ?dup if dup 1- and recurse 1+ then ;
0 1337 c
หากจำเป็นต้องใช้ฟังก์ชันจริงบรรทัดที่สองจะกลายเป็น
: c 0 swap c ;
และคุณเรียกมันว่า "1337 c" คำที่ใช้ในการควบคุมอย่างละเอียดของ Forth ทำให้สิ่งนี้เป็นคำที่ยาก (อันที่จริงแล้ว
แก้ไข: รุ่นก่อนหน้าของฉันจัดการตัวเลขลบไม่ถูกต้อง
ขอขอบคุณที่ 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
รุ่นธงยังคงใช้งานได้)
สิ่งนี้ใช้ aproach เหมือนกับคำตอบ ES6ของฉัน
<?=count(split(1,decbin($_GET[n])))-1;
n=<number>
นี่คือรหัสเต็มคุณจะต้องใส่ไว้ในไฟล์และการเข้าถึงผ่านเบราว์เซอร์ที่มีพารามิเตอร์
สั้นกว่านี้เล็กน้อย:
<?=count(split(1,decbin($n)))-1;
สิ่งนี้ทำงานได้อย่างน่าเชื่อถือบน PHP <4.2 เพราะคำสั่งregister_globals
ถูกตั้งค่าเป็นค่าOff
เริ่มต้นจาก PHP4.2 ถึง PHP5.4 (ซึ่งถูกลบออกไปแล้ว)
หากคุณสร้างphp.ini
ไฟล์ด้วยregister_globals=On
สิ่งนี้จะทำงาน
ในการใช้รหัสให้เข้าถึงไฟล์โดยใช้เบราว์เซอร์ด้วย POST หรือ GET
เขาให้คำแนะนำที่ดีจริงๆ 2 ข้อซึ่งมีการใช้งานฟังก์ชั่นที่น่าสนใจมากarray_sum
:
38 ไบต์:
<?=array_sum(str_split(decbin(1337)));
45 ไบต์:
<?=array_sum(preg_split('//', decbin(1337)));
นี่เป็นแนวคิดที่ยอดเยี่ยมและสามารถย่อให้สั้นลงได้อีก 36 ไบต์:
<?=array_sum(split(1,decbin(1337)));
<?=substr_count(decbin(1337),"1");
(34 ไบต์)
<?=substr_count(decbin(1337),1);
และคุณสามารถประหยัดมากยิ่งขึ้นโดยการเอาคำพูด: นั่นคือทั้งหมด 32 ไบต์ เมื่อพิจารณาว่าเป็นรหัสที่แตกต่างกันคุณไม่ต้องการโพสต์เป็นคำตอบของคุณเองหรือ ฉันจะยกมันขึ้นไปเลย!
<?=substr_count(decbin($argv[1]),1);
(หรือ$_GET[n]
; 36 bytes)
¢o1 l
ก็ใช้ได้เช่นกัน อีกวิธีที่น่าสนใจคือ-¢¬r-0
; ¢¬
แยกออกเป็นอาเรย์ของเลขฐานสองr-0
ลดโดยการลบเริ่มต้นที่ 0 และ-
คัดค้านผลลัพธ์ทำให้เป็นบวก
¢¬x
ในฐานะของคืนที่ผ่านมาตอนนี้คุณสามารถใช้
คำตอบที่ไม่ใช่การแข่งขัน Beeswax ใหม่กว่าความท้าทายนี้
วิธีนี้ใช้วิธีนับจำนวนบิตของ Brian Kherigan จากเว็บไซต์“ Bit Twiddling Hacks”
มันเป็นเพียงแค่วิ่งผ่านห่วงที่เพิ่มขึ้นนับบิตในขณะที่การทำซ้ำผ่านจนกว่าnumber=number&(number-1)
number = 0
การแก้ปัญหาจะต้องผ่านการวนซ้ำบ่อยเท่าที่มีการตั้งค่าบิต
ฉันสามารถโกน 4 ไบต์ด้วยการจัดเรียงคำสั่งใหม่ ทั้งซอร์สโค้ดและคำอธิบายได้รับการอัพเดต:
pT_
>"p~0+M~p
d~0~@P@&<
{@<
คำอธิบาย:
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)
โคลนที่เก็บ GitHub ของฉันที่มีตัวแปลขี้ผึ้งข้อมูลจำเพาะภาษาและตัวอย่าง
การทำงานสำหรับbyte
, short
, และchar
int
ใช้เป็นแลมบ์ดา
Integer::bitCount
โดยไม่ต้องใช้บิวด์อิน:
42 ไบต์
s->{int c=0;for(;s!=0;c++)s&=s-1;return c}
2 วิธี:
cb2nx1
นี่คือการแปลข้อกำหนดที่ตรงไปตรงมา: การนับจำนวนในการแสดงเลขฐาน 2
r+`b2n
วิธีอื่นซึ่งใช้ผลรวมของตัวเลขของการแสดงฐาน 2
sum(dec2bin(s)-48)
ตัวอย่าง:
octave:1> s=1337
s = 1337
octave:2> sum(dec2bin(s)-48)
ans = 6
for(n=0;x;n/=2)n+=x&1
Convert.ToString(X,2).Count(C=>C=='1');
$r=grep$v&1<<$_,0..15
"$([char[]][convert]::ToString($s,2)|%{"+$_"})"|iex
คำอธิบาย: ผลิตแสดงสตริงไบนารีจาก
[convert]::ToString($s,2)
ปลดเปลื้องมันเป็นอาร์เรย์ถ่านและช่วยให้เราระบุถ่านแต่ละตัว เติมอักขระแต่ละตัวด้วยเครื่องหมาย + โดยนัยการเรียกในนิพจน์ย่อยผลลัพธ์จะรวมสตริง piped (เช่น "+1 +0 +1 +1 +1 +0 +1 +0 +0" = 4)$s
[char[]]
|%{"+$_"}
"$()"
.ToString()
|iex
-join
ดำเนินการอินไลน์และโดยปริยาย.ToString()
เพื่อให้ได้ 45 ไบต์ด้วย[char[]][convert]::ToString($s,2)-join'+'|iex
... หรือวิธีการต่าง ๆ ใช้-replace
ตัวดำเนินการแบบอินไลน์เพื่อให้ได้ 43 ไบต์ด้วย([convert]::ToString($s,2)-replace0).length
#(count(filter #{\1}(Long/toString % 2)))
อ่านจากขวาไปซ้าย, แปลงเป็นสตริงไบนารี, แปลงเป็นลำดับของอักขระ, กรองบน1
s และนับจำนวนคุณ
แก้ไข ด้วยความช่วยเหลือจาก Sieg
#(count(filter #{\1}(Integer/toString% 2)))
#(count(filter #{\1}(Integer/toString % 2)))
CompilerException java.lang.IllegalArgumentException: No matching method: toString_PERCENT_
Integer/toString
เห็นได้ชัดว่าหน้าก็ไม่รู้จัก มันทำงานได้ในวินาทีที่ผ่านมา
t 0=[]
t n=t(quot n 2)++[rem n 2]
f=sum.t
ประกาศการf :: Integer -> Integer
ใช้ฟังก์ชั่นจากล่ามแบบโต้ตอบเป็นf <number>
หรือเพิ่มบรรทัดmain=print$f <number>
ในตอนท้ายของไฟล์
rem n 2
s แทนการสร้างรายการและโดยใช้div
แทนquot
: t 0=0
t n=t(div n 2)+rem n 2
- ไม่f
อีกต่อไป
de2bi
สร้างเวกเตอร์ของศูนย์และคนที่เป็นตัวแทนของเลขฐานสองและsum
เพียงแค่ส่งกลับผลรวมของรายการทั้งหมด
sum(de2bi(n))
⨭⟦ïⓑ
แปลงอินพุตเป็นไบนารีแยกตามตัวอักษรและรับผลรวมของอาร์เรย์ที่ได้