Đếm số lượng trong số nguyên 16 bit không dấu


24

Viết một số câu lệnh sẽ đếm số lượng câu lệnh trong một số nguyên mười sáu bit không dấu.

Ví dụ, nếu đầu vào là 1337, thì kết quả là 6bởi vì 1337số nhị phân mười sáu bit là 0000010100111001, chứa sáu số.


2
Mẹo: giống như một số chữ số trong một số phù hợp với số mod 9, một số bit bằng với số mod 1.
PyRulez 17/03/2015

8
@PyRulez Bất kỳ số nào là số 0 modulo 1.
Thomas

1
Xin chào, bạn đã chọn một câu trả lời sai là câu trả lời được chấp nhận (theo mặc định logic ngắt kết nối của bài đăng sớm nhất).
Tối ưu hóa

4
@Thomas Tôi không bao giờ nói đó là một mẹo hữu ích.
PyRulez 18/03/2015

2
Tại sao câu hỏi này thu hút phiếu bầu gần SAU hầu hết các câu trả lời đã được đăng? Cử tri đóng xin vui lòng cho biết lý do của bạn trong các ý kiến. Nếu đó là sự chấp nhận câu trả lời 4 byte của es1024 (rất thông minh) không tuân thủ các sơ hở tiêu chuẩn (vì nó sử dụng nội dung), vui lòng cho biết đây là lý do. Nếu không, nó là gì?
Cấp sông St

Câu trả lời:


37

Mã máy 80386, 4 byte

F3 0F B8 C1

trong đó lấy số nguyên trong cxvà xuất ra số đếm axvà tương đương với:

popcnt ax, cx     ; F3 0F B8 C1

Và đây là một giải pháp 11 10 byte không sử dụng POPCNT:

31 C0 D1 E9 10 E0 85 C9 75 F8

tương đương với:

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

Đây là ở chế độ 32 bit hay 16 bit (thực hay được bảo vệ)?
FUZxxl 17/03/2015

2
@FUZxxl Việc lắp ráp được cung cấp là 16 bit, mặc dù thay thế axcxbằng eaxecxthay đổi nó thành 32 bit. Mã byte là giống nhau cho một trong hai.
es1024 17/03/2015

1
@ es1024 Mã byte giống nhau nếu mã này được biên dịch ở chế độ 16 bit và phiên bản 32 bit ở chế độ 32 bit.
Cole Johnson

2
Không phải là một bản dựng sẵn và do đó rơi vào lỗi sơ hở tiêu chuẩn? Vẫn tín dụng cho giải pháp thứ hai mặc dù.
17/03/2015

5
Khi bạn yêu cầu độ dài của mã máy , không nên đặt tiêu đề là "Mã máy 80386", không phải là "Trình biên dịch 80386"?
Kevin Reid

14

Python 2, 17 byte

bin(s).count('1')

Các binbuilt-in trả về số nguyên chuyển thành một chuỗi nhị phân. Sau đó chúng tôi đếm các 1chữ số:

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

11

J (5 ký tự)

J không có loại rõ ràng. Điều này làm điều đúng cho tất cả các số nguyên.

+/@#:
  • +/ Tổng
  • @ của
  • #: đại diện hai cơ sở

11

C, 21

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

bạn đã nói "viết một số câu lệnh" (không phải "một hàm") vì vậy tôi đã giả sử số được cung cấp xvà số 1 được trả về n. Nếu tôi không phải khởi tạo, ntôi có thể tiết kiệm 3 byte.

Đây là bản chuyển thể của biểu thức nổi tiếng x&x-1để kiểm tra nếu thứ gì đó có sức mạnh bằng 2 (sai nếu đúng, đúng nếu không.)

Đây là hành động trên số 1337 từ câu hỏi. Lưu ý rằng trừ đi 1 lần lật ít nhất 1 bit và tất cả các số 0 ở bên phải.

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

EDIT: để hoàn thiện, đây là thuật toán ngây thơ, dài hơn một byte (và chậm hơn một chút.)

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


