Wydrukuj liczbę jedynek w liczbie binarnej bez użycia operatorów bitowych

14

Opis

Biorąc pod uwagę liczbę, wypisz jej liczbę 1w reprezentacji binarnej.

Wejście

Liczba >= 0w bazie 10, która nie przekroczy najwyższej liczby, którą Twój język jest w stanie obsłużyć.

Wynik

Ilość 1s w reprezentacji binarnej.

Warunki wygranej

Najkrótszy kod wygrywa.

Niedozwolone

  • Operatory bitowe. Inne operatory, takie jak dodawanie i mnożenie, są dozwolone.
  • Wbudowane podstawowe funkcje konwersji.

Przykłady

Input:     Ouput:

56432      8


Input:     Output:

45781254   11


Input:     Output:

0          0
pimvdb
źródło
Czy funkcje są dozwolone? Chcę stworzyć rozwiązanie Java, ale pisanie pełnego kodu jest zbyt żmudne ...: /
HyperNeutrino 13.02.2016
1
Chyba nie
użyję

Odpowiedzi:

16

APL, 9 12 znaków

+/2|⌊⎕÷2*⍳32

Zakłada się, że interpreter używa 32-bitowych liczb całkowitych i ⎕IOjest ustawiony na 0 (co oznacza, że ​​monadyczny zaczyna się od 0, a nie od 1). Użyłem 32-bitowej wersji Dyalog APL .

Objaśnienie, od prawej do lewej:

  • ⍳32 generuje wektor pierwszego 32 liczb całkowitych (jak wyjaśniono wcześniej, ponieważ ⎕IOwynosi 0, ten wektor zaczyna się od 0).
  • *jest funkcją mocy. W tym przypadku generuje2 do potęgi każdego elementu wektora podanego jako jego właściwy argument.
  • ÷jest funkcją podzieloną przez. Daje nam (ocenione dane wejściowe użytkownika) podzielone przez każdy element wektora po jego prawej stronie (każda potęga dwóch).
  • podłoga każdego elementu argumentu po jego prawej stronie.
  • 2| daje nam resztę każdego elementu po prawej stronie podzieloną przez 2 .
  • / zmniejsza (fałduje) swój prawy argument za pomocą funkcji po lewej, + .

Już niecałe 9 znaków. :(

Stara, przełomowa wersja:

+/⎕⊤⍨32/2

Objaśnienie, od prawej do lewej:

  • 32/2: Replikacja 2,32 razy.
  • zamienia funkcję dyadyczną po jej lewej stronie, która w tym przypadku jest (tzn. X⊤⍨Yjest równoważna zY⊤X ).
  • jest funkcją kodowania. Koduje liczbę całkowitą po jej prawej stronie w podstawie podanej po jej lewej stronie. Zauważ, że z powodu operatora dojazdów argumenty prawy i lewy są przełączane. Stąd podstawa jest powtarzana dla wymaganej liczby cyfr32/2 .
  • to funkcja niladyczna, która akceptuje dane wejściowe użytkownika i ocenia je.
  • +/zmniejsza (fałduje) odpowiedni argument za pomocą +. (Dodajemy 0 i 1).
Dillon Cower
źródło
2
Czy to nie łamie przeciwności Built-in base conversion functions?
Gareth,
Ups! Nie trafiłem tego.
Dillon Cower,
Gah! Myślałem, że dałem sobie szansę na walkę z moim programem J! :-) Dobra robota.
Gareth
@Gareth: Dopiero teraz przeczytałem twoje wyjaśnienie, ale moja odpowiedź jest prawie identyczna z twoją!
Wydaje
11

Brainbool , 2

,.

Moim zdaniem najbardziej rozsądną interpretacją (i tego, z czego korzysta większość odpowiedzi) „największej liczby, jaką Twój język jest w stanie obsłużyć”, jest „największa liczba, którą Twój język obsługuje natywnie ”. Brainbool to pochodna od pieprzenia mózgów, która używa bitów zamiast bajtów i pobiera dane wejściowe i wyjściowe w postaci binarnej ( 0i 1znaków), a nie kodów znaków. Dlatego jest to największa obsługiwana liczba natywnie1 , a najmniejszy 0, który ma wagi Hamminga1 i 0odpowiednio.

Brainbool został stworzony w 2010 roku, zgodnie z Esolang.

lirtosiast
źródło
9
Wiedziałem, że musiał istnieć, ale zajęło mi godzinę sortowanie pochodnych Brainfuck na Esolang, aby znaleźć Brainbool.
lirtosiast
8

J, 13 znaków

(+ liczba cyfr w liczbie)

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

Sposób użycia: zastąp nw programie numerem do przetestowania.

