Cetak jumlah yang dalam jumlah biner tanpa menggunakan operator bitwise

14

Deskripsi

Diberi nomor, cetak jumlah yang 1dimilikinya dalam representasi biner.

Memasukkan

Angka >= 0dalam basis 10 yang tidak akan melebihi angka tertinggi yang dapat ditangani oleh bahasa Anda.

Keluaran

Jumlah 1s dalam representasi biner.

Kondisi menang

Kode terpendek menang.

Dilarang

  • Operator bitwise. Operator lain, seperti penambahan dan perkalian, diizinkan.
  • Fungsi konversi basis bawaan.

Contohnya

Input:     Ouput:

56432      8


Input:     Output:

45781254   11


Input:     Output:

0          0
pimvdb
sumber
Apakah fungsi diizinkan? Saya ingin membuat solusi Java, tetapi menulis kode lengkap terlalu membosankan ...: /
HyperNeutrino
1
Saya kira saya tidak akan menggunakan Wise untuk tantangan ini ... :)
MildlyMilquetoast

Jawaban:

16

APL, 9 12 karakter

+/2|⌊⎕÷2*⍳32

Ini mengasumsikan bahwa interpreter menggunakan bilangan bulat 32-bit, dan itu ⎕IOdiatur ke 0 (artinya monadik dimulai dengan 0, bukan 1). Saya menggunakan Dyalog APL versi 32-bit .

Penjelasan, dari kanan ke kiri:

  • ⍳32menghasilkan vektor 32bilangan bulat pertama (seperti yang dijelaskan sebelumnya, karena ⎕IO0, vektor ini dimulai dengan 0).
  • *adalah fungsi daya. Dalam hal ini, ia menghasilkan 2kekuatan setiap elemen dari vektor yang disediakan sebagai argumen yang tepat.
  • ÷adalah fungsi dibagi-oleh. Ini memberi kita (input pengguna yang dievaluasi) dibagi dengan setiap elemen vektor di sebelah kanannya (masing-masing kekuatan dua).
  • lantai setiap elemen argumen di sebelah kanannya.
  • 2|memberi kita sisa dari setiap elemen ke kanan dibagi dengan 2.
  • /mengurangi (melipat) argumen kanannya menggunakan fungsi ke kiri +,.

Tidak lagi 9 karakter. :(

Versi lama dan melanggar aturan:

+/⎕⊤⍨32/2

Penjelasan, dari kanan ke kiri:

  • 32/2: Replikasi 2, 32kali.
  • mengubah fungsi diad ke kiri, yang dalam hal ini (yaitu, X⊤⍨Ysetara dengan Y⊤X).
  • adalah fungsi encode. Ini mengkodekan integer ke kanan di dasar yang diberikan di sebelah kirinya. Perhatikan bahwa, karena operator bolak-balik, argumen kanan dan kiri dialihkan. Basis diulang untuk jumlah digit yang dibutuhkan, karenanya 32/2.
  • adalah fungsi niladik yang menerima input pengguna dan mengevaluasinya.
  • +/mengurangi (melipat) argumen yang benar menggunakan +. (Kami menambahkan 0 dan 1.)
Dillon Cower
sumber
2
Tidakkah ini melanggar Built-in base conversion functionslarangan?
Gareth
Aduh! Merindukan yang itu.
Dillon Cower
Gah! Kupikir aku memberi diriku kesempatan bertarung dengan program J-ku! :-) Pekerjaan yang baik.
Gareth
@ Gareth: Saya tidak menyadari sampai membaca penjelasan Anda sekarang, tapi jawaban saya sangat identik dengan Anda! Saya kira itu bisa diharapkan dari APL dan J. :)
Dillon Cower
11

Brainbool , 2

,.

Penafsiran yang paling masuk akal, menurut saya (dan apa yang sebagian besar jawaban gunakan) dari "angka tertinggi yang dapat ditangani oleh bahasa Anda" adalah "jumlah terbesar yang didukung bahasa Anda secara native ". Brainbool adalah turunan brainfuck yang menggunakan bit daripada byte, dan mengambil input dan output dalam biner ( 0dan 1karakter) daripada kode karakter. Karenanya 1, jumlah terbesar yang didukung secara 0alami adalah , dan yang terkecil adalah , yang masing 1- 0masing memiliki bobot Hamming .

Brainbool dibuat pada 2010, menurut Esolang.

lirtosiast
sumber
9
Saya tahu itu pasti ada, tetapi butuh satu jam saya memilah-milah turunan Brainfuck di Esolang untuk menemukan Brainbool.
lirtosiast
8

J, 13 karakter

(+ jumlah digit dalam angka)

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

