Подсчитайте количество единиц в 16-разрядном целом числе без знака


24

Напишите некоторые операторы, которые будут считать количество единиц в шестнадцатиразрядном целом числе без знака.

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


2
Совет: точно так же, как некоторые цифры в числе совпадают с числом mod 9, некоторые биты равны числу mod 1.
PyRulez

8
@PyRulez Любое число равно нулю по модулю 1.
Томас

1
Привет! Вы выбрали неверный ответ в качестве принятого (по умолчанию логика прерывания связей в самой ранней публикации).
Оптимизатор

4
@ Томас Я никогда не говорил, что это полезный совет.
PyRulez

2
Почему этот вопрос вызывает близкое голосование ПОСЛЕ того, как большинство ответов было опубликовано? Близкие избиратели, пожалуйста, укажите вашу причину в комментариях. Если это 4-байтовый ответ es1024 (очень умный), который не соответствует стандартным лазейкам (поскольку он использует встроенную функцию), пожалуйста, укажите, что это является причиной. Иначе что это?
Уровень Река St

Ответы:


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 (false, если это так, true, если это не так).

Вот оно в действии по номеру 1337 из вопроса. Обратите внимание, что вычитание 1 переворачивает младший значащий 1 бит и все нули вправо.

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

РЕДАКТИРОВАТЬ: для полноты, вот простой алгоритм, который на один байт длиннее (и немного медленнее.)

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


1
@ edc65, как оказалось, я заново изобрел колесо. По крайней мере, я сохранил 2 байта, пропустив {}. Это такая простая задача, я не должен удивляться, что кто-то уже придумал ее.
Уровень Река St

«Впервые опубликовано в 1960 году» , впечатляет.
mbomb007

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

1
@nmxprime OP запрашивает неподписанный 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. Тогда x = -7 загружает (1 << 32) -7 = 4294967289 в x.
Уровень Река St

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() читает ввод из стандартного ввода.

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: Да, это тоже странно для меня. Ну что ж. Если бы каждый свинина был безупречен, у нас не было бы хот-догов.
Алекс А.

И это самая странная метафора.
seequ

3

Рубин, 18 байт

n.to_s(2).count'1'


1
n.to_s(2).count ?1тоже работает, но такой же длины
Пикколо

Версия 2019: n.digits (2) .sum / 15 байтов
GB

3

Далее 48 49 байтов

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

Если нужна фактическая функция, то вторая строка становится

: c 0 swap c ;

и вы называете это "1337 с". Относительно многословные контрольные слова Форта делают его сложным (на самом деле, они делают много таких сложных).

Изменить: Моя предыдущая версия не правильно обрабатывать отрицательные числа.


3

Mathematica, 22 18 байт

Спасибо alephalpha за напоминание о DigitCount.

DigitCount[#,2,1]&

@alephalpha спасибо, но DigitCount принимает другой параметр :)
Martin Ender

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-функция 'reguar'. функция B (n, x) {для (x = 0; n; n >> = 1) x + = n & 1; return x}
волчебный молот

@ user1455003 Большое спасибо или ваше предложение! Я использовал его, адаптировал к ES6 и сильно укоротил. Спасибо!
Исмаэль Мигель

Пожалуйста! Мне нравится то, что ты сделал с этим. С рекурсией регулярный JavaScript снизился до 39! function B (n) {return n? (1 & n) + B (n >> 1): 0}
волчебный молот

@ user1455003 Если хотите, вы можете отредактировать часть ES5 и добавить количество байтов в версию для гольфа. (Я думаю, что вы выиграли репутацию с правками).
Исмаэль Мигель

@ user81655 ВАУ! Оно работает!!! Большое спасибо! Я действительно знал, что это можно сделать короче
Исмаэль Мигель

2

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

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

Программа просто повторяет мод 2, вычитает и делит, пока входное число не станет равным нулю, а затем печатает сумму мод 2.

Тест с -vфлагом, например

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

Для 16-битного целого числа кодовая точка ввода, вероятно, не подходит. ( -v
Флаговая

@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)));
Виниций Монтейру

1
@ViniciusMonteiro Большое спасибо за ваше предложение. Я действительно любил это! Я добавил это к ответу.
Исмаэль Мигель

Получите четыре байта, используя <?=substr_count(decbin(1337),"1");(34 байта)
Cogicero

1
@Cogicero И вы можете сэкономить еще больше, удалив кавычки: <?=substr_count(decbin(1337),1);. Это в сумме 32 байта. Учитывая, что это достаточно другой код, вы не хотите опубликовать его как свой собственный ответ? Я, безусловно, буду голосовать!
Исмаэль Мигель