1
@ edc65 vì vậy khi nó bật ra, tôi đã phát minh lại bánh xe. Ít nhất tôi đã lưu 2 byte bằng cách bỏ qua {}. Đó là một nhiệm vụ đơn giản như vậy tôi không nên ngạc nhiên khi ai đó đã nghĩ ra nó.
Cấp sông St

"Xuất bản lần đầu năm 1960" , ấn tượng.
mbomb007

Sửa thuật toán ngây thơ:for(n=0;x;x/=2)n+=x&1;
Helios

1
@nmxprime OP yêu cầu int unsign. cho -7 = 11111111 11111111 11111111 11111001 trên trình biên dịch 32 bit của tôi, tôi nhận được 30 cho thuật toán nhanh, điều này là chính xác. Đối với thuật toán ngây thơ, nó lặp qua -7, -7 / 2 = -3, -3 / 2 = -1, -1 / 2 = 0. Điều đó cho một câu trả lời không chính xác. Thay đổi x / = 2 thành x >> = 1 có thể đưa ra câu trả lời chính xác trên một số trình biên dịch, nhưng C không xác định được liệu 1 hay 0 được chuyển sang bit trống cho >> trên các số âm. Những trình biên dịch dịch chuyển 1 in sẽ đi vào một vòng lặp vô hạn. Cách giải quyết là định nghĩa x là một số nguyên không dấu. Sau đó x = -7 tải (1 << 32) -7 = 4294967289 vào x.
Cấp sông St

5

Thạch , không cạnh tranh

Câu trả lời này là không cạnh tranh, vì ngôn ngữ được tạo ra sau khi thử thách được đăng.

2 byte:

BS

Jelly là một ngôn ngữ mới được viết bởi @Dennis, với cú pháp giống như J.

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

Hãy thử nó ở đây .


4

Bình thường, 4 byte

sjQ2

Chương trình lấy số có trọng lượng hamming được tìm thấy trên STDIN.


4

Julia, 29 27 19 byte

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

Điều này tạo ra một hàm ẩn danh chấp nhận một đối số duy nhất , n. Để sử dụng nó, gán nó cho một cái gì đó như f=n->...và gọi nó như thế nào f(1337).

Các digits()chức năng, khi được gọi với 2 đối số, trả về một mảng của các chữ số của đầu vào trong cơ sở nhất định. Vì vậy, digits(n, 2)trả về các chữ số nhị phân của n. Lấy tổng của mảng và bạn có số lượng trong biểu diễn nhị phân của n.


Điều này có thể ngắn hơn rất nhiều: Julia có một chức năngcount_ones
Andrew nói Phục hồi Monica

@AndrewPiliser: Cảm ơn bạn đã gợi ý, nhưng các chức năng tích hợp hoàn thành chính xác nhiệm vụ được coi là một lỗ hổng tiêu chuẩn và được tán thành khi không được phép rõ ràng.
Alex A.


3

Joe , 4 byte

/+Ba

Đây là một chức năng ẩn danh. Bađưa ra biểu diễn nhị phân của một số và tính /+tổng của nó.

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

3

R, 24 byte

sum(intToBits(scan())>0)

scan() đọc đầu vào từ stdin.

intToBits()lấy một số nguyên và trả về một vectơ loại rawchứa các số 0 và một số của biểu diễn nhị phân của đầu vào.

intToBits(scan())>0trả về một vectơ logic trong đó mỗi phần tử là TRUEnếu phần tử vectơ nhị phân tương ứng là 1 (vì tất cả các phần tử là 0 hoặc 1 và 1> 0), nếu không FALSE.

Trong R, bạn có thể tổng hợp một vectơ logic để có được số lượng TRUEphần tử, do đó, việc tổng hợp vectơ logic như trên sẽ cho chúng ta những gì chúng ta muốn.

Lưu ý rằng sum()không thể xử lý rawđầu vào trực tiếp, do đó cách giải quyết bằng cách sử dụng logic.


Sẽ không sum(intToBits(scan()))giống nhau?
xem

