In số lượng trong một số nhị phân mà không cần sử dụng toán tử bitwise


14

Sự miêu tả

Cho một số, in số lượng 1s có trong biểu diễn nhị phân.

Đầu vào

Một số >= 0trong cơ sở 10 không vượt quá số cao nhất mà ngôn ngữ của bạn có thể xử lý.

Đầu ra

Số lượng 1s trong biểu diễn nhị phân.

Điều kiện chiến thắng

Mã ngắn nhất sẽ thắng.

Không được phép

  • Toán tử bitwise. Các toán tử khác, như phép cộng và phép nhân, được cho phép.
  • Tích hợp chức năng chuyển đổi cơ sở.

Ví dụ

Input:     Ouput:

56432      8


Input:     Output:

45781254   11


Input:     Output:

0          0

Các chức năng có được phép không? Tôi muốn tạo một giải pháp Java, nhưng viết mã đầy đủ thì quá tẻ nhạt ...: /
HyperNeutrino

1
Tôi đoán tôi sẽ không sử dụng Wise cho thử thách này ... :)
MildlyMilquetoast

Câu trả lời:


16

APL, 9 12 ký tự

+/2|⌊⎕÷2*⍳32

Điều này giả định rằng trình thông dịch sử dụng các số nguyên 32 bit và ⎕IOđược đặt thành 0 (có nghĩa là đơn âm bắt đầu bằng 0, thay vì 1). Tôi đã sử dụng phiên bản 32-bit của Dyalog APL .

Giải thích, từ phải sang trái:

  • ⍳32tạo ra một vectơ của các 32số nguyên đầu tiên (như đã giải thích trước đó, vì ⎕IOlà 0, vectơ này bắt đầu bằng 0).
  • *là hàm năng lượng. Trong trường hợp này, nó tạo ra 2sức mạnh của từng phần tử của vectơ được cung cấp như là đối số đúng của nó.
  • ÷là hàm chia cho. Nó cho chúng ta (đánh giá đầu vào của người dùng) chia cho mỗi phần tử của vectơ bên phải (mỗi lũy thừa của hai).
  • tầng mỗi phần tử của đối số bên phải của nó.
  • 2|cho chúng ta phần còn lại của mỗi phần tử bên phải chia cho 2.
  • /giảm (gập) đối số bên phải của nó bằng cách sử dụng hàm bên trái , +.

Không còn 9 ký tự nữa. :

Phiên bản cũ, phá vỡ quy tắc:

+/⎕⊤⍨32/2

Giải thích, từ phải sang trái:

  • 32/2: Nhân rộng 2, 32lần.
  • đi lại hàm dyadic ở bên trái của nó, trong trường hợp này là (nghĩa X⊤⍨Ylà tương đương với Y⊤X).
  • là hàm mã hóa. Nó mã hóa số nguyên ở bên phải của nó trong cơ sở cho bên trái của nó. Lưu ý rằng, do toán tử đi lại, các đối số phải và trái được chuyển đổi. Do đó, cơ sở được lặp lại cho số chữ số cần thiết, do đó 32/2.
  • là một hàm niladic chấp nhận đầu vào của người dùng và đánh giá nó.
  • +/giảm (gấp) đối số đúng của nó bằng cách sử dụng +. (Chúng tôi cộng 0 và 1.)

2
Điều này không phá vỡ sự Built-in base conversion functionschống đối?
Gareth

Rất tiếc! Bỏ lỡ cái đó
Dillon Cower

Trời ạ! Nghĩ rằng tôi đã cho mình cơ hội chiến đấu với chương trình J của mình! :-) Công việc tốt.
Gareth

@Gareth: Tôi đã không nhận ra cho đến khi đọc lời giải thích của bạn, nhưng câu trả lời của tôi khá giống với bạn! Tôi đoán điều đó có thể được mong đợi từ APL và J. :)
Dillon Cower

11