Przykłady:

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

Prawdopodobnie istnieje sposób na zmianę tego ustawienia, aby numer mógł być umieszczony na początku lub na końcu, ale to jest mój pierwszy wpis w J i głowa trochę mnie teraz boli.

Wyjaśnienie (głównie po to, aby je zrozumieć w przyszłości)

i.32 - tworzy tablicę liczb od 1 do 32

2^ - zamienia listę w potęgi dwóch 1 do 4294967296

n% - dzieli numer wejściowy przez każdy element na liście

<. - zaokrągla wszystkie wyniki dywizji w dół do następnej liczby całkowitej

2|- tak samo jak %2w większości języków - zwraca 0, jeśli parzyste i 1, jeśli nieparzyste

+/ - sumuje pozycje na liście (które są teraz tylko 1s lub 0s)

Gareth
źródło
Z przyjemnością będę głosować za tym, gdy będzie czytać ze standardowego wejścia (lub innego odpowiednika J).
Steven Rumbalski
Myślę, że najlepsze, co mogę zrobić (może, w zależności od tego, jak to wymyślić), to przenieść dane wejściowe na koniec programu. Standardowe dane wejściowe nie są jednak wymienione w pytaniu?
Gareth,
Przepraszam, że nie określiłem sposobu wprowadzania danych. Zmiana zasad byłaby niesprawiedliwa, więc zaakceptuję tę. Wspomnę o tym następnym razem!
pimvdb
@pimvdb Nie ma problemu, to nie była skarga. Myślę, że w programach J wszystko, co możesz zrobić, to zdefiniować czasownik, który działa na danych wejściowych. Nie jestem jednak pewien, jak to zmienić. Może JB lub jeden z innych ekspertów J mógłby mi w tym pomóc ...
Gareth
... i po przeczytaniu czegoś więcej widzę, że całkowicie się myliłem co do standardowego wejścia.
Gareth
8

Brainfuck, 53 znaki

Brakowało obowiązkowego rozwiązania Brainfuck, więc zrobiłem to:

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

Pobiera liczbę z komórki 1 i umieszcza wynik w komórce 6.

Wersja niezarejestrowana i skomentowana:

[  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
  [-<<<<+>>>>]
  <<<<
]
Kopiuj
źródło
6

Python 2.6, 41 znaków

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

Uwaga: Moja druga odpowiedź używa lambda i rekurencji, a ta wykorzystuje pętlę while. Myślę, że są na tyle różne, że uzasadniają dwie odpowiedzi.

Steven Rumbalski
źródło
6

Ruby, 38 znaków

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

Inne rozwiązanie wykorzystujące ruby ​​i to samo rekurencyjne podejście jak Steven.

Howard
źródło
5

GolfScript, 17 16 znaków

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

Edycja: nowa wersja zapisuje 1 znak, używając operacji listy zamiast składania (pierwotna wersja to wersja z ~{.2%\2/.}do]{+}*bezpośrednim zliczaniem:) ~0\{.2%@+\2/.}do;.

Howard
źródło
5

C, 45

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

Nie ma tu nic specjalnego do gry w golfa w C: niejawny typ zwrotu, niejawny typ liczbowy dla parametrów.

Pan Llama
źródło
4

Python 2.6, 45 znaków

b=lambda n:n and n%2+b(n/2) 
print b(input())
Steven Rumbalski
źródło
1
Można go skrócić o dwa znaki, używając defzamiast lambda.
Konrad Rudolph,
1
@KonradRudolph: W rzeczywistości tracisz przewagę po dołączeniu instrukcji return.
Steven Rumbalski
Ups, zapomniałem o tym. Głupi.
Konrad Rudolph
Nie potrzebujesz print b(input()). Dopuszczalne jest zwrócenie wartości i przyjęcie „danych wejściowych” jako argumentów funkcji.
caird coinheringaahing
4

Perl, 45 43 36 znaków

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

Dzięki Howard za 45-> 43 i User606723 za 43-> 36.

PhiNotPi
źródło
Możesz użyć $n=int($n/2)2 znaków krótszych.
Howard,
Czy na pewno potrzebujemy int ()? $n=<>;while($n){$_+=$n%2;$n/=2}printTo będzie się powtarzać, dopóki $ n / 2 w końcu nie zbliży się wystarczająco do 0, ale czy nas to obchodzi? ;)
user606723,
@ user606723 Właśnie to wypróbowałem i wydaje się, że działa idealnie, przynajmniej w każdej sprawie do 1000.
PhiNotPi
3

Perl, 30 znaków

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

Oparty na rozwiązaniu PhiNotPi , z dodatkowym golfem. Uruchom za pomocą, perl -M5.010aby włączyć funkcję Perla 5.10 say.