@Cogicero Это только на два байта короче, если вы используете параметризацию: <?=substr_count(decbin($argv[1]),1);(или $_GET[n]; 36 байтов)
Тит


2

Japt, 3 байта (неконкурентный)

¢¬x

Попробуй это здесь.


Человек, я никогда не вижу эти даты по какой-то причине.
Mama Fun Roll

1
Ха-ха, Джапт самый короткий: D Кстати, ¢o1 lбудет работать. Еще один интересный подход -¢¬r-0; ¢¬разбивается на массив двоичных цифр, r-0уменьшается на вычитание, начиная с 0, и -сводит на нет результат, делая его положительным.
ETHproductions

По состоянию на прошлую ночь, теперь вы можете использовать ¢¬x.
ETHproductions

2

пчелиный воск ,31 27 байт

Неконкурентный ответ. Пчелиный воск новее, чем этот вызов.

Это решение использует способ Брайана Керигана для подсчета установленных битов с сайта «Bit Twiddling Hacks».

он просто проходит через цикл, увеличивая счетчик битов и повторяя number=number&(number-1)до number = 0. Решение проходит через цикл так часто, как установлены биты.

Я мог бы сбрить 4 байта, переставив несколько инструкций. Обновлены и исходный код, и пояснения:

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

Объяснение:

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)

Клонируйте мой репозиторий GitHub, содержащий интерпретатор пчелиного воска, спецификации языка и примеры.


1

Java, 17 байт

Работает на byte, short, charи int. Используйте в качестве лямбды.

Integer::bitCount

Тест здесь

Без использования встроенных модулей:

42 байта

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

Тест здесь


6
это стандартная лазейка: встроенные функции, которые делают именно то, что вы хотите, запрещены.
FUZxxl

@FUZxxl ОП никогда не запрещал стандартные лазейки
Коул Джонсон


6
@FUZxxl Хотя es1024 прав, что стандартные лазейки по умолчанию закрыты, использование встроенных функций в настоящее время не является принятой лазейкой при разбивке голосов + 43 / -26.
Мартин Эндер

1

Зажим , 6

2 способа:

cb2nx1

Это простой перевод требования: количество единиц в представлении числа в base-2.

r+`b2n

Другой метод, который принимает сумму цифр представления base-2.


1

Октава, 18

sum(dec2bin(s)-48)

Пример:

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




1

PowerShell (51 байт)

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

Объяснение:
[convert]::ToString($s,2)создает двоичное представление строки из $s.
[char[]]преобразует его в массив символов и позволяет перечислять каждый символ.
|%{"+$_"}каждый символ со знаком «+»
"$()"неявно вызывает .ToString()результирующее
|iexподвыражение, суммирующее переданную строку (т. е. «+1 +0 +1 +1 +0 +1 +0 +0» = 4)


Hiya! Следуя той же логике, что и у вас, почему бы не использовать встроенный -joinоператор и неявный .ToString()для получения 45 байтов с [char[]][convert]::ToString($s,2)-join'+'|iex... ИЛИ, в качестве другого подхода используйте встроенный -replaceоператор для получения 43 байтов с([convert]::ToString($s,2)-replace0).length
AdmBorkBork

1

Clojure, 42 байта

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

Чтение справа налево, преобразование в двоичную строку, преобразование в последовательность символов, фильтрация по 1s и подсчет, сколько у вас есть.

Отредактировано с помощью Sieg


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

Вам нужен еще один персонаж#(count(filter #{\1}(Integer/toString % 2)))
Нил Массон

Нет, ты не :)
seequ

Вот что я получил, когда попробовал:CompilerException java.lang.IllegalArgumentException: No matching method: toString_PERCENT_
Нил Массон

Я проверил это в Try Clojure. Видимо, страница вдруг не распознается Integer/toString. Это сработало секунду назад, хотя.
Seequ

1

Haskell 42 символа

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

объявляет использование функции f :: Integer -> Integer
из интерактивного интерпретатора как f <number>или добавляет строку main=print$f <number>в конец файла.


Вы можете сэкономить много байтов, напрямую суммируя rem n 2s вместо построения списка и используя divвместо quot: t 0=0 t n=t(div n 2)+rem n 2- больше fнет.
Ними

1

Matlab, 13 байт

de2biсоздает вектор нулей и единиц, представляющих двоичное число, и sumпросто возвращает сумму всех записей.

sum(de2bi(n))

1

𝔼𝕊𝕄𝕚𝕟, 4 символа / 11 байт (неконкурентные)

⨭⟦ïⓑ

Try it here (Firefox only).

объяснение

Преобразует входные данные в двоичные, разделяет их на символы и получает сумму результирующего массива.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.