Brainbool , 2

,.

Việc giải thích hợp lý nhất, theo ý kiến của tôi (và những gì hầu hết các câu trả lời sử dụng) của "số cao nhất ngôn ngữ của bạn là khả năng xử lý" là "lớn nhất số lượng ngôn ngữ của bạn natively hỗ trợ". Brainbool là một dẫn xuất brainfuck sử dụng các bit thay vì byte và lấy đầu vào và đầu ra ở dạng nhị phân ( 01ký tự) thay vì mã ký tự. Do đó 1, số lượng lớn nhất được hỗ trợ là lớn nhất và nhỏ nhất là 0có trọng số Hamming 10tương ứng.

Brainbool được tạo ra vào năm 2010, theo Esolang.


9
Tôi biết nó phải tồn tại, nhưng tôi phải mất một giờ để phân loại các dẫn xuất Brainfuck trên Esolang để tìm Brainbool.
lirtosiast

8

J, 13 ký tự

(+ số chữ số trong số)

+/2|<.n%2^i.32

Cách sử dụng: thay thế ntrong chương trình bằng số cần kiểm tra.

Ví dụ:

+/2|<.56432%2^i.32
8
+/2|<.45781254%2^i.32
11
+/2|<.0%2^i.32
0

Có lẽ có một cách sắp xếp lại thứ này để con số có thể được đặt ở đầu hoặc cuối, nhưng đây là mục J đầu tiên của tôi và bây giờ đầu tôi hơi đau.

Giải thích (chủ yếu để tôi hiểu nó trong tương lai)

i.32 - tạo một mảng các số từ 1 đến 32

2^ - biến danh sách thành quyền hạn của hai 1 thành 4294967296

n% - chia số đầu vào cho từng thành phần trong danh sách

<. - làm tròn tất cả các kết quả divison xuống số nguyên tiếp theo

2|- giống như %2trong hầu hết các ngôn ngữ - trả về 0 nếu chẵn và 1 nếu lẻ

+/ - tổng các mục trong danh sách (hiện chỉ là 1 hoặc 0)


Tôi sẽ rất vui khi nâng cấp điều này một khi nó đọc từ stdin (hoặc bất cứ thứ gì tương đương với J).
Steven Rumbalski

Điều tốt nhất tôi có thể làm tôi nghĩ (có thể, tùy thuộc vào việc tìm ra cách thức) là di chuyển đầu vào đến cuối chương trình. Đầu vào tiêu chuẩn không được đề cập trong câu hỏi mặc dù?
Gareth

Tôi xin lỗi vì đã không chỉ định cách nhập liệu. Bây giờ sẽ không công bằng khi thay đổi các quy tắc, vì vậy tôi sẽ chấp nhận quy tắc này. Tôi sẽ đề cập đến nó lần sau!
pimvdb

@pimvdb Không có vấn đề gì, đó không phải là một khiếu nại. Tôi nghĩ với các chương trình J mặc dù tất cả những gì bạn có thể làm là xác định một động từ hoạt động trên đầu vào được cung cấp. Không chắc chắn làm thế nào tôi sắp xếp lại điều này để làm điều đó mặc dù. Có lẽ JB hoặc một trong những chuyên gia J khác có thể giúp tôi giải quyết điều đó ...
Gareth

... và đã đọc thêm một số bây giờ tôi thấy rằng tôi đã hoàn toàn sai về đầu vào tiêu chuẩn.
Gareth

8

Brainfuck, 53 ký tự

Điều này đã thiếu một giải pháp Brainfuck bắt buộc, vì vậy tôi đã thực hiện điều này:

[[->+<[->->>>+<<]>[->>>>+<<]<<<]>>>>[-<<<<+>>>>]<<<<]

Lấy số từ ô 1 và đặt kết quả vào ô 6.

Không đăng ký và nhận xét phiên bản:

[  while n != 0
  [  div 2 loop
    -
    >+<  marker for if/else
    [->->>>+<<]  if n != 0 inc n/2
    >
    [->>>>+<<]  else inc m
    <<<
  ]
  >>>>  move n/2 back to n
  [-<<<<+>>>>]
  <<<<
]

6

Python 2.6, 41 ký tự

t,n=0,input()
while n:t+=n%2;n/=2
print t

lưu ý: Câu trả lời khác của tôi sử dụng lambda và đệ quy và câu trả lời này sử dụng vòng lặp while. Tôi nghĩ rằng họ đủ khác nhau để đảm bảo hai câu trả lời.


6

Ruby, 38 ký tự

f=->u{u<1?0:u%2+f[u/2]}
p f[gets.to_i]

Một giải pháp khác sử dụng ruby ​​và cách tiếp cận đệ quy tương tự như Steven.


5

GolfScript, 17 16 ký tự

~{.2%\2/.}do]0-,

Chỉnh sửa: phiên bản mới lưu 1 ký tự bằng cách sử dụng thao tác danh sách thay vì gấp (phiên bản gốc là ~{.2%\2/.}do]{+}*, phiên bản đếm trực tiếp ~0\{.2%@+\2/.}do;:).


5

C, 45

f(n,c){for(c=0;n;n/=2)c+=n%2;printf("%d",c);}

Không có gì thực sự đặc biệt ở đây khi chơi golf trong C: kiểu trả về ẩn, kiểu số nguyên ẩn cho các tham số.


4

Python 2.6, 45 ký tự

b=lambda n:n and n%2+b(n/2) 
print b(input())

1
Có thể rút ngắn hai ký tự bằng cách sử dụng defthay vì lambda.
Konrad Rudolph

1
@KonradRudolph: Thật ra, bạn mất lợi thế một khi bạn bao gồm câu lệnh return.
Steven Rumbalski

Rất tiếc, tôi đã quên điều đó. Ngốc nghếch.
Konrad Rudolph

Bạn không cần print b(input()). Có thể chấp nhận trả về giá trị và lấy "đầu vào" làm đối số cho các hàm.
caird coinheringaahing

4

Perl, 45 43 36 Nhân vật

$n=<>;while($n){$_+=$n%2;$n/=2}print

Cảm ơn Howard vì 45-> 43 và User606723 cho 43-> 36.


Bạn có thể sử dụng $n=int($n/2)ngắn hơn 2 ký tự.
Howard

Chúng tôi có chắc chúng tôi cần int () không? $n=<>;while($n){$_+=$n%2;$n/=2}printĐiều này sẽ tiếp tục lặp cho đến khi $ n / 2 cuối cùng cũng đủ gần 0, nhưng chúng ta có quan tâm không? ;)
dùng606723

@ user606723 Tôi mới dùng thử và nó dường như hoạt động hoàn hảo, ít nhất là cho mọi trường hợp lên tới 1000.
PhiNotPi

3

Perl, 30 ký tự

$==<>;1while$_+=$=%2,$=/=2;say

Dựa trên giải pháp của PhiNotPi's , với một số môn đánh gôn bổ sung. Chạy với perl -M5.010để kích hoạt saytính năng Perl 5.10 .


Liệu $=biến đặc biệt có làm gì đặc biệt trong chương trình của bạn không, hay nó chỉ là một biến thông thường khác?
PhiNotPi

2
@PhiNotPi: $=chỉ lấy các giá trị nguyên, vì vậy sử dụng nó sẽ tiết kiệm cho tôi một int.
Ilmari Karonen

Không nên lập luận dòng lệnh là một phần của số char?
Soham Chowdhury

@SohamChowdhury: Không theo chủ đề meta này .
Ilmari Karonen

3

Lisp thường gặp, 12 ký tự

(giả sử tên biến 1 char - tức là: 11 + độ dài số)

