Gibt die Anzahl der Einsen in einer Binärzahl ohne Verwendung von bitweisen Operatoren aus

14

Beschreibung

Gib bei gegebener Zahl die Anzahl der 1s in binärer Darstellung aus.

Eingang

Eine Zahl >= 0in Basis 10, die die höchste Zahl, die Ihre Sprache verarbeiten kann, nicht überschreitet.

Ausgabe

Der Betrag von 1s in binärer Darstellung.

Gewinnbedingung

Der kürzeste Code gewinnt.

Nicht erlaubt

  • Bitweise Operatoren. Andere Operatoren wie Addition und Multiplikation sind zulässig.
  • Eingebaute Basisumwandlungsfunktionen.

Beispiele

Input:     Ouput:

56432      8


Input:     Output:

45781254   11


Input:     Output:

0          0
pimvdb
quelle
Sind Funktionen erlaubt? Ich möchte eine Java-Lösung machen, aber das Schreiben von vollständigem Code ist zu mühsam ...: /
HyperNeutrino
1
Ich nehme an, ich werde Wise nicht für diese Herausforderung verwenden ... :)
MildlyMilquetoast

Antworten:

16

APL, 9 12 Zeichen

+/2|⌊⎕÷2*⍳32

Dies setzt voraus, dass der Interpreter 32-Bit-Ganzzahlen verwendet und diese ⎕IOauf 0 gesetzt sind (was bedeutet, dass monadisch mit 0 anstatt mit 1 beginnt). Ich habe die 32-Bit-Version von Dyalog APL verwendet .

Erklärung von rechts nach links:

  • ⍳32erzeugt einen Vektor der ersten 32ganzen Zahlen (da ⎕IO0 ist, beginnt dieser Vektor mit 0).
  • *ist die Potenzfunktion. In diesem Fall generiert 2es die Potenz jedes Elements des Vektors, der als rechtes Argument angegeben wird.
  • ÷ist die Division durch Funktion. Es gibt uns (ausgewertete Benutzereingaben) geteilt durch jedes Element des Vektors zu seiner Rechten (jede Zweierpotenz).
  • Fußböden jedes Element des Arguments auf der rechten Seite.
  • 2|gibt uns den Rest jedes Elements von zu seiner Rechten geteilt durch 2.
  • /reduziert (faltet) sein rechtes Argument mit der Funktion nach links +,.

Nicht mehr ganz 9 Zeichen. :(

Alte, regelwidrige Version:

+/⎕⊤⍨32/2

Erklärung von rechts nach links:

  • 32/2: Replizieren 2, 32mal.
  • pendelt die dyadische Funktion nach links, was in diesem Fall (dh X⊤⍨Yäquivalent zu Y⊤X) ist.
  • ist die Codierungsfunktion. Es codiert die Ganzzahl rechts in der Basis links davon. Beachten Sie, dass aufgrund des Pendeloperators das rechte und das linke Argument vertauscht werden. Die Basis wird daher für die Anzahl der erforderlichen Stellen wiederholt 32/2.
  • ist eine niladische Funktion, die Benutzereingaben akzeptiert und auswertet.
  • +/reduziert (faltet) sein rechtes Argument mit +. (Wir addieren die Nullen und Einsen.)
Dillon Cower
quelle
2
Bricht das nicht die Built-in base conversion functionsKontraktion?
Gareth
Hoppla! Habe das verpasst.
Dillon Cower
Gah! Dachte, ich hätte mir mit meinem J-Programm eine Chance zum Kämpfen gegeben! :-) Gut gemacht.
Gareth
@Gareth: Ich habe es erst bemerkt, als ich deine Erklärung gelesen habe, aber meine Antwort ist ziemlich identisch mit deiner! Ich denke, das kann man von APL und J. erwarten. :)
Dillon Cower
11

Brainbool , 2

,.

