İmzasız bir 16 bit tamsayıdakilerin sayısını


24

İmzasız bir on altı bit tamsayıdakilerin sayısını sayan bazı ifadeler yazın.

Girişidir Örneğin, 1337ardından sonucudur 6çünkü 1337bir onaltı bitlik ikili sayı olarak 0000010100111001altı olanları içeren,.


2
İpucu: bir sayının içindeki bazı hanelerin mod 9 sayısına
uyduğu

8
@PyRulez Herhangi bir sayı sıfır modulo 1'dir.
Thomas

1
Merhaba, kabul edilen cevap olarak yanlış bir cevap seçtiniz (varsayılan olarak ilk gönderinin bağ kırıcı mantığı).
Doktor

4
@ Tommas, bunun yararlı bir ipucu olduğunu söylemedim.
PyRulez

2
Yanıtların çoğu gönderildikten SONRA neden bu soru yakın oy çekiyor? Seçmenleri kapatın, lütfen yorumlarınızı nedeninizi belirtin. Eğer standart boşluklara uymayan es1024'ün (çok akıllı) 4-byte cevabını kabul ediyorsa (çünkü bir yerleşik kullanır), bunun nedenini belirtin. Aksi takdirde, nedir?
Seviye Nehri St

Yanıtlar:


37

80386 Makine Kodu, 4 bayt

F3 0F B8 C1

tamsayı alır cxve sayımı çıkarır axve buna eşdeğerdir:

popcnt ax, cx     ; F3 0F B8 C1

Ve burada bir olduğunu 11 10 POPCNT kullanmayan bayt çözümü:

31 C0 D1 E9 10 E0 85 C9 75 F8

hangi eşdeğerdir:

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

Bu 32 bit mi, 16 bit mi (gerçek veya korumalı)
FUZxxl

2
Takımı temin @FUZxxl değiştirilmesi olsa da, 16-bit için axve cxile eaxve ecx32-bit değiştirir. Bayt kodu her ikisi için de aynıdır.
es1024

1
@ es1024 Bayt kodu, eğer 16-bit modunda ve 32-bit sürümü 32-bit modunda derlenmişse aynıdır .
Cole Johnson

2
Popcnt yerleşik yapılı ve bu nedenle standart boşlukların düşen faul değil mi? Yine de ikinci çözüm için kredi.
Simyacı

5
Makine kodunun uzunluğunu talep ettiğinizde , "80386 Assembler" değil, "80386 Makine Kodu" başlığı kullanılmamalıdır?
Kevin Reid

14

Python 2,17 bayt

bin(s).count('1')

binYerleşik getiri tamsayı ikili dizeye dönüştürülür. Daha sonra 1rakamları sayarız :

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

11

J (5 karakter)

J'nin açık bir türü yok. Bu tüm tamsayılar için doğru olanı yapar.

+/@#:
  • +/ toplam
  • @ arasında
  • #: temel iki temsil

11

Cı-21

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

"bazı ifadeler yaz" dedin ("işlev" değil), bu yüzden numaranın girildiğini ve 1'lerin sayısının xgeri döndüğünü varsaydım n. Başlatmam gerekmiyorsa n3 bayt kaydedebilirim.

Bu, bir ifadenin x&x-12 gücü olup olmadığını test etmek için ünlü ifadenin uyarlanmasıdır ( eğer yanlışsa, doğru değilse).

İşte soruya göre 1337 numara ile ilgili eylem var. 1 çıkarma işleminin en az önemli 1 bit ve tüm sıfırları sağa çevirdiğini unutmayın.

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

EDIT: bütünlüğü için, işte bir bayt daha uzun olan ve biraz daha yavaş olan saf algoritma.

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


1
@ edc65 çıktı ki, tekerleği yeniden icat ettim. En azından çıkartarak 2 bayt kurtardım {}. Bu kadar basit bir iş, birisinin çoktan gelmesine şaşırmamam gerekirdi.
Seviye Nehri St

"İlk 1960 yılında yayınlanan" , etkileyici.
mbomb007 23:15

Saf algoritmaya yönelik düzeltme:for(n=0;x;x/=2)n+=x&1;
Helios,