Ilmari Karonen
źródło
Czy $=zmienna specjalna robi coś specjalnego w twoim programie, czy jest to tylko zwykła zmienna?
PhiNotPi
2
@PhiNotPi: $=przyjmuje tylko wartości całkowite, więc użycie go oszczędza mi int.
Ilmari Karonen,
Czy argument wiersza poleceń nie powinien być częścią liczby znaków?
Soham Chowdhury
@SohamChowdhury: Nie dla tego meta wątku .
Ilmari Karonen
3

Common Lisp, 12 znaków

(przyjmując nazwę zmiennej o 1 znaku - tj. 11 + długość liczby)

To nie jest podstawowa funkcja konwersji, więc powinna działać:

(logcount x)

Przykłady:

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

(Korzystanie z GNU CLISP.)

Joanis
źródło
Hm cóż, niezupełnie to, co miałem na myśli, aby zobaczyć jako odpowiedź :) Nie sądzę, że mogę to zaakceptować. Jest to w zasadzie tylko kolejny przypadek tego .
pimvdb
3

C, 61 60 57 53 znaków

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

Treść funkcji ma tylko 38 znaków. Edytuj : usunięto bitowego operatora Edytuj : printfwyjdź z pętli, jak sugerowano w komentarzach Edytuj : przełącz na deklarację K&R; nie jest to już specyficzne dla C99

sam hocevar
źródło
Widzę bitowe !!!
Joanis,
Przykro mi, ale operator AND również liczy się jako operator bitowy.
pimvdb
@ M.Joanis: duh, dzięki za zauważenie. Naprawiony.
sam hocevar
1
Myślę, że możesz oszczędzić kilka postaci, jeśli przejdziesz do K&R C. Jeśli nie masz nic przeciwko.
JB
Możesz to skrócić o cztery znaki, przesuwając printf poza pętlę.
marinus
3

dc - 26 znaków

Jest to dość długie, głównie z powodu braku konstrukcji pętli w dc.

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

Kontynuuje sumowanie modulo 2 liczby i dzielenie liczby przez, aż do osiągnięcia zera. Może obsługiwać dowolnie długie liczby całkowite.

Przykład:

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

C, 66 znaków

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

Uwaga: wymaga kompilatora gcc lub kompatybilnego z gcc (np. ICC, clang).

Dla niektórych procesorów __builtin_popcountkompiluje się do pojedynczej instrukcji (np. POPCNTNa x86).

Paul R.
źródło
Czy to prawda, że ​​w __builtin_popcountrzeczywistości po prostu implementuje liczenie 1samego s? Jeśli tak, chociaż nie jest to całkowicie niezgodne z zasadami, szczerze mówiąc, nie sądzę, aby było to uczciwe wejście.
pimvdb
Prawdopodobnie powinieneś to ustalić w pytaniu, jeśli chcesz zabronić wpisów korzystających z wbudowanych możliwości danego języka lub kompilatora.
Paul R
To nie jest legalne C ++, ponieważ w C ++ nie można pominąć typu zwrotu na main, ani używać printfbez wcześniejszego włączenia.
celtschk
@celtschk: fair point - zredagowałC++
Paul R
2

JavaScript, 78 72 71 znaków

Zamieszczę moje wstępne rozwiązanie, które wymyśliłem przed opublikowaniem pytania. Istnieje jednak znacznie lepsza odpowiedź 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/

Pomysł pochodzi z pewnych „kart do czytania w myślach”, które pozwalają uzyskać numer, który ma na myśli ktoś inny, pokazując im karty i pozwalając im powiedzieć, na których kartach ich liczba jest widoczna.

Działa, ponieważ każda liczba jest unikalną kombinacją 1s / 0s binarnie. Moje rozwiązanie sprawdza, które „karty” numer jest widoczny, aby ustalić, ile1 ma. To po prostu mało wydajne, chociaż ...

Znalazłem ten dokument, który opisuje technikę czytania w myślach.

pimvdb
źródło
2

Haskell (60 znaków)

f n=sum[1|x<-[0..n],odd$n`div`2^x]
main=interact$show.f.read
marinus
źródło
2

PHP, 57

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

Zakłada się, że $nzawiera wartość do przetestowania.

PHP, 55 (rozwiązanie alternatywne)

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

Ponownie zakłada się, że $nzawiera wartość do przetestowania. Jest to alternatywa, ponieważ używa operatora or-tofloor danych wejściowych.

Oba rozwiązania działają i nie powodują powiadomień.

Arjan
źródło
2

Ocaml, 45 znaków

