Роздрукуйте кількість одиниць у двійковому числі, не використовуючи побітові оператори


14

Опис

Враховуючи число, надрукуйте кількість 1s, яку він має у двійковому поданні.

Вхідні дані

Число >= 0в базі 10, яке не перевищує найвищої кількості, з якою може обходитися ваша мова.

Вихідні дані

Сума 1s у двійковому поданні.

Умова виграшу

Виграє найкоротший код.

Заборонено

  • Побітові оператори. Дозволені інші оператори, такі як додавання та множення.
  • Вбудовані базові функції перетворення.

Приклади

Input:     Ouput:

56432      8


Input:     Output:

45781254   11


Input:     Output:

0          0

Чи дозволені функції? Я хочу зробити рішення Java, але написання повного коду є занадто стомлюючим ...: /
HyperNeutrino

1
Я думаю, я не буду використовувати Wise для цього виклику ... :)
MildlyMilquetoast

Відповіді:


16

APL, 9 12 символів

+/2|⌊⎕÷2*⍳32

Це передбачає, що інтерпретатор використовує 32-бітні цілі числа, і ⎕IOце встановлено на 0 (це означає, що монадика починається з 0, а не з 1). Я використовував 32-бітну версію Dyalog APL .

Пояснення справа наліво:

  • ⍳32генерує вектор перших 32цілих чисел (як пояснено раніше, оскільки ⎕IOдорівнює 0, цей вектор починається з 0).
  • *- це функція живлення. У цьому випадку він генерує 2силу кожного елемента вектора, що подається як його правильний аргумент.
  • ÷- це розділена функція. Він дає нам (оцінене введення користувача), розділене кожним елементом вектора праворуч (кожна потужність на два).
  • перекриває кожен елемент аргументу праворуч.
  • 2|дає нам залишок кожного елемента праворуч розділений на 2.
  • /(Зменшує складки) його правий аргумент з допомогою функції зліва від неї , +.

Не зовсім вже 9 символів. :(

Стара версія, що порушує правила:

+/⎕⊤⍨32/2

Пояснення справа наліво:

  • 32/2: Повтор 2, 32часи.
  • комутує діадичну функцію зліва, яка в даному випадку є (тобто X⊤⍨Yеквівалентна Y⊤X).
  • є функцією кодування. Він кодує ціле число праворуч у базі, даній ліворуч. Зауважте, що через оператора маршруту комутація правою та лівою аргументами перемикається. База повторюється на кількість необхідних цифр 32/2.
  • це niladic функція, яка приймає введення користувача та оцінює його.
  • +/зменшує (згортає) правильний аргумент, використовуючи +. (Ми додаємо 0 і 1.)

2
Це не порушує Built-in base conversion functionsконтрант?
Гарет

Ого! Пропустив того.
Dillon Cower

Гах! Думав, що я даю собі шанс на боротьбу зі своєю програмою J! :-) Хороша робота.
Гарет

@Gareth: Я не зрозумів, поки я не прочитав ваше пояснення, але моя відповідь майже однакова з вашою! Я думаю, що цього можна було б очікувати від APL та J. :)
Dillon Cower

11

Brainbool , 2

,.

Найрозумніше тлумачення, на мій погляд (і то , що більшість відповідей використання) «найбільшу кількість ваш мова здатна обробляти» це « саме велика кількість ваш язик нативної підтримує». Brainbool - це похідне від думок, яке використовує біти, а не байти, і приймає введення та вихід у двійкові ( 0та 1символи), а не кодові символи. Таким чином, найбільша кількість, що підтримується в основному 1, є найменшою 0, яка має ваги Хеммінга 1і 0відповідно.

Brainbool був створений у 2010 році, повідомляє Esolang.


9
Я знав, що воно, мабуть, існувало, але мені знадобилася година сортування по похідних Brainfuck на Esolang, щоб знайти Brainbool.
lirtosiast

8

J, 13 символів

(+ кількість цифр у кількості)

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

Використання: замініть nв програмі число, яке потрібно протестувати.

Приклади:

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

Напевно, існує спосіб їх перестановки, щоб число можна було розмістити на початку чи в кінці, але це мій перший запис J, і голова болісно болить зараз.

Пояснення (головним чином, щоб я це розумів у майбутньому)

i.32 - створює масив чисел 1 до 32

2^ - перетворює список у повноваження двох 1 до 4294967296

n% - ділить номер введення на кожен елемент у списку

<. - округляє всі результати ділення до наступного цілого числа

2|- те саме, що %2в більшості мов - повертає 0, якщо парне і 1, якщо непарне

+/ - підсумовує елементи зі списку (які зараз лише 1 або 0)


Я з радістю підтверджую це, як тільки він прочитає з stdin (або будь-якого іншого еквівалента J).
Стівен Румбальський