Die vernünftigste Interpretation, meiner Meinung nach (und was den meisten Antworten verwenden) von „höchster Zahl Ihrer Sprache ist in der Lage zu handhaben “ ist „größte Zahl Ihrer Sprache nativ unterstützt“. Brainbool ist ein Brainfuck-Derivat, das Bits anstelle von Bytes verwendet und Eingaben und Ausgaben in Binärform ( 0und 1Zeichen) anstelle von Zeichencodes vornimmt. Die größte nativ unterstützt Zahl ist daher 1, und die kleinste ist 0, die Hamming - Gewichte haben 1und 0jeweils.

Brainbool wurde laut Esolang im Jahr 2010 gegründet.

Lirtosiast
quelle
9
Ich wusste, dass es das gegeben haben musste, aber ich brauchte eine Stunde, um die Brainfuck-Derivate auf Esolang zu durchsuchen und Brainbool zu finden.
Lirtosiast
8

J, 13 Zeichen

(+ die Anzahl der Ziffern in der Nummer)

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

Verbrauch: ersetzen Sie das n im Programm durch die zu testende Nummer.

Beispiele:

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

Es gibt wahrscheinlich eine Möglichkeit, dies neu zu ordnen, damit die Nummer am Anfang oder Ende platziert werden kann, aber dies ist mein erster J-Eintrag und mein Kopf tut jetzt leicht weh.

Erläuterung (hauptsächlich, damit ich es in Zukunft verstehe)

i.32 - Erstellt ein Array mit den Zahlen 1 bis 32

2^ - verwandelt die Liste in Zweierpotenzen 1 bis 4294967296

n% - teilt die eingegebene Nummer durch jedes Element in der Liste

<. - rundet alle Divisionsergebnisse auf die nächste Ganzzahl ab

2|- wie %2in den meisten Sprachen - liefert 0 wenn gerade und 1 wenn ungerade

+/ - summiert die Elemente in der Liste (die jetzt nur 1s oder 0s sind)

Gareth
quelle
Ich freue mich, dies zu verbessern, sobald es von stdin (oder was auch immer J hat) liest.
Steven Rumbalski
Das Beste, was ich tun kann (vielleicht, je nachdem, wie), ist die Eingabe an das Ende des Programms zu verschieben. Standardeingabe wird in der Frage jedoch nicht erwähnt?
Gareth
Es tut mir leid, dass ich die Art der Eingabe nicht angegeben habe. Es wäre unfair, die Regeln jetzt zu ändern, also akzeptiere ich diese. Ich werde es beim nächsten Mal erwähnen!
pimvdb
@pimvdb Kein Problem, es war keine Beschwerde. Ich denke, mit J-Programmen können Sie nur ein Verb definieren, das auf die angegebene Eingabe angewendet wird. Ich bin mir nicht sicher, wie ich das ändern soll, um das zu tun. Vielleicht könnte mir JB oder einer der anderen J-Experten dabei helfen ...
Gareth
... und nachdem ich mehr gelesen habe, sehe ich jetzt, dass ich mich bei der Standardeingabe völlig geirrt habe.
Gareth
8

Brainfuck, 53 Zeichen

Diesem fehlte eine obligatorische Brainfuck-Lösung, daher habe ich diese erstellt:

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

Übernimmt die Nummer aus Zelle 1 und fügt das Ergebnis in Zelle 6 ein.

Nicht registrierte und kommentierte Version:

[  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
  [-<<<<+>>>>]
  <<<<
]
Kopieren
quelle
6

Python 2.6, 41 Zeichen

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

Anmerkung: Meine andere Antwort verwendet Lambda und Rekursion und diese verwendet eine while-Schleife. Ich denke, sie sind unterschiedlich genug, um zwei Antworten zu rechtfertigen.

Steven Rumbalski
quelle
6

Ruby, 38 Zeichen

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

Eine andere Lösung mit Ruby und dem gleichen rekursiven Ansatz wie Steven.