@Sieg: Thật không may vì sum()không thể lấy đầu vào của loại raw, đó là những gì được trả về intToBits().
Alex A.

Điều đó thực sự kỳ lạ với tôi.
Seequ 18/03/2015

1
@Sieg: Vâng, nó cũng kỳ lạ với tôi. Ồ tốt Nếu mọi con lợn đều hoàn hảo, chúng ta sẽ không có hotdogs.
Alex A.

Và đó là phép ẩn dụ kỳ lạ nhất từng có.
Seequ 18/03/2015

3

Ruby, 18 byte

n.to_s(2).count'1'


1
n.to_s(2).count ?1cũng hoạt động, nhưng có cùng độ dài
Piccolo

Phiên bản 2019: n.digits (2) .sum / 15 byte
GB

3

Forth, 48 49 byte

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

Nếu một chức năng thực sự là cần thiết thì dòng thứ hai trở thành

: c 0 swap c ;

và bạn gọi nó bằng "1337 c". Các từ kiểm soát tương đối dài dòng của Forth làm cho điều này trở nên khó khăn (thực ra, chúng tạo ra rất nhiều từ khó khăn này).

Chỉnh sửa: Phiên bản trước của tôi không xử lý chính xác các số âm.


3

Toán học, 22 18 byte

Cảm ơn alephalpha đã nhắc nhở tôi DigitCount.

DigitCount[#,2,1]&

@alephalpha cảm ơn, nhưng DigitCount có một tham số khác :)
Martin Ender

3

ES6 (34 22 21 byte):

Đây là một hàm đệ quy đơn giản có thể rút ngắn thêm một chút. Nó chỉ đơn giản là mất một chút và tự chạy lại:

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

Hãy thử nó trên http://www.es6fiddle.net/imt5ilve/ (bạn cần var'use strict';).

Tôi không thể tin rằng tôi đã đánh cá !!!

Cái cũ:

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

ES5 (39 byte):

Cả hai chức năng có thể dễ dàng thích ứng với 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;
    }
}

Người già:

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

@ user1455003 đã cho tôi một ý tưởng thực sự tuyệt vời, đó là 'kích hoạt' ý tưởng nhỏ nhất:

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

Tôi đã điều chỉnh nó thành ES6 và làm cho nó đệ quy để rút ngắn rất nhiều!


1
Đây là một chức năng javascript 'reguar' nhỏ hơn. hàm B (n, x) {for (x = 0; n; n >> = 1) x + = n & 1; return x}
wolfhammer 18/03/2015

@ user1455003 Cảm ơn bạn rất nhiều hoặc đề nghị của bạn! Tôi đã sử dụng nó và điều chỉnh nó thành ES6 và rút ngắn rất nhiều. Cảm ơn bạn!
Ismael Miguel

Chào mừng bạn! Tôi thích những gì bạn đã làm với nó. Với đệ quy, javascript thông thường giảm xuống còn 39! hàm B (n) {return n? (1 & n) + B (n >> 1): 0}
wolfhammer

@ user1455003 Nếu bạn muốn, bạn có thể chỉnh sửa phần ES5 và thêm số byte vào phiên bản được đánh gôn. (Tôi nghĩ bạn giành được danh tiếng với các chỉnh sửa).
Ismael Miguel

@ user81655 WOW! Nó hoạt động !!! Cảm ơn bạn rất nhiều! Tôi thực sự biết điều này có thể được thực hiện ngắn hơn
Ismael Miguel

2

> <> (Cá) , 24 byte + 2 = 26

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

Chương trình chỉ thực hiện lặp lại mod 2, trừ và chia cho đến khi số đầu vào bằng 0, sau đó in tổng của mod 2s.

Kiểm tra với -vcờ, ví dụ

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

Đối với số nguyên 16 bit, đầu vào codepoint có thể không đủ. ( -vPhiên bản cờ vẫn hoạt động.)
Randomra 17/03/2015

@randomra Chết tiệt, bạn nói đúng. Trong khi đầu vào Unicode không hoạt động, 16 bit chỉ là một vài bậc có độ lớn ngoài phạm vi ...
Sp3000 17/03/2015