Penggunaan: ganti n program dalam dengan nomor yang akan diuji.

Contoh:

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

Mungkin ada cara menata ulang ini sehingga jumlahnya dapat ditempatkan di awal atau akhir, tetapi ini adalah entri J pertama saya dan kepala saya sedikit sakit sekarang.

Penjelasan (terutama agar saya memahaminya di masa depan)

i.32 - Membuat array angka 1 hingga 32

2^ - Mengubah daftar menjadi kekuatan dua 1 hingga 4294967296

n% - Membagi nomor input dengan masing-masing elemen dalam daftar

<. - bulatkan semua hasil divisi ke integer berikutnya

2|- sama seperti %2di kebanyakan bahasa - mengembalikan 0 jika genap dan 1 jika ganjil

+/ - total item dalam daftar (yang sekarang hanya 1s atau 0s)

Gareth
sumber
Saya akan senang untuk memperbaiki ini setelah membaca dari stdin (atau apa pun yang setara J miliki).
Steven Rumbalski
Yang terbaik yang bisa saya lakukan saya pikir (mungkin, tergantung pada mencari tahu bagaimana) adalah memindahkan input ke akhir program. Input standar tidak disebutkan dalam pertanyaan?
Gareth
Maaf karena tidak menentukan cara input. Tidak adil untuk mengubah aturan sekarang, jadi saya akan menerima yang ini. Saya akan menyebutkannya lain kali!
pimvdb
@ pimvdb Tidak masalah, itu bukan keluhan. Saya pikir dengan program J meskipun yang dapat Anda lakukan adalah mendefinisikan kata kerja yang beroperasi pada input yang diberikan. Tidak yakin bagaimana saya mengatur ulang ini untuk melakukan itu. Mungkin JB atau salah satu pakar J lainnya bisa membantu saya ...
Gareth
... dan setelah membaca lebih banyak lagi sekarang saya melihat bahwa saya benar-benar salah tentang input standar.
Gareth
8

Brainfuck, 53 karakter

Ini tidak ada solusi Brainfuck yang wajib, jadi saya buat yang ini:

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

Mengambil angka dari sel 1 dan memasukkan hasilnya ke sel 6.

Versi tidak terdaftar dan dikomentari:

[  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
  [-<<<<+>>>>]
  <<<<
]
salinan
sumber
6

Python 2.6, 41 karakter

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

Catatan: Jawaban saya yang lain menggunakan lambda dan rekursi dan yang ini menggunakan loop sementara. Saya pikir mereka cukup berbeda untuk menjamin dua jawaban.

Steven Rumbalski
sumber
6

Ruby, 38 karakter

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

Solusi lain menggunakan ruby ​​dan pendekatan rekursif yang sama dengan Steven.

Howard
sumber
5

GolfScript, 17 16 karakter

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

Sunting: versi baru menyimpan 1 karakter dengan menggunakan operasi daftar alih-alih lipatan (versi aslinya adalah ~{.2%\2/.}do]{+}*, versi hitung langsung:) ~0\{.2%@+\2/.}do;.

Howard
sumber
5

C, 45

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

Tidak ada yang benar-benar istimewa di sini untuk bermain golf di C: tipe pengembalian implisit, tipe integer implisit untuk parameter.

Tuan Llama
sumber
4

Python 2.6, 45 karakter

b=lambda n:n and n%2+b(n/2) 
print b(input())
Steven Rumbalski
sumber
1
Dapat disingkat dua karakter dengan menggunakan defbukan lambda.
Konrad Rudolph
1
@KonradRudolph: Sebenarnya, Anda kehilangan keuntungan begitu Anda memasukkan pernyataan pengembalian.
Steven Rumbalski
Ups, saya lupa itu. Bodoh.
Konrad Rudolph
Anda tidak membutuhkannya print b(input()). Dapat diterima untuk mengembalikan nilai dan mengambil "input" sebagai argumen untuk fungsi.
caird coinheringaahing
4

Perl, 45 43 36 Karakter

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

Terima kasih kepada Howard untuk 45-> 43, dan untuk User606723 untuk 43-> 36.

PhiNotPi
sumber
Anda dapat menggunakan $n=int($n/2)2 karakter yang lebih pendek.
Howard
Apakah kami yakin kami membutuhkan int ()? $n=<>;while($n){$_+=$n%2;$n/=2}printIni akan terus berulang sampai $ n / 2 akhirnya cukup dekat ke 0, tetapi apakah kita peduli? ;)
user606723
@ user606723 Saya baru saja mencobanya dan sepertinya berfungsi dengan baik, setidaknya untuk setiap kasus hingga 1000.
PhiNotPi
3

Perl, 30 karakter

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

