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

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).

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.


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)


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
  [-<<<<+>>>>]
  <<<<
]

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.


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.


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


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.


4

Python 2.6, 45 znaków

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

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.


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.


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.)


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


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

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).


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.


2

Haskell (60 znaków)

f n=sum[1|x<-[0..n],odd$n`div`2^x]
main=interact$show.f.read

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ń.


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))  


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



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

1

OCaml, 52 znaki

let rec o x=if x=0 then 0 else (x mod 2) + (o (x/2))

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))])))

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 .


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 :(


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 ...


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(są jednobajtowe , reszta to dwa


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.


Witamy na stronie! :)
— James
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.