Đây không phải là một chức năng chuyển đổi cơ sở, vì vậy nó sẽ hoạt động:

(logcount x)

Ví dụ:

[1]> (logcount 0)
0
[2]> (logcount 1)
1
[3]> (logcount 1024)
1
[4]> (logcount 1023)
10
[5]> (logcount 1234567890123456789012345678901234567890)
68

(Sử dụng GNU CLISP.)


Hừm, không chính xác những gì tôi nghĩ trong đầu để xem như một câu trả lời :) Tôi không nghĩ mình có thể chấp nhận điều này. Đó là về cơ bản chỉ là một trường hợp này .
pimvdb

3

C, 61 60 57 53 ký tự

void f(x){int i=0;for(;x;x/=2)i+=x%2;printf("%u",i);}

Cơ thể chỉ có 38 ký tự. Chỉnh sửa : loại bỏ toán tử bitwise Chỉnh sửa : đưa printfra khỏi vòng lặp như được đề xuất trong các bình luận Chỉnh sửa : chuyển sang khai báo K & R; Ngoài ra, đây không còn là C99 cụ thể


Tôi thấy một chút !!!
Joanis

Tôi xin lỗi nhưng toán tử AND cũng được tính là toán tử bitwise.
pimvdb

@ M.Joanis: duh, cảm ơn vì đã chú ý. Đã sửa.
sam hocevar

1
Tôi nghĩ rằng bạn có thể dành một vài ký tự nếu bạn chuyển sang K & R C. Nếu bạn ổn với điều đó.
JB

Bạn có thể rút ngắn điều này bằng bốn ký tự bằng cách di chuyển printf ra khỏi vòng lặp.
bến tàu

3

dc - 26 ký tự

Điều này khá dài, chủ yếu là do thiếu các cấu trúc vòng lặp trong dc.

0?[d2%rsi+li2/d0<x]dsxx+p

Tiếp tục cộng modulo 2 của số và chia số cho đến khi nó bằng không. Có thể xử lý số nguyên dài tùy ý.

Thí dụ:

$ dc -e '0?[d2%rsi+li2/d0<x]dsxx+p' <<< 127
7
$ dc countones.dc <<< 1273434547453452352342346734573465732856238472384263456458235374653784538469120235
138

3

C, 66 ký tự

main(int n,char **a){printf("%u",__builtin_popcount(atoi(a[1])))};

Lưu ý: yêu cầu trình biên dịch tương thích gcc hoặc gcc (ví dụ ICC, clang).

Đối với một số CPU __builtin_popcountbiên dịch thành một lệnh đơn (ví dụ: POPCNTtrên x86).


Có đúng là __builtin_popcountthực sự chỉ thực hiện việc đếm 1chính nó? Nếu vậy, mặc dù nó không hoàn toàn sai theo các quy tắc, nhưng thật lòng tôi không nghĩ đây là một mục công bằng.
pimvdb

Bạn có thể nên quy định điều này trong câu hỏi nếu bạn muốn không cho phép các mục nhập tận dụng các khả năng tích hợp sẵn của một ngôn ngữ hoặc trình biên dịch nhất định.
Paul R

Đây không phải là C ++ hợp pháp vì trong C ++, bạn không thể bỏ qua kiểu trả về trên chính, cũng không sử dụng printfmà không có trước.
celtschk

@celtschk: điểm công bằng - đã chỉnh sửaC++
Paul R

2

JavaScript, 78 72 71 ký tự

Tôi sẽ đăng giải pháp ban đầu mà tôi đã đưa ra trước khi đăng câu hỏi. Đã có một câu trả lời JavaScript tốt hơn nhiều :)

for(n=prompt(a=0),j=1;j<=n;j*=2)for(i=j;i<=n;i+=2*j)n<i+j&&a++;alert(a)

http://jsfiddle.net/Mk8zd/1/