1
@nmxprime OP imzasız int için sorar. -7 = 11111111 11111111 11111111 11111001 32 bit derleyicimde, doğru olan hızlı algoritma için 30 elde ediyorum. Saf algoritması için -7, -7 / 2 = -3, -3 / 2 = -1, -1 / 2 = 0 ile yinelenir. Bu yanlış bir cevap verir. X / = 2 ila x >> = 1 değerinin değiştirilmesi, bazı derleyicilerde doğru cevabı verebilir, ancak C, negatif sayılar üzerinde >> için boş bitin 1 veya 0 değerinin kaydırılıp kaydırılmayacağı konusunda tanımsızdır. 1 değerini değiştiren bu derleyiciler sonsuz bir döngüye girer. Çözüm, x'i işaretsiz bir int olarak tanımlamaktır. Daha sonra x = -7 (1 << 32) -7 = 4294967289’u x’e yükler.
Seviye Nehri St

5

Jöle , rakipsiz

Bu cevap yarışmacı değildir, çünkü meydan okuma yapıldıktan sonra dil oluşturulmuştur.

2 bayt:

BS

Jelly, @Dennis tarafından yazılmış, J benzeri bir sözdizimi ile yazılmış yeni bir dildir.

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

Burada dene .


4

Pyth, 4 bayt

sjQ2

Program hamle ağırlığı STDIN'de bulunan sayıyı alır.


4

Julia, 29 27 19 bayt

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

Bu, tek bir argümanı kabul eden anonim bir işlev oluşturur n,. Kullanmak için, f=n->...onun gibi bir şeye atayın ve onun gibi söyleyin f(1337).

digits()2 argüman çağrıldığında fonksiyonu, belirli bir baz girdi basamak dizisi döndürür. Bu yüzden digits(n, 2)ikili rakamını döndürür n. Dizinin toplamını alın ve ikili gösterimdeki sayıların sayısını elde edin n.


Bu çok daha kısa olabilir: Julia'nın bir işlevi vardırcount_ones
Andrew diyor Reinstate Monica

@AndrewPiliser: Öneriniz için teşekkürler, ancak görevi tam olarak yapan yerleşik işlevler standart bir boşluk olarak kabul edilir ve açıkça izin verilmediğinde üzerine kaşlarını çattı.
Alex A.


3

Joe , 4 bayt

/+Ba

Bu anonim bir işlevdir. Babir sayının ikili gösterimini verir ve /+onu toplar.

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

3

R, 24 bayt

sum(intToBits(scan())>0)

scan() stdin'den girdi okur.

intToBits()bir tamsayı alır ve rawsıfırı ve girişin ikili gösterimini içeren bir vektör türünü döndürür .

intToBits(scan())>0Her elemanın TRUEkarşılık gelen ikili vektör elemanının 1 olduğu bir mantıksal vektör (aksi halde tüm elemanlar 0 ya da 1 ve 1> 0 olduğundan) döndürür FALSE.

R'de, TRUEelemanların sayısını almak için mantıksal bir vektör toplayabilirsiniz, bu nedenle mantıksal vektörleri yukarıdaki gibi toplamak bize ne istediğimizi alır.

Not sum()işleyemez rawdoğrudan girişi, Mantıksal bölümler kullanılarak dolayısıyla geçici çözüm.


sum(intToBits(scan()))Aynı olmaz mıydı ?
15'de

@Sieg: Maalesef hayır sum(), o zaman türden girdi alamıyor raw, ki geri döndüğü şey intToBits().
Alex A.

Bu benim için gerçekten garip.
15'de

1
@Sieg: Evet, benim için de garip. Oh iyi. Her domuz eti mükemmel olsaydı, sosisli sandviçimiz olmazdı.
Alex A.

Ve bu şimdiye kadarki en garip metafor.
seequ

3

Yakut, 18 bayt

n.to_s(2).count'1'


1
n.to_s(2).count ?1ayrıca çalışır, ancak aynı uzunluktadır
Piccolo

2019 sürümü: n.digits (2) .sum / 15 bayt
GB

3

İleri, 48 49 bayt

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

Gerçek bir işleve ihtiyaç duyulursa, ikinci satır

: c 0 swap c ;

ve sen buna "1337 c" diyorsun. Forth'un nispeten ayrıntılı kontrol sözcükleri bunu zorlaştırıyor (aslında, bunlardan bir çoğunu zorlaştırıyorlar).

Düzenleme: Önceki sürümüm negatif sayıları doğru işlemiyordu.


3

Mathematica, 22 18 bayt

Beni hatırlattığı için alephalpha'ya teşekkürler DigitCount.

DigitCount[#,2,1]&

@alephalpha teşekkürler, ancak DigitCount başka bir parametre alır :)
Martin Ender

3

ES6 (34 22 21 bayt):

Bu, biraz daha kısaltılabilen basit bir özyinelemeli fonksiyondur. Sadece biraz zaman alıyor ve tekrar çalışıyor:

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