Найкраще, що я міг зробити, я думаю (можливо, залежно від з'ясування способу) - перемістити вхід на кінець програми. Типовий вхід не згадується в запитанні?
Гарет

Вибачте за те, що не вказали спосіб введення. Зараз було б несправедливо змінювати правила, тому я прийму це. Я згадаю про це наступного разу!
pimvdb

@pimvdb Немає проблем, це не була скарга. Я думаю, що з програмами J, хоча все, що ви можете зробити, це визначити дієслово, яке працює на введеному йому вході. Не впевнений, як я переставив це, щоб це зробити. Можливо, JB або хтось із інших експертів J може допомогти мені у цьому ...
Гарет

... і прочитавши ще трохи, я бачу, що я зовсім помилявся щодо стандартного введення.
Гарет

8

Brainfuck, 53 символи

Для цього не було обов'язкового рішення Brainfuck, тому я зробив це:

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

Бере число з комірки 1 і додає результат у комірку 6.

Непровідна та коментована версія:

[  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 символ

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

Примітка. У моїй іншій відповіді використовується лямбда та рекурсія, і ця використовує цикл час. Я думаю, що вони досить різні, щоб отримати дві відповіді.


6

Рубі, 38 символів

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

Ще одне рішення з використанням рубіну та того ж рекурсивного підходу, що і Стівен.


5

GolfScript, 17 16 символів

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

Редагувати: нова версія зберігає 1 символ, використовуючи операцію зі списком, а не складку (оригінальна версія була ~{.2%\2/.}do]{+}*, версія прямого рахунку:) ~0\{.2%@+\2/.}do;.


5

С, 45

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

Тут нічого особливого для гольфу в C: неявний тип повернення, неявний цілочисельний тип параметрів.


4

Python 2.6, 45 символів

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

1
Можна скоротити на два символи, використовуючи defзамість лямбда.
Конрад Рудольф

1
@KonradRudolph: Насправді ви втрачаєте перевагу, коли включаєте заяву про повернення.
Стівен Румбальський

На жаль, я це забув. Дурний.
Конрад Рудольф

Вам це не потрібно print b(input()). Прийнятно повернути значення і прийняти "введення" як аргументи для функцій.
caird coinheringaahing

4

Perl, 45 43 36 Персонажі

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

Дякуємо Говарду за 45-> 43 та користувачеві606723 за 43-> 36.


Ви можете використовувати, $n=int($n/2)які 2 символи коротші.
Говард

Ми впевнені, що нам потрібен int ()? $n=<>;while($n){$_+=$n%2;$n/=2}printЦе триватиме циклічність, поки $ n / 2 нарешті не наблизиться до 0, але нас це хвилює? ;)
user606723

@ user606723 Я просто спробував це, і, здається, працює чудово, принаймні для кожного випадку до 1000.
PhiNotPi

3

Perl, 30 символів

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

На основі рішення PhiNotPi , з деяким додатковим гольфом. Запустіть, perl -M5.010щоб увімкнути функцію Perl 5.10 say.


Чи робить $=спеціальна змінна щось особливе у вашій програмі, чи це просто чергова звичайна змінна?
PhiNotPi

2
@PhiNotPi: $=приймає лише цілі значення, тому його використання економить мені int.
Ільмарі Каронен

Чи не повинен аргумент командного рядка бути частиною рахунку знаків?
Soham Chowdhury

@SohamChowdhury: не за цією метапотоком .
Ільмарі Каронен

3

Лист звичайний, 12 чол

(припускаючи ім'я змінної 1 char - тобто: 11 + число довжини)

Це не основна функція перетворення, тому вона повинна працювати:

(logcount x)

Приклади:

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

(Використання GNU CLISP.)


Гм ну, не зовсім те, що я мав на увазі, щоб побачити як відповідь :) Я не думаю, що я можу це прийняти. Це в основному лише інший випадок цього .
pimvdb

3

C, 61 60 57 53 символів

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

Тіло функції лише 38 символів. Редагувати : видалено побітовий оператор Редагувати : вивести printfз циклу, як запропоновано в коментарях Редагувати : перейти на декларацію K&R; Крім того, це вже не є специфічним для С99


Бачу побито !!!
Джоаніс

Вибачте, але оператор AND також вважається оператором побітових операцій.
pimvdb

@ M. Joanis: так, дякую за те, що помітили. Виправлено.
sam hocevar

1
Я думаю, що ти можеш пощадити кілька символів, якби ти перейшов на K&R C. Якщо з цим все гаразд.
JB

Ви можете скоротити це на чотири символи, перемістивши printf з циклу.
Марина

3

постійний струм - 26 символів

Це досить довго, в основному через відсутність контурних конструкцій у dc.

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