Ý tưởng xuất phát từ một số "thẻ đọc tâm trí" cho phép bạn có được số người khác có trong đầu, bằng cách cho họ xem thẻ và cho họ biết số thẻ của họ rõ ràng.

Nó hoạt động vì mỗi số là một kết hợp duy nhất của 1s / 0s trong nhị phân. Giải pháp của tôi kiểm tra số "thẻ" nào là số rõ ràng để xác định có bao nhiêu1 xem nó có s. Nó chỉ không hiệu quả lắm, mặc dù ...

Tôi tìm thấy tài liệu này phác thảo kỹ thuật đọc tâm trí.


2

Haskell (60 ký tự)

f n=sum[1|x<-[0..n],odd$n`div`2^x]
main=interact$show.f.read

2

PHP, 57

$i=$s=0;for(;$i<log($n,2);){$s+=$n/pow(2,$i++)%2;}echo$s;

Điều này giả định rằng $ngiữ giá trị được kiểm tra.

PHP, 55 (giải pháp thay thế)

function b($i){return$i|0?($i%2)+b($i/2):0;}echo b($n);

Một lần nữa, điều này giả định rằng $ngiữ giá trị được kiểm tra. Đây là một thay thế bởi vì nó sử dụng toán tử hoặcfloor đầu vào.

Cả hai giải pháp đều hoạt động và không gây ra thông báo.


2

Ocaml, 45 ký tự

Dựa trên giải pháp của @Leah Xue. Ba khoảng trắng có thể được loại bỏ và nó ngắn hơn (~ 3 ký tự) để sử dụng chức năng thay vì if-then-other.

let rec o=function 0->0|x->(x mod 2)+(o(x/2))  


1

Scala, 86 ký tự

object O extends App{def f(i:Int):Int=if(i>0)i%2+f(i/2)else 0
print(f(args(0).toInt))}

Sử dụng: scala O 56432


1

D (70 ký tự)

int f(string i){int k=to!int(i),r;while(k){if(k%2)r++;k/=2;}return r;}

1

R, 53 ký tự

o=function(n){h=n%/%2;n%%2+if(h)o(h)else 0};o(scan())

Ví dụ:

> o=function(n){h=n%/%2;n%%2+if(h)o(h)else 0};o(scan())
1: 56432
2: 
Read 1 item
[1] 8
> o=function(n){h=n%/%2;n%%2+if(h)o(h)else 0};o(scan())
1: 45781254
2: 
Read 1 item
[1] 11
> o=function(n){h=n%/%2;n%%2+if(h)o(h)else 0};o(scan())
1: 0
2: 
Read 1 item
[1] 0

Nếu nhập số không phải là một phần của số ký tự, thì đó là 43 ký tự:

o=function(n){h=n%/%2;n%%2+if(h)o(h)else 0}

với các trường hợp thử nghiệm

> o(56432)
[1] 8
> o(45781254)
[1] 11
> o(0)
[1] 0

1

OCaml, 52 ký tự

let rec o x=if x=0 then 0 else (x mod 2) + (o (x/2))

1

Kế hoạch

Tôi đánh bóng các quy tắc một chút để thêm vào thử thách. Hàm không quan tâm đến cơ sở của số vì nó sử dụng thang nhị phân của chính nó. Tôi đã được truyền cảm hứng từ cách tương tự để chuyển đổi số hoạt động. Tôi chỉ sử dụng đệ quy đơn giản cho việc này:

(define (find-ones n)
  (define (nbits n)
    (let nbits ([i 2])
      (if (< i n) (nbits (* i 2)) i)))
  (let f ([half (/ (nbits n) 2)] [i 0] [n n])
    (cond [(< half 2) i]
      [(< n i) (f (/ half 2) i (/ n 2))]
      [else (f (/ half 2) (+ i 1) (/ n 2))])))

1