2

PHP (38 byte):

Điều này sử dụng cùng một aproach như câu trả lời ES6 của tôi

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

Đây là một mã đầy đủ, bạn chỉ cần đặt nó vào một tệp và truy cập nó trên trình duyệt, với tham số n=<number> .

PHP <4.2 (32 byte):

Cái này ngắn hơn một chút:

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

Điều này chỉ hoạt động đáng tin cậy trên PHP <4.2 vì lệnh register_globalsđược đặt thànhOff mặc định từ PHP4.2 lên đến PHP5.4 (đã bị xóa sau đó).

Nếu bạn tạo một php.initập tin với register_globals=On, điều này sẽ làm việc.

Để sử dụng mã, truy cập tệp bằng trình duyệt, bằng POST hoặc GET.

@ViniciusMonteiro 's gợi ý (38/45 byte):

Ông đã đưa ra 2 gợi ý thực sự tốt có chức năng sử dụng rất thú vị array_sum:

38 byte:

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

45 byte:

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

Đây là một ý tưởng thực sự tuyệt vời và có thể rút ngắn thêm một chút, dài 36 byte:

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

2
Hoặc bạn có thể sử dụng echo Array_sum (str_split (decbin (1337))); và bạn có thể sử dụng quá echo Array_sum (preg_split ('//', decbin (1337)));
Vinicius Monteiro

1
@ViniciusMonteiro Cảm ơn bạn rất nhiều vì lời đề nghị của bạn. Tôi thực sự yêu thích nó! Tôi đã thêm nó vào câu trả lời.
Ismael Miguel

Nhận bốn byte bằng cách sử dụng <?=substr_count(decbin(1337),"1");(34 byte)
Cogicero

1
@Cogicero Và bạn có thể tiết kiệm nhiều hơn bằng cách xóa dấu ngoặc kép : <?=substr_count(decbin(1337),1);. Đó là tổng cộng 32 byte. Xem xét rằng đó là một mã đủ khác, bạn không muốn đăng nó dưới dạng câu trả lời của riêng mình? Tôi surelly sẽ upvote nó!
Ismael Miguel

@Cogicero Nó chỉ ngắn hơn hai byte nếu bạn sử dụng tham số: <?=substr_count(decbin($argv[1]),1);(hoặc $_GET[n]; 36 byte)
Tít


2

Japt, 3 byte (không cạnh tranh)

¢¬x

Hãy thử nó ở đây.


Man, tôi không bao giờ thấy những ngày đó vì một số lý do.
Mama Fun Roll

1
Haha, Japt là ngắn nhất: D BTW, ¢o1 lcũng sẽ hoạt động tốt. Một cách tiếp cận thú vị khác là -¢¬r-0; ¢¬chia thành mảng các chữ số nhị phân, r-0giảm bằng phép trừ, bắt đầu từ 0 và -phủ định kết quả, làm cho nó dương.
Sản phẩm ETH

Tính đến tối qua, bây giờ bạn có thể sử dụng ¢¬x.
Sản xuất ETH

2

sáp ong ,31 27 byte

Câu trả lời không cạnh tranh. Sáp ong mới hơn thử thách này.

Giải pháp này sử dụng cách đếm các bit set của Brian Kherigan từ trang web của Bit Bit Twiddling Hacks.

nó chỉ chạy qua một vòng lặp, tăng số bit, trong khi lặp qua number=number&(number-1)cho đến khi number = 0. Giải pháp chỉ đi qua vòng lặp thường xuyên như có các bit được đặt.

Tôi có thể tắt 4 byte bằng cách sắp xếp lại một vài hướng dẫn. Cả mã nguồn và giải thích đã được cập nhật:

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

Giải trình:

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)

Sao chép kho GitHub của tôi có chứa trình thông dịch sáp ong, thông số ngôn ngữ và ví dụ.


1

Java, 17 byte

Làm việc cho byte, short, char, và int. Sử dụng như một lambda.