Howard
quelle
5

GolfScript, 17 16 Zeichen

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

Bearbeiten: Neue Version speichert 1 Zeichen, indem Listenoperation anstelle von Falz verwendet wird (ursprüngliche Version war ~{.2%\2/.}do]{+}*, direkte Zählversion:) ~0\{.2%@+\2/.}do;.

Howard
quelle
5

C 45

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

Hier ist nichts Besonderes für das Golfen in C: impliziter Rückgabetyp, impliziter ganzzahliger Typ für Parameter.

Herr Lama
quelle
4

Python 2.6, 45 Zeichen

b=lambda n:n and n%2+b(n/2) 
print b(input())
Steven Rumbalski
quelle
1
Kann durch Verwendung defeines Lambdas um zwei Zeichen gekürzt werden .
Konrad Rudolph
1
@KonradRudolph: Tatsächlich verlieren Sie den Vorteil, sobald Sie die return-Anweisung einfügen.
Steven Rumbalski
Ups, das habe ich vergessen. Blöd.
Konrad Rudolph
Das brauchst du nicht print b(input()). Es ist akzeptabel, den Wert zurückzugeben und "input" als Argumente für Funktionen zu verwenden.
Caird Coinheringaahing
4

Perl, 45 43 36 Zeichen

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

Vielen Dank an Howard für 45-> 43 und an User606723 für 43-> 36.

PhiNotPi
quelle
Sie könnten $n=int($n/2)die 2 kürzeren Zeichen verwenden.
Howard
Sind wir sicher, dass wir die int () brauchen? $n=<>;while($n){$_+=$n%2;$n/=2}printDies wird so lange wiederholt, bis $ n / 2 endlich nahe genug bei 0 angelangt ist, aber kümmert es uns? ;)
user606723 30.12.11
@ user606723 Ich habe das gerade ausprobiert und es scheint perfekt zu funktionieren, zumindest für jeden Fall bis zu 1000.
PhiNotPi
3

Perl, 30 Zeichen

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

Basierend auf der PhiNotPi-Lösung , mit etwas mehr Golf. Führen Sie mit aus perl -M5.010, um die Perl 5.10- sayFunktion zu aktivieren .

Ilmari Karonen
quelle
Tut die $=spezielle Variable etwas Besonderes in Ihrem Programm oder ist es nur eine gewöhnliche Variable?
PhiNotPi
2
@PhiNotPi: Nimmt $=nur ganzzahlige Werte an int.
Ilmari Karonen
Sollte das Befehlszeilenargument nicht Teil der Zeichenanzahl sein?
Soham Chowdhury
@SohamChowdhury: Nicht für diesen Meta-Thread .
Ilmari Karonen
3

Common Lisp, 12 Zeichen

(unter der Annahme eines 1-Zeichen-Variablennamens - dh: 11 + Nummernlänge)

Es ist keine Basiskonvertierungsfunktion, daher sollte es funktionieren:

(logcount x)

Beispiele:

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

(Mit GNU CLISP.)

Joanis
quelle
Hm na ja, nicht genau das, was ich als Antwort sehen wollte :) Ich glaube nicht, dass ich das akzeptieren kann. Es ist im Grunde nur ein weiterer Fall von diesem .
pimvdb
3

C 61 60 57 53 Zeichen

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

Der Funktionskörper ist nur 38 Zeichen. Bearbeiten : Bitweiser Operator entfernt Bearbeiten : printfAus der Schleife entfernen, wie in den Kommentaren vorgeschlagen Bearbeiten : Zur K & R-Deklaration wechseln; Auch dies ist nicht mehr C99-spezifisch

sam hocevar
quelle
Ich sehe bitweise !!!
Joanis
Es tut mir leid, aber der AND-Operator zählt auch als bitweiser Operator.
Pimvdb
@ M.Joanis: duh, danke fürs mitbekommen. Fest.
Sam Hocevar
1
Ich denke, Sie könnten ein paar Zeichen sparen, wenn Sie zu K & R C wechseln. Wenn Sie damit einverstanden sind.
JB
Sie können dies um vier Zeichen verkürzen, indem Sie den Ausdruck aus der Schleife herausziehen.
marinus
3

