Порахуйте кількість одиниць у непідписаному 16-бітовому цілому


24

Напишіть деякий виклад (и), який підраховуватиме кількість одиниць у непідписаному шістнадцяти бітовому цілому.

Наприклад, якщо вхід є 1337, то результат полягає в 6тому, що 1337як шістнадцять біт двійкове число є 0000010100111001, яке містить шість.


2
Порада: подібно до того, як деякі цифри в числі збігаються з числом mod 9, деякі біти дорівнюють числу mod 1.
PyRulez

8
@PyRulez Будь-яке число дорівнює нулю за модулем 1.
Томас,

1
Привіт, ви вибрали неправильну відповідь як прийняту відповідь (за замовчуванням логіка вимикача зачісок найчастішого повідомлення).
Оптимізатор

4
@Thomas Я ніколи не казав, що це корисна порада.
PyRulez

2
Чому це питання привертає близькі голоси ПІСЛЯ більшості відповідей було опубліковано? Близькі виборці просимо вказати причину у коментарях. Якщо це прийняття 4-байтової відповіді es1024 (дуже розумної), яка не відповідає стандартним лазівкам (тому що використовується вбудований), будь ласка, зазначте, що це причина. Інакше що це?
Річка Рівня Св.

Відповіді:


37

80386 Код машини, 4 байти

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

Це в 32-бітному чи 16-бітному (реальному чи захищеному) режимі?
FUZxxl

2
@FUZxxl Вузол надана для 16-бітного, хоча заміни axі cxз eaxі ecxзмінює його на 32-бітний. Байт-код однаковий для будь-якого.
es1024

1
@ es1024 Байт-код той самий, якщо він був складений в 16-бітному режимі, а 32-розрядна версія в 32-бітному режимі.
Коул Джонсон

2
Чи не є popcnt вбудованим і, таким чином, збивається зі стандартних лазів? І все-таки заслуга за друге рішення.
Алхімік

5
Якщо ви заявляєте про довжину машинного коду , чи не повинен заголовок бути "80386 Код машини", а не "80386 Асемблер"?
Кевін Рейд

14

Python 2, 17 байт

bin(s).count('1')

binВбудований повертає ціле число перетворюється в двійкову рядок. Потім підраховуємо 1цифри:

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

11

J (5 символів)

J не має явних типів. Це робить все правильно для всіх цілих чисел.

+/@#:
  • +/ сума
  • @ з
  • #: базове два представлення

11

С, 21

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

EDIT: для повноти, ось наївний алгоритм, який на один байт довший (і зовсім трохи повільніше.)

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


1
@ edc65 так, як виявляється, я винаходив колесо. Принаймні я врятував 2 байти, опустивши {}. Це таке просте завдання, я не повинен дивуватися, що хтось його вже придумав.
Річка Рівня Св.

"Вперше опублікований у 1960 році" , вражаючий.
mbomb007

Виправлення наївного алгоритму:for(n=0;x;x/=2)n+=x&1;
Геліос

1
@nmxprime ОП просить непідписаний int. для -7 = 11111111 11111111 11111111 11111001 на моєму 32-бітовому компіляторі я отримую 30 для швидкого алгоритму, що правильно. Для наївного алгоритму він повторює через -7, -7 / 2 = -3, -3 / 2 = -1, -1 / 2 = 0. Це дає неправильну відповідь. Зміна x / = 2 на x >> = 1 може дати правильну відповідь на деяких компіляторах, але C не визначено, чи зміщується 1 або 0 в порожній біт для >> за від'ємними числами. Ті компілятори, які зміщують 1 на, перейдуть у нескінченний цикл. Вирішення завдання полягає у визначенні x як непідписаного int. Тоді х = -7 навантажень (1 << 32) -7 = 4294967289 в х.
Рівень річки Св.

5

Желе , не конкуруючий

Ця відповідь є неконкурентною, оскільки мова була створена після публікації виклику.

2 байти:

BS

Jelly - це нова мова, написана @Dennis, з J-подібним синтаксисом.

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

Спробуйте тут .


4

Pyth, 4 байти

sjQ2

Програма приймає число, вага якого забивається на STDIN.


4

Юлія, 29 27 19 байт

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

Це створює анонімну функцію , яка приймає один аргумент, n. Щоб використовувати його, призначте його на щось подібнеf=n->... і назвіть його як f(1337).