Không đọc số thành nhị phân hay in số từ nhị phân "hàm chuyển đổi cơ sở dựng sẵn", do đó làm mất hiệu lực mọi câu trả lời ở trên đó printlà số nguyên? Nếu bạn cho phép đọc và in một số nguyên, giống như hầu hết các câu trả lời ở trên, thì tôi sẽ đưa ra yêu cầu bằng hàm dựng sẵnpopcount :

Haskell, 50

Có một popCountthói quen được thêm vào Data.Bitsmô-đun cho GHC v7.2.1 / v7.4.1 vào mùa hè này (xem vé liên quan đến bản gốcràng buộc ).

import Data.Bits
main=interact$show.popCount.read

Tôi không thể đánh bại các điểm số Python và Perl ở trên bằng cách sử dụng GMPYhoặc GMP::Mpzcác mô-đun của chúng cho GMP, mặc dù vậy, GMP cũng cung cấp chức năng đếm số .


1

JavaScript, 49 47 45 42 byte

for(n=prompt(o=0);n=n/2|0;o+=n%2);alert(o)

Bản trình diễn: http://jsfiddle.net/hcYdx/4/

Chỉnh sửa 1: xóa qvà sử dụng ~~để làm tròn, lưu 2 ký tự.

Chỉnh sửa 2: sử dụng |0toán tử làm tròn thay vì ~~để lưu dấu ngoặc đơn (2 ký tự).

Sửa 3: đơn giản hóa n>0đến nvà kết hợp với n=n/2|0để làm cho toàn bộ điều kiện; bây giờ đã lãng phí không gian câu lệnh :(


3
Không phải là |0một toán tử bitwise?
Vilx-

Về mặt kỹ thuật thì có. Nhưng tôi đang sử dụng nó hoàn toàn để làm tròn đến int gần nhất, vì vậy tôi không nhận được bất kỳ lợi ích khôn ngoan nào :)
mellamokb

Mùi như uốn cong các quy tắc với tôi ... nhưng tôi không phải là thẩm phán.
Vilx-

Đầu vào 1 cho đầu ra 0.
Atreys

1
|là toán tử bitwise ... nó không được phép. Thời gian để làm Math.round:-)
Jamie

1

Java 7, 36 byte

int b(Long a){return a.bitCount(a);}

Bởi vì tất nhiên, tất cả mọi thứ, là thứ mà Java đã tích hợp sẵn cho ...


Điều này không phù hợp với "chức năng chuyển đổi cơ sở tích hợp", bị cấm?
FlipTack

@ Flp.Tkc Tôi không thực sự chuyển đổi cơ sở. Tôi không biết làm thế nào bitCounthoạt động dưới mui xe.
Chọc

điều này có vẻ như chỉ cần sử dụng một bulitin để thực hiện công việc, nhưng ok ...
FlipTack

@ Flp.Tkc Đó là ... chính xác nó là gì? Tôi thậm chí bao gồm tất cả các thư viện cần thiết (không có bất kỳ). Điều này đang thể hiện sức mạnh của ngôn ngữ! meta liên quan
Chọc

1

TI-Basic (TI-84 Plus CE), 30 byte

Prompt X
0→S
While X
S+remainder(2,X→S
int(X/2→X
End
S

TI-Basic là ngôn ngữ được mã hóa, tất cả các mã thông báo nhưng remainder(một byte , phần còn lại là hai


Chào mừng đến với trang web!
DJMcMayhem

1

PHP, 36 byte

while($n){$o+=$n%2;$n/=2*1;}echo $o;

Giả sử $nlà số cần kiểm tra, hiển thị Thông báo PHP $ovà không hoạt động chính xác khi$n 0 (không có kết quả).

PHP, 53 byte

$n=$argv[1];$o=0;while($n){$o+=$n%2;$n/=2*1;}echo $o;

Chấp nhận đầu vào dòng lệnh, không hiển thị Thông báo PHP và xuất ra chính xác cho 0.


Chào mừng đến với trang web! :)
DJMcMayhem
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.