Bunu http://www.es6fiddle.net/imt5ilve/ adresinde deneyin ( varsebebi 'use strict';).

Balık yendiğime inanamıyorum !!!

Eski olan:

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

ES5 (39 bayt):

Her iki fonksiyon da kolayca ES5'e uyarlanabilir:

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;
    }
}

Eski olan:

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

@ user1455003 bana en küçüğü tetikleyen harika bir fikir verdi:

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

ES6'ya uyarladım ve çok kısaltmak için özyinelemeye yaptım!


1
İşte daha küçük bir 'reguar' javascript işlevi. B (n, x) {için (x = 0; n; n >> = 1) x + = n & 1; dönüş x}
wolfhammer 18:15

@ user1455003 Bir LOT veya öneriniz için teşekkür ederiz! Kullandım ve ES6'ya uyarladım ve çok kısalttım. Teşekkür ederim!
Ismael Miguel

Rica ederim! Yaptıklarını beğendim. Özyineleme ile düzenli javascript 39'a düştü! işlev B (n) {dönüş n? (1 & n) + B (n >> 1): 0}
wolfhammer

@ user1455003 İsterseniz, ES5 bölümünü düzenleyebilir ve bayt sayısını golf sürümüne ekleyebilirsiniz. (Düzenlemelerle itibar kazandığını düşünüyorum).
Ismael Miguel

@ user81655 VAY! İşe yarıyor!!! Çok teşekkür ederim! Bunun daha kısa yapılabileceğini gerçekten biliyordum
Ismael Miguel

2

> <> (Balık) , 24 bayt + 2 = 26

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

Program sadece tekrarlanan mod 2'yi yapar, giriş numarası sıfır olana kadar çıkarır ve böler, ardından mod 2'lerin toplamını yazdırır.

-vBayrakla test edin , örneğin

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

16 bitlik bir tamsayı için kod noktası girişi muhtemelen yeterli değil. ( -vBayrak versiyonu hala çalışıyor.)
randomra

@randomra Lanet olsun, haklısın. Unicode girişi işe
yarıyorken

2

PHP (38 bayt):

Bu benim ES6 cevabım ile aynı yaklaşımı kullanır

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

Bu tam bir koddur, yalnızca bir dosyaya koymanız ve tarayıcıyla erişmeniz yeterlidir n=<number>.

PHP <4.2 (32 bayt):

Bu biraz daha kısa:

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

Direktifi, çünkü bu sadece PHP <4.2 üzerinde güvenilir bir şekilde çalışır register_globalsolarak ayarlandı Off(o sırada çıkarıldı) PHP5.4 için PHP4.2 kadar varsayılan olarak.

php.iniIle bir dosya oluşturursanız register_globals=On, bu işe yarayacak.

Kodu kullanmak için, POST veya GET ile bir tarayıcı kullanarak dosyaya erişin.

@ViniciusMonteiro'nun önerisi (38/45 bytes):

Fonksiyonu çok ilginç bir şekilde kullanan 2 çok iyi öneride bulundu array_sum:

38 bayt:

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

45 bayt:

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

Bu gerçekten harika bir fikir ve biraz daha kısaltılabilir, 36 byte uzunluğunda olabilir:

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

2
Veya echo array_sum kullanabilirsiniz (str_split (decbin (1337))); ve çok echo array_sum kullanabilirsiniz (preg_split ('//', decbin (1337)));
Vinicius Monteiro

1
@ViniciusMonteiro Öneriniz için teşekkür ederiz. Gerçekten çok sevdim! Ben cevaba ekledim.
Ismael Miguel

<?=substr_count(decbin(1337),"1");(34 bayt) kullanarak dört bayt kazanın
Cogicero

1
@Cogicero Ve tırnak kaldırarak daha fazla tasarruf edebilirsiniz: <?=substr_count(decbin(1337),1);. Bu toplam 32 bayttır. Yeterince farklı bir kod olduğu düşünüldüğünde, bunu kendi cevabınız olarak göndermek istemez misiniz? Ben surelly buna oy verecek!
Ismael Miguel,

@Cogicero Parametizasyon kullanıyorsanız sadece iki bayt daha kısadır: <?=substr_count(decbin($argv[1]),1);(veya $_GET[n]; 36 bayt)
Titus


2

Japt, 3 bayt (rekabetçi olmayan)

¢¬x

Burada dene.


Dostum, hiç bir zaman bu tarihleri ​​görmüyorum.
Mama Fun Roll