digits()Функція, при виклику з 2 аргументами, повертає масив цифр введення в даній базі. Так digits(n, 2)повертає двійкові цифри n. Візьміть суму масиву, і ви отримаєте кількість одиниць у двійковому поданні n.


Це може бути набагато коротше: у Джулії є функція,count_ones
Ендрю каже, що повернути Моніку

@AndrewPiliser: Дякую за пропозицію, але вбудовані функції, які точно виконують завдання, вважаються стандартною лазівкою і нахмуряються, коли явно не заборонено.
Алекс А.


3

Джо , 4 байти

/+Ba

Це анонімна функція. Baдає двійкове подання числа і /+підсумовує його.

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

3

R, 24 байти

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()))було б те саме?
seequ

@Sieg: На жаль, ні, оскільки sum()не вдається ввести тип raw, який повертається з intToBits().
Олексій А.

Це мені справді дивно.
seequ

1
@Sieg: Так, мені це теж дивно. Ну добре. Якби кожен porkchop був ідеальним, у нас не було б хот-догів.
Алекс А.

І це най дивніша метафора коли-небудь.
seequ

3

Рубін, 18 байт

n.to_s(2).count'1'


1
n.to_s(2).count ?1також працює, але однакової довжини
Пікколо

Версія 2019 року: n.digits (2) .сум / 15 байт
GB

3

По-четверте, 48 49 байт

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

Якщо потрібна фактична функція, то другий рядок стає

: c 0 swap c ;

і ви називаєте це "1337 с". Відносно багатослівні контрольні слова Форта роблять це важким (насправді, вони дуже важкі).

Редагувати: Моя попередня версія неправильно обробляла негативні числа.



3

ES6 (34 22 21 байт):

Це проста рекурсивна функція, яку можна скоротити трохи більше. Він просто трохи запускається і запускається знову:

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 (39 байт):

Обидві функції можна легко адаптувати до 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 і зробив це рекурсивно, щоб скоротити багато!


1
Ось менша функція JavaScript "регулятор". функція B (n, x) {for (x = 0; n; n >> = 1) x + = n & 1; return x}
wolfhammer

@ user1455003 Дякую ВЕЛИКОГО чи Ваші пропозиції! Я використовував його і адаптував його до ES6 і дуже скоротив. Дякую!
Ісмаїл Мігель

Будь ласка! Мені подобається те, що ти зробив з цим. З рекурсією звичайний javascript знижується до 39! функція B (n) {повернути n? (1 & n) + B (n >> 1): 0}
вовчий молот

@ user1455003 Якщо ви хочете, ви можете відредагувати частину ES5 і додати кількість байтів до версії для гольфу. (Я думаю, ви завоюєте репутацію правками).
Ісмаїл Мігель

@ user81655 WOW! Це працює!!! Дуже дякую! Я дійсно знав, що це можна скоротити
Ісмаель Мігель

2

> <> (Риба) , 24 байти + 2 = 26

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

Програма просто повторює mod 2, віднімає і ділить, поки число введення не стане нульовим, після чого надрукує суму моди 2s.

Тест з -vпрапором, наприклад

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

Для 16-бітного цілого числа вхід кодової точки, ймовірно, не є адекватним. (Версія -vпрапора досі працює.)
randomra

@randomra Чорт, ти маєш рацію. Хоча введення Unicode працює, 16-бітний - це лише кілька порядків поза діапазоном ...
Sp3000

2

PHP (38 байт):

Для цього використовується такий самий підхід, як і моя відповідь ES6

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

Це повний код, вам потрібно лише помістити його у файл і отримати доступ до нього через браузер, з параметром n=<number>.

PHP <4,2 (32 байти):

Це трохи коротше:

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

Це надійно працює лише на PHP <4.2, оскільки директива register_globalsбула встановлена Offза замовчуванням від PHP4.2 до PHP5.4 (який був видалений на той час).

Якщо ви створите php.iniфайл із register_globals=On, це спрацює.

Щоб використовувати код, перейдіть до файла за допомогою браузера з допомогою POST або GET.

Пропозиція @ViniciusMonteiro (38/45 байт):

Він дав 2 дійсно хороших пропозиції, які дуже цікаво використовують функцію array_sum:

38 байт:

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

45 байт:

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

Це дійсно чудова ідея, і її можна трохи скоротити до 36 байт:

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

2
Або ви можете використовувати echo array_sum (str_split (decbin (1337))); і ви можете використовувати занадто echo array_sum (preg_split ('//', decbin (1337)));
Vinicius Monteiro