Gleichstrom - 26 Zeichen

Dies ist ziemlich lang, hauptsächlich wegen des Fehlens von Schleifenkonstrukten in dc.

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

Addiert das Modulo 2 der Zahl und dividiert die Zahl durch bis, bis sie Null erreicht. Kann mit beliebig langen ganzen Zahlen umgehen.

Beispiel:

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

C, 66 Zeichen

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

Hinweis: Erfordert gcc oder gcc-kompatiblen Compiler (zB ICC, Clang).

__builtin_popcountKompiliert für einige CPUs zu einer einzigen Anweisung (zB POPCNTauf x86).

Paul R
quelle
Ist es richtig, dass __builtin_popcounttatsächlich nur das Zählen von 1s selbst implementiert wird ? Wenn ja, obwohl es nicht streng nach den Regeln falsch ist, halte ich das ehrlich gesagt nicht für einen fairen Einstieg.
pimvdb
Sie sollten dies wahrscheinlich in der Frage festlegen, wenn Sie keine Einträge zulassen möchten, die die integrierten Funktionen einer bestimmten Sprache oder eines bestimmten Compilers nutzen.
Paul R
Dies ist kein legales C ++, da Sie in C ++ den Rückgabetyp für main nicht weglassen oder printfohne vorheriges Include verwenden können.
Celtschk
@celtschk: fair point - herausgearbeitetC++
Paul R
2

JavaScript, 78 72 71 Zeichen

Ich werde meine ursprüngliche Lösung posten, die ich mir ausgedacht habe, bevor ich auch die Frage stelle. Es gibt aber schon eine viel bessere JavaScript-Antwort :)

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/

Die Idee kommt von bestimmten "Gedankenlesekarten", die es Ihnen ermöglichen, die Nummer zu ermitteln, die jemand anderes im Sinn hat, indem Sie ihm Karten zeigen und sagen lassen, auf welchen Karten seine Nummer ersichtlich ist.

Es funktioniert, weil jede Zahl eine eindeutige Kombination von 1s / 0s in der Binärdatei ist. Meine Lösung überprüft, auf welchen "Karten" die Nummer ersichtlich ist, um festzustellen, wie viele1 s sie hat. Es ist nur nicht sehr effizient, obwohl ...

ich fand dieses Dokument gefunden, das die Gedankenlesetechnik beschreibt.

pimvdb
quelle
2

Haskell (60 Zeichen)

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

PHP, 57

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

Dies setzt voraus, dass $n der zu testende Wert enthalten ist.

PHP, 55 (alternative Lösung)

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

Dies setzt wiederum voraus, dass $nder zu testende Wert vorliegt. Dies ist eine Alternative, da der Operator or verwendet wirdfloor die Eingabe verwendet wird.

Beide Lösungen funktionieren und verursachen keine Auffälligkeiten.

Arjan
quelle
2

Ocaml, 45 Zeichen

Basierend auf der Lösung von @Leah Xue. Drei Leerzeichen könnten entfernt werden, und es ist etwas kürzer (~ 3 Zeichen), um die Funktion anstelle von if-then-else zu verwenden.

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

Mathematica 26

Count[n~IntegerDigits~2,1]
DavidC
quelle
1

Scala, 86 Zeichen

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

Verwendung: scala O 56432

Gareth
quelle
1

D (70 Zeichen)

int f(string i){int k=to!int(i),r;while(k){if(k%2)r++;k/=2;}return r;}
Ratschenfreak
quelle
1

R, 53 Zeichen

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

Beispiele:

> 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

Wenn die Eingabe der Nummer nicht Teil der Zeichenanzahl ist, sind es 43 Zeichen:

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