1
Haha, Japt en kısa: D BTW ¢o1 lde işe yarayacaktı. Diğer ilginç bir yaklaşım ise -¢¬r-0; ¢¬İkili basamak dizisine ayrılır, r-0çıkartma ile azalır, 0'dan başlar ve -sonucu olumsuzlar.
ETHProductions

Dün gece itibariyle artık kullanabilirsiniz ¢¬x.
ETHProductions

2

balmumu ,31 27 bayt

Rekabet etmeyen cevap. Balmumu bu mücadeleden daha yeni.

Bu çözüm Brian Kherigan'ın “Bit Twiddling Hacks” web sitesinden set bit sayma yöntemini kullanıyor.

Sadece yineleme sırasında, bit sayısını artırarak bir döngü geçiyor number=number&(number-1)kadarnumber = 0 . Çözüm, yalnızca ayarlanan bitlerin olduğu kadar sık ​​döngüden geçer.

Birkaç byte yeniden düzenleyerek 4 byte tıraş olabilir. Hem kaynak kodu hem de açıklama güncellendi:

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

Açıklama:

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)

Klon benim GitHub depo balmumu tercüman, dil spesifikasyonları ile örnekler içeren.


1

Java, 17 bayt

İçin çalışır byte, short, char, ve int. Bir lambda olarak kullanın.

Integer::bitCount

Burada test et

Yerleşik kullanmadan:

42 bayt

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

Burada test et


6
bu standart bir boşluktur: tam olarak ne istiyorsan onu yapan yerleşik fonksiyonlar yasaktır.
FUZxxl

@ FUZxxl OP standart boşluklara asla izin vermedi
Cole Johnson


6
@ FUZxxl es1024 standart boşlukların varsayılan olarak kapalı olduğu doğru olsa da, yerleşik işlevlerin kullanılması şu anda + 43 / -26 oy dağılımında kabul edilen bir boşluk değildir.
Martin Ender

1

Klips , 6

2 yol:

cb2nx1

Bu, gereksinimin basit bir çevirisidir: sayının taban-2 gösteriminde olanların sayısı.

r+`b2n

Base-2 gösteriminin rakamlarının toplamını alan başka bir yöntem.


1

Octave, 18

sum(dec2bin(s)-48)

Örnek:

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

1

GML (Game Maker Language), 21 bayt

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



1

PowerShell (51 bayt)

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

Açıklama:
[convert]::ToString($s,2)dan bir ikili dize temsili üretiyor $s.
[char[]]char dizisi olarak yazar ve her karakterin numaralandırılmasını sağlar.
|%{"+$_"}her bir karakteri bir + işaretiyle
"$()"dolaylı .ToString()olarak ortaya çıkan alt ifadeye çağırarak
|iexhazırlar, dizilenmiş dizgenin toplamını (yani.


Selam! Aynı mantığın ardından, neden satır içi -joinoperatörü ve .ToString()45 [char[]][convert]::ToString($s,2)-join'+'|iex-replace([convert]::ToString($s,2)-replace0).length
byte'ı

1

Clojure, 42 bayt

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

Sağdan sola okuma, ikili bir dizgeye dönüştürme, bir karakter dizisine dönüştürme, 1s'de filtreleme ve kaç tane kullandığınızı sayma.

EDİTMELİ Sieg'in yardımıyla


42:#(count(filter #{\1}(Integer/toString% 2)))
15'te

Bir karaktere daha ihtiyacın var#(count(filter #{\1}(Integer/toString % 2)))
Neil Masson

Hayır yapmazsın. :)
seequ

Bunu denediğimde aldığım şey buydu:CompilerException java.lang.IllegalArgumentException: No matching method: toString_PERCENT_
Neil Masson

Try Clojure'da test ettim. Görünüşe göre sayfa aniden tanımıyor Integer/toString. Yine de bir saniye önce çalıştı.
görüyorsunuz

1

Haskell 42 karakter

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

fonksiyon beyan f :: Integer -> Integer
gibi etkileşimli yorumlayıcıdan kullanımını f <number>veya satır ekleyin main=print$f <number>Dosyanın sonuna.


Doğrudan toplayarak bayt bir çok kaydedebilirsiniz rem n 2s yerine onun bir listesini oluşturmaya ve kullanarak divyerine quot: t 0=0 t n=t(div n 2)+rem n 2hayır - fArtık değil.
nimi

1

Matlab, 13 bayt

de2bibir sıfır ve ikili sayıyı temsil eden bir vektör oluşturur ve sumsadece tüm girdilerin toplamını döndürür.

sum(de2bi(n))

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.