1
@ViniciusMonteiro Дякую вам за пропозицію. Мені це дуже сподобалось! Я додав це до відповіді.
Ісмаїл Мігель

Набирайте чотири байти, використовуючи <?=substr_count(decbin(1337),"1");(34 байти)
Cogicero

1
@Cogicero І ви можете заощадити ще більше, видаливши лапки: <?=substr_count(decbin(1337),1);. Це загалом 32 байти. Враховуючи, що це досить інший код, чи не хочете ви розміщувати його як власну відповідь? Я, безумовно, підтримаю це!
Ісмаїл Мігель

@Cogicero It´s only two bytes shorter if you use parametrization: <?=substr_count(decbin($argv[1]),1); (or $_GET[n]; 36 bytes)
Titus


2

Japt, 3 bytes (non-competitive)

¢¬x

Try it here.


Man, I never see those dates for some reason.
Mama Fun Roll

1
Haha, Japt is shortest :D BTW, ¢o1 l would work as well. Another interesting approach is -¢¬r-0; ¢¬ splits into array of binary digits, r-0 reduces by subtraction, starting at 0, and - negates the result, making it positive.
ETHproductions

As of last night, you can now use ¢¬x.
ETHproductions

2

beeswax, 31 27 bytes

Non-competing answer. Beeswax is newer than this challenge.

This solution uses Brian Kherigan’s way of counting set bits from the “Bit Twiddling Hacks” website.

it just runs through a loop, incrementing the bit count, while iterating through number=number&(number-1) until number = 0. The solution only goes through the loop as often as there are bits set.

I could shave off 4 bytes by rearranging a few instructions. Both source code and explanation got updated:

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

Explanation:

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)

Clone my GitHub repository containing the beeswax interpreter, language spec and examples.


1

Java, 17 bytes

Works for byte, short, char, and int. Use as a lambda.

Integer::bitCount

Test here

Without using built-ins:

42 bytes

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

Test here


6
this is a standard loophole: builtin functions that do exactly what you want are forbidden.
FUZxxl

@FUZxxl The OP never forbade standard loopholes
Cole Johnson


6
@FUZxxl While es1024 is right that the standard loopholes are closed by default, using built-in functions is currently not an accepted loophole at a vote breakdown of +43/-26.
Martin Ender

1

Clip, 6

2 ways:

cb2nx1

This is a straightforward translation of the requirement: the count of ones in the base-2 representation of number.

r+`b2n

Another method, which takes the sum of the digits of the base-2 representation.


1

Octave, 18

sum(dec2bin(s)-48)

Example:

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




1

PowerShell (51 bytes)

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

Explanation:
[convert]::ToString($s,2) produces a binary string representation from $s.
[char[]] casts it as a char array and allows us to enumerate each char.
|%{"+$_"} prepends each character with a + sign
"$()" implicitly calls .ToString() on the resulting sub expression
|iex sums the piped string (ie. "+1 +0 +1 +1 +0 +1 +0 +0" = 4)


Hiya! Following the same logic you have, why not use the inline -join operator and an implicit .ToString() to achieve 45 bytes with [char[]][convert]::ToString($s,2)-join'+'|iex ... OR, as a different approach use inline -replace operator to achieve 43 bytes with ([convert]::ToString($s,2)-replace0).length
AdmBorkBork

1

Clojure, 42 bytes

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

Reading right to left, convert to a binary string, convert to a sequence of characters, filter on 1s and count how many you have.

EDITED With help from Sieg


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

You need one more character #(count(filter #{\1}(Integer/toString % 2)))
Neil Masson

No you don't. :)
seequ

This is what I got when I tried it: CompilerException java.lang.IllegalArgumentException: No matching method: toString_PERCENT_
Neil Masson

I tested it in Try Clojure. Apparently the page suddenly doesn't recognize Integer/toString. It worked a second ago though.
seequ

1

Haskell 42 chars

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

declares the function f :: Integer -> Integer
use from the interactive interpreter as f <number> or add the line main=print$f <number> to the end of the file.


You can save a lot of bytes by directly summing the rem n 2s instead of building a list of it and by using div instead of quot: t 0=0 t n=t(div n 2)+rem n 2 - no f anymore.
nimi

1

Matlab, 13 bytes

de2bi creates a vector of zeros and ones representing the binary number, and sum just returns the sum of all the entries.

sum(de2bi(n))

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.