Na podstawie rozwiązania @Leah Xue. Można usunąć trzy spacje i jest on nieco krótszy (~ 3 znaki), aby użyć funkcji zamiast if-then-else.

let rec o=function 0->0|x->(x mod 2)+(o(x/2))  
ReyCharles
źródło
2

Mathematica 26

Count[n~IntegerDigits~2,1]
DavidC
źródło
1

Scala, 86 znaków

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

Stosowanie: scala O 56432

Gareth
źródło
1

D (70 znaków)

int f(string i){int k=to!int(i),r;while(k){if(k%2)r++;k/=2;}return r;}
maniak zapadkowy
źródło
1

R, 53 znaki

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

Przykłady:

> 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

Jeśli wpisanie liczby nie jest częścią liczby znaków, to jest 43 znaków:

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

z przypadkami testowymi

> o(56432)
[1] 8
> o(45781254)
[1] 11
> o(0)
[1] 0
Brian Diggs
źródło
1

OCaml, 52 znaki

let rec o x=if x=0 then 0 else (x mod 2) + (o (x/2))
Leah Xue
źródło
1

Schemat

Trochę dopracowałem zasady, aby dodać do wyzwania. Funkcja nie dba o podstawę liczby, ponieważ używa własnej skali binarnej. Zainspirował mnie sposób, w jaki działa konwersja analogowa na numeryczną. Po prostu używam do tego zwykłej rekurencji:

(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
źródło
1

Czy wczytywanie liczby do pliku binarnego lub drukowanie numeru z pliku binarnego nie jest „wbudowaną funkcją konwersji bazy”, a tym samym unieważnia każdą odpowiedź powyżej printliczby całkowitej? Jeśli zezwalasz na odczytywanie i drukowanie liczb całkowitych, tak jak robią to prawie wszystkie powyższe odpowiedzi, wtedy zgłaszam roszczenia za pomocą wbudowanej popcountfunkcji :

Haskell, 50

Nie było popCountrutynowe dodana do Data.Bitsmodułu dla GHC v7.2.1 / v7.4.1 tego lata (patrz bilety dotycząca primop i wiążące ).

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

Niestety nie mogę pobić powyższych wyników w Pythonie i Perlu, używając ich modułów GMPYlub GMP::MpzGMP, chociaż GMP oferuje również funkcję popcount .

Jeff Burdges
źródło
1

JavaScript, 49 47 45 42 bajtów

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

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

Edycja 1: usuń qi użyj ~~do zaokrąglania, zapisz 2 znaki.

Edycja 2: użyj |0operatora zaokrąglania zamiast ~~zapisywać nawiasy (2 znaki).

Edycja 3: uprościć n>0do ni połączyć ze n=n/2|0aby całą sytuację; teraz zmarnowałem miejsce na wyciągi :(

mellamokb
źródło
3
Czy to nie |0operator bitowy?
Vilx
Technicznie tak. Ale używam go wyłącznie do zaokrąglenia do najbliższej int, więc nie dostaję żadnych
drobnych
Pachnie mi jak naginanie zasad ... ale nie jestem sędzią.
Vilx
Wejście 1 daje wynik 0.
Atreys
1
|jest operatorem bitowym ... jest niedozwolony. Czas na zrobienie Math.round:-)
Jamie
1

Java 7, 36 bajtów

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

Ponieważ, oczywiście, jest to coś, co Java ma wbudowane w ...

Szturchać
źródło
Czy to nie pasuje do „wbudowanych funkcji konwersji bazy”, które są zbanowane?
FlipTack,
@ Flp.Tkc Właściwie to nie robię konwersji bazy. Nie mam pojęcia, jak bitCountdziała pod maską.
Poke
wygląda na to, że po prostu wykorzystuję bulitin do wykonania zadania, ale ok ...
FlipTack
@ Flp.Tkc To jest ... dokładnie to, co to jest? Dołączam nawet wszystkie wymagane biblioteki (nie ma żadnych). To pokazuje siłę języka! powiązane meta
Poke
1

TI-Basic (TI-84 Plus CE), 30 bajtów

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

TI-Basic jest tokenizowanym językiem, wszystkie tokeny remainder(jednobajtowe , reszta to dwa

pizzapanty184
źródło
Witamy na stronie!
James
1

PHP, 36 bajtów

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

Zakłada, że $njest to liczba do przetestowania, pokazuje Powiadomienie PHP $oi nie działa dokładnie, kiedy$n is 0 (outputs nothing).

PHP, 53 bajty

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

Akceptuje dane wejściowe z wiersza poleceń, nie wyświetla powiadomienia PHP i wypisuje poprawnie dla 0.

jstnthms
źródło
Witamy na stronie! :)
James