Integer::bitCount

Kiểm tra tại đây

Không sử dụng tích hợp:

42 byte

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

Kiểm tra tại đây


6
đây là một lỗ hổng tiêu chuẩn: các hàm dựng sẵn thực hiện chính xác những gì bạn muốn bị cấm.
FUZxxl 17/03/2015

@FUZxxl OP không bao giờ cấm các sơ hở tiêu chuẩn
Cole Johnson


6
@FUZxxl Mặc dù es1024 đúng là các lỗ hổng tiêu chuẩn được đóng theo mặc định, sử dụng các hàm tích hợp hiện tại không phải là lỗ hổng được chấp nhận khi phân tích phiếu bầu + 43 / -26.
Martin Ender

1

Clip , 6

2 cách:

cb2nx1

Đây là một bản dịch đơn giản của yêu cầu: số lượng trong số đại diện cơ sở-2 của số.

r+`b2n

Một phương thức khác, lấy tổng các chữ số của biểu diễn cơ số 2.


1

Tháng mười, 18

sum(dec2bin(s)-48)

Thí dụ:

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

1

GML (Ngôn ngữ nhà sản xuất trò chơi), 21 byte

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



1

PowerShell (51 byte)

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

Giải thích:
[convert]::ToString($s,2)tạo ra một đại diện chuỗi nhị phân từ $s.
[char[]]biến nó thành một mảng char và cho phép chúng ta liệt kê từng char.
|%{"+$_"}chuẩn bị cho mỗi ký tự bằng dấu +
"$()"gọi ngầm .ToString()vào biểu thức con kết quả tính
|iextổng chuỗi (ví dụ: "+1 +0 +1 +1 +0 +1 +0 +0" = 4)


Hiya! Theo cùng một logic bạn có, tại sao không sử dụng -jointoán tử nội tuyến và ẩn .ToString()để đạt được 45 byte với [char[]][convert]::ToString($s,2)-join'+'|iex... HOẶC, như một cách tiếp cận khác sử dụng -replacetoán tử nội tuyến để đạt được 43 byte với([convert]::ToString($s,2)-replace0).length
admBorkBork

1

Clojure, 42 byte

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

Đọc từ phải sang trái, chuyển đổi thành chuỗi nhị phân, chuyển đổi thành một chuỗi các ký tự, lọc trên 1s và đếm số lượng bạn có.

EDITED với sự giúp đỡ từ Sieg


42:#(count(filter #{\1}(Integer/toString% 2)))
Seequ 18/03/2015

Bạn cần thêm một nhân vật#(count(filter #{\1}(Integer/toString % 2)))
Neil Masson

Không, bạn không có. :)
xem 18/03/2015

Đây là những gì tôi nhận được khi dùng thử:CompilerException java.lang.IllegalArgumentException: No matching method: toString_PERCENT_
Neil Masson

Tôi đã thử nó trong Thử Clojure. Rõ ràng trang đột nhiên không nhận ra Integer/toString. Nó đã làm việc một giây trước mặc dù.
Seequ 18/03/2015

1

Haskell 42 ký tự

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

khai báo hàm f :: Integer -> Integer
sử dụng từ trình thông dịch tương tác dưới dạng f <number>hoặc thêm dòng main=print$f <number>vào cuối tệp.


Bạn có thể tiết kiệm rất nhiều byte bằng cách trực tiếp tóm tắt rem n 2s thay vì xây dựng danh sách của nó và bằng cách sử dụng divthay vì quot: t 0=0 t n=t(div n 2)+rem n 2- không fcòn nữa.
nimi

1

Matlab, 13 byte

de2bitạo một vectơ số không và số đại diện cho số nhị phân và sumchỉ trả về tổng của tất cả các mục.

sum(de2bi(n))

1

, 4 ký tự / 11 byte (không cạnh tranh)

⨭⟦ïⓑ

Try it here (Firefox only).

Giải trình

Chuyển đổi đầu vào thành nhị phân, phân chia dọc theo ký tự và lấy tổng của mảng kết quả.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.