mit Testfällen

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

OCaml, 52 Zeichen

let rec o x=if x=0 then 0 else (x mod 2) + (o (x/2))
Leah Xue
quelle
1

Planen

Ich habe die Regeln ein wenig überarbeitet, um die Herausforderung zu erweitern. Die Funktion kümmert sich nicht um die Basis der Zahl, da sie eine eigene Binärskala verwendet. Ich war inspiriert von der Art und Weise, wie analoge numerische Konvertierungen funktionieren. Ich benutze dafür einfach die Rekursion:

(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
quelle
1

Ist das Lesen einer Zahl in eine Binärzahl oder das Drucken der Zahl aus einer Binärzahl nicht eine "eingebaute Basiskonvertierungsfunktion", die jede Antwort darüber ungültig macht, die printeine Ganzzahl ist? Wenn Sie das Lesen und Drucken einer Ganzzahl zulassen, wie es bei fast allen obigen Antworten der Fall ist , werde ich Behauptungen mit einer eingebauten popcountFunktion aufstellen :

Haskell, 50

In diesem Sommer wurde popCountdem Data.BitsModul für GHC v7.2.1 / v7.4.1 eine Routine hinzugefügt (siehe Tickets zu Primop und Bindung ).

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

Ich kann die obigen Python- und Perl-Scores mit ihren GMPYoder GMP::MpzModulen für GMP leider nicht übertreffen , obwohl GMP auch eine Popcount-Funktion bietet .

Jeff Burdges
quelle
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: entfernen qund ~~zum Runden verwenden, 2 Zeichen speichern.

Edit 2: Verwenden Sie den |0Rundungsoperator ~~, um Klammern (2 Zeichen) zu speichern.

Bearbeiten 3: Vereinfachung n>0zu nund verbinden sich mit n=n/2|0bis zu ganzem Zustand zu machen; Jetzt haben Statement-Platz verschwendet :(

mellamokb
quelle
3
Ist das nicht |0ein bitweiser Operator?
Vilx
Technisch ja. Aber ich verwende es nur, um auf das nächste int zu runden, also bekomme ich keine bitweisen Vorteile :)
mellamokb
Es riecht so, als würde ich die Regeln biegen ... aber ich bin nicht der Richter.
Vilx
Eingang 1 gibt Ausgang 0.
Atreys
1
|ist bitweiser Operator ... ist nicht erlaubt. Zeit zu tun Math.round:-)
Jamie
1

Java 7, 36 Bytes

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

Ausgerechnet dafür hat Java natürlich ...

Sack
quelle
Passt das nicht unter "Built-in Base-Conversion-Funktionen", die verboten sind?
FlipTack
@ Flp.Tkc Ich mache eigentlich keine Base-Konvertierung. Ich habe keine Ahnung, wie das bitCountunter der Haube funktioniert.
Poke
Dies scheint nur mit einem Bulitin, um die Arbeit zu erledigen, aber ok ...
FlipTack
@ Flp.Tkc Das ist ... genau das, was es ist? Ich schließe sogar alle benötigten Bibliotheken ein (es gibt keine). Dies zeigt die Stärke der Sprache! Verwandte Meta
Poke
1

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

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

TI-Basic ist eine Token-Sprache. Alle Token remainder(bestehen aus einem Byte , der Rest aus zwei

Pizzapants184
quelle
Willkommen auf der Seite!
DJMcMayhem
1

PHP, 36 Bytes

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

Angenommen, $nist die zu testende Zahl, zeigt einen PHP-Hinweis für $ound funktioniert nicht genau, wenn $n0 ist (gibt nichts aus).

PHP, 53 Bytes

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

Akzeptiert Befehlszeilen-Eingaben, zeigt keine PHP-Benachrichtigung an und gibt für 0 korrekt aus.

jstnthms
quelle
Willkommen auf der Seite! :)
DJMcMayhem