Berdasarkan solusi PhiNotPi , dengan beberapa golf tambahan. Jalankan dengan perl -M5.010untuk mengaktifkan fitur Perl 5.10 say.

Ilmari Karonen
sumber
Apakah $=variabel khusus melakukan sesuatu yang istimewa dalam program Anda, atau hanya variabel biasa?
PhiNotPi
2
@PhiNotPi: $=hanya membutuhkan nilai integer, jadi menggunakannya menghemat saya int.
Ilmari Karonen
Bukankah seharusnya baris perintah arg menjadi bagian dari perhitungan char?
Soham Chowdhury
@SohamChowdhury: Tidak sesuai utas meta ini .
Ilmari Karonen
3

Gangguan Umum, 12 karakter

(dengan asumsi nama variabel 1 char - yaitu: 11 + panjang angka)

Ini bukan fungsi konversi basis, jadi seharusnya berfungsi:

(logcount x)

Contoh:

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

(Menggunakan GNU CLISP.)

Joanis
sumber
Hm, tidak persis apa yang ada dalam pikiran saya untuk dilihat sebagai jawaban :) Saya tidak berpikir saya bisa menerima ini. Ini pada dasarnya hanyalah kasus lain dari ini .
pimvdb
3

C, 61 60 57 53 karakter

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

Badan fungsi hanya 38 karakter. Sunting : dihapus operator bitwise Sunting : printfkeluar dari loop seperti yang disarankan dalam komentar Sunting : beralih ke deklarasi K&R; juga, ini tidak lagi khusus untuk C99

sam hocevar
sumber
Saya melihat bitwise !!!
Joanis
Maaf, operator DAN juga dianggap sebagai operator bitwise.
pimvdb
@ M. Joanis: ya, terima kasih sudah memperhatikan. Tetap.
sam hocevar
1
Saya pikir Anda bisa menyisihkan beberapa karakter jika Anda beralih ke K&R C. Jika Anda setuju dengan itu.
JB
Anda dapat mempersingkat ini dengan empat karakter dengan memindahkan printf keluar dari loop.
marinus
3

dc - 26 karakter

Ini agak panjang, sebagian besar karena kurangnya loop konstruksi di dc.

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

Terus menjumlahkan modulo 2 dari angka dan membaginya dengan hingga sampai mencapai nol. Dapat menangani bilangan bulat panjang yang sewenang-wenang.

Contoh:

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

C, 66 karakter

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

Catatan: membutuhkan kompiler yang kompatibel dengan gcc atau gcc (mis. ICC, dentang).

Untuk beberapa CPU __builtin_popcountmengkompilasi ke instruksi tunggal (misalnya POPCNTpada x86).

Paul R
sumber
Apakah benar bahwa __builtin_popcountsebenarnya hanya menerapkan penghitungan 1itu sendiri? Jika demikian, meskipun tidak sepenuhnya salah menurut aturan, saya jujur ​​tidak berpikir ini adalah entri yang adil.
pimvdb
Anda mungkin harus menetapkan ini dalam pertanyaan jika Anda ingin melarang entri yang memanfaatkan kemampuan bawaan dari bahasa atau kompiler yang diberikan.
Paul R
Ini bukan C ++ legal karena dalam C ++ Anda tidak bisa menghilangkan tipe return pada main, juga tidak menggunakan printftanpa menyertakan sebelumnya.
celtschk
@celtschk: titik adil - dieditC++
Paul R
2

JavaScript, 78 72 71 karakter

Saya akan memposting solusi awal saya yang saya buat sebelum memposting pertanyaan juga. Sudah ada jawaban JavaScript yang jauh lebih baik :)

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/

Idenya datang dari "kartu baca pikiran" tertentu yang memungkinkan Anda mendapatkan nomor yang ada dalam benak orang lain, dengan menunjukkan kartu-kartu itu dan membiarkan mereka mengatakan kartu-kartu mana nomor mereka jelas.

Ini berfungsi karena setiap angka adalah kombinasi unik dari 1s / 0s dalam biner. Solusi saya memeriksa "kartu" mana nomor yang jelas untuk menentukan berapa banyak1 dimilikinya. Hanya saja tidak terlalu efisien, meskipun ...

saya menemukan dokumen ini yang menguraikan teknik membaca pikiran.

pimvdb
sumber
2

Haskell (60 karakter)

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

PHP, 57

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

Ini mengasumsikan bahwa $nmemegang nilai yang akan diuji.

PHP, 55 (solusi alternatif)

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

Sekali lagi, ini mengasumsikan bahwa $nmemegang nilai yang akan diuji. Ini adalah alternatif karena menggunakan operator atau untukfloor input.