Продовжує додавати модуль 2 числа і ділити число на, поки воно не досягне нуля. Може обробляти довільно довгі цілі числа.

Приклад:

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

3

C, 66 символів

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

Примітка: потрібен компілятор, сумісний з gcc або gcc (наприклад, ICC, clang).

Для деяких процесорів __builtin_popcountкомпілюється в одну інструкцію (наприклад, POPCNTна x86).


Чи правильно, що __builtin_popcountнасправді просто реалізує підрахунок 1s? Якщо так, хоча це не зовсім неправильно за правилами, я, чесно кажучи, не вважаю, що це справедливий запис.
pimvdb

Ви, ймовірно, повинні вказати це у запитанні, якщо ви хочете заборонити записи, які використовують переваги вбудованих можливостей певної мови чи компілятора.
Пол Р.

Це не є законним C ++, оскільки в C ++ ви не можете опустити тип повернення на основний, а також використовувати printfбез попереднього включення.
celtschk

@celtschk: Справедлива точка - відредагованоC++
Paul R

2

JavaScript, 78 72 71 символ

Я опублікую своє початкове рішення, яке я придумав, перш ніж публікувати питання. Відповідь на JavaScript вже є набагато кращою :)

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/

Ідея походить від певних «карт читання розуму», які дозволяють отримати номер, який має на увазі хтось інший, показуючи їм картки та дозволяючи їм сказати, на яких картках видно їх кількість.

Це працює, тому що кожне число є унікальною комбінацією 1s / 0s у двійковій формі . Моє рішення перевіряє, на яких "картках" число очевидно, щоб визначити, скільки1s it has. It's just not very efficient, though...

Я знайшов цей документ, який окреслює техніку читання розуму.



2

PHP, 57

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

This assumes that $n holds the value to be tested.

PHP, 55 (alternative solution)

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

Again, this assumes that $n holds the value to be tested. This is an alternative because it uses the or-operator to floor the input.

Both solutions work and do not cause notices.


2

Ocaml, 45 characters

Based on @Leah Xue's solution. Three spaces could be removed and it's sligthly shorter (~3 characters) to use function instead of if-then-else.

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


1

Scala, 86 characters

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

Usage: scala O 56432



1

R, 53 characters

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

Examples:

> 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

If inputting the number is not part of the character count, then it is 43 characters:

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

with test cases

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


1

Scheme

I polished the rules a bit to add to the challenge. The function doesn't care about the base of the number because it uses its own binary scale. I was inspired by the way analog to numeric conversion works. I just use plain recursion for this:

(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

Isn't reading a number into binary or printing the number from binary a "builtin base conversion function", thus invalidating every answer above that prints an integer? If you permit reading and printing an integer, like almost all the above answers do, then I'll make claims using a builtin popcount function :

Haskell, 50

There was a popCount routine added to the Data.Bits module for GHC v7.2.1/v7.4.1 this summer (see tickets concerning the primop and binding).

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

I cannot beat the above Python and Perl scores using their GMPY or GMP::Mpz modules for GMP sadly, although GMP does offer a popcount function too.


1

JavaScript, 49 47 45 42 bytes

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

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

Edit 1: remove q and use ~~ for rounding, save 2 chars.

Edit 2: use |0 rounding operator instead of ~~ to save parentheses (2 chars).

Edit 3: simplify n>0 to n and combine with n=n/2|0 to make entire condition; now have wasted statement space :(


3
Isn't the |0 a bitwise operator?
Vilx-

Technically yes. But i'm using it purely to round to the nearest int, so I'm not getting any bit-wise benefit :)
mellamokb

Smells like bending the rules to me... but I'm not the judge.
Vilx-

Input 1 gives output 0.
Atreys

1
| is bitwise operator... it is disallowed. Time to do Math.round :-)
Jamie

1

Java 7, 36 bytes

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

Because of course this, of all things, is something that Java has a builtin for...


Doesn't this fit under "built-in base-conversion functions", which are banned?
FlipTack

@Flp.Tkc I'm not actually doing base-conversion. I have no idea how bitCount operates under the hood.
Poke

this seems like just using a bulitin to do the job, but ok...
FlipTack

@Flp.Tkc That's... exactly what it is? I'm even including all required libraries (there aren't any). This is demonstrating the strength of the language! related meta
Poke

1

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

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

TI-Basic is a tokenized language, all tokens but remainder( are one-byte, remainder is two


Welcome to the site!
James

1

PHP, 36 bytes

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

Assumes $n is the number to be tested, shows a PHP Notice for $o, and doesn't exactly work when $n is 0 (outputs nothing).

PHP, 53 bytes

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

Accepts command-line input, doesn't show a PHP Notice, and outputs correctly for 0.


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