Kedua solusi bekerja dan tidak menimbulkan pemberitahuan.

Arjan
sumber
2

Ocaml, 45 karakter

Berdasarkan solusi @Leah Xue. Tiga spasi dapat dihapus dan ini lebih pendek (~ 3 karakter) untuk menggunakan fungsi alih-alih-jika-lain.

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

Mathematica 26

Count[n~IntegerDigits~2,1]
DavidC
sumber
1

Scala, 86 karakter

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

Pemakaian: scala O 56432

Gareth
sumber
1

D (70 karakter)

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

R, 53 karakter

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

Contoh:

> 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

Jika memasukkan nomor bukan bagian dari jumlah karakter, maka itu adalah 43 karakter:

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

dengan kasus uji

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

OCaml, 52 karakter

let rec o x=if x=0 then 0 else (x mod 2) + (o (x/2))
Leah Xue
sumber
1

Skema

Saya sedikit memperbaiki aturan untuk menambah tantangan. Fungsi tidak peduli tentang basis angka karena menggunakan skala binernya sendiri. Saya terinspirasi oleh cara kerja konversi analog ke numerik. Saya hanya menggunakan rekursi sederhana untuk ini:

(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))])))
Samuel Duclos
sumber
1

Tidakkah membaca angka menjadi biner atau mencetak angka dari biner sebagai "fungsi konversi basis bawaan", sehingga membatalkan setiap jawaban di atas yang printmerupakan bilangan bulat? Jika Anda mengizinkan membaca dan mencetak bilangan bulat, seperti hampir semua jawaban di atas, maka saya akan membuat klaim menggunakan fungsi bawaanpopcount :

Haskell, 50

Ada popCountrutin yang ditambahkan ke Data.Bitsmodul untuk GHC v7.2.1 / v7.4.1 musim panas ini (lihat tiket mengenai primop dan penjilidan ).

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

Saya tidak bisa mengalahkan skor Python dan Perl di atas menggunakan modul mereka GMPYatau GMP::Mpzuntuk GMP sayangnya, meskipun GMP memang menawarkan fungsi popcount juga.

Jeff Burdges
sumber
1

JavaScript, 49 47 45 42 byte

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

Demo: http://jsfiddle.net/hcYdx/4/

Sunting 1: hapus qdan gunakan ~~untuk pembulatan, simpan 2 karakter.

Sunting 2: gunakan |0operator pembulatan alih-alih ~~untuk menyimpan tanda kurung (2 karakter).

Edit 3: menyederhanakan n>0untuk ndan menggabungkan dengan n=n/2|0untuk membuat seluruh kondisi; sekarang telah menyia-nyiakan ruang pernyataan :(

mellamokb
sumber
3
Bukankah |0operator bitwise?
Vilx-
Secara teknis ya. Tapi saya menggunakannya murni untuk membulatkan ke int terdekat, jadi saya tidak mendapatkan sedikit pun manfaat :)
mellamokb
Baunya seperti membengkokkan aturan kepada saya ... tapi saya bukan hakim.
Vilx-
Input 1 memberikan output 0.
Atreys
1
|adalah operator bitwise ... tidak diizinkan. Saatnya melakukan Math.round:-)
Jamie
1

Java 7, 36 byte

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

Karena tentu saja ini, dari semua hal, adalah sesuatu yang dimiliki Java untuk ...

Menyodok
sumber
Apakah ini tidak sesuai dengan "fungsi konversi basis bawaan", yang dilarang?
FlipTack
@ Flp.Tkc Saya sebenarnya tidak melakukan konversi basis. Saya tidak tahu bagaimana bitCountberoperasi di bawah tenda.
Poke
ini sepertinya hanya menggunakan bulitin untuk melakukan pekerjaan itu, tapi ok ...
FlipTack
@ Flp.Tkc Itu ... persis apa itu? Saya bahkan memasukkan semua perpustakaan yang diperlukan (tidak ada). Ini menunjukkan kekuatan bahasa! meta terkait
Poke
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-Dasar adalah bahasa tokenized, semua token tetapi remainder(adalah satu-byte , sisanya adalah dua

pizzapants184
sumber
Selamat datang di situs ini!
DJMcMayhem
1

PHP, 36 byte

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

Asumsinya $nadalah angka yang akan diuji, menunjukkan Pemberitahuan PHP untuk $o, dan tidak berfungsi dengan benar ketika $n0 (tidak menghasilkan apa-apa).

PHP, 53 byte

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

Menerima input baris perintah, tidak menampilkan Pemberitahuan PHP, dan menampilkan dengan benar untuk 0.

jstnthms
sumber
Selamat datang di situs ini! :)
DJMcMayhem