Binär-Dezimal-Konverter

32

Binär-Dezimal-Konverter

Soweit ich sehen kann, gibt es keine einfache Herausforderung für die Konvertierung von Binärdaten in Dezimalzahlen.


Schreiben Sie ein Programm oder eine Funktion, die eine positive binäre Ganzzahl annimmt und deren Dezimalwert ausgibt.

Sie dürfen keine eingebauten Basisumwandlungsfunktionen verwenden. Ganzzahl-zu-Dezimal-Funktionen (z. B. eine Funktion, die 101010zu [1, 0, 1, 0, 1, 0]oder wird "101010") sind von dieser Regel ausgenommen und daher zulässig.

Regeln:

  • Der Code muss Binärzahlen bis zu dem höchsten numerischen Wert unterstützen, den Ihre Sprache unterstützt (standardmäßig).
  • Sie können festlegen, dass die Binärdarstellung führende Nullen enthält
  • Die Dezimalausgabe darf keine führenden Nullen enthalten.
  • Eingabe- und Ausgabeformate sind optional, zwischen den Ziffern dürfen jedoch keine Trennzeichen stehen. (1,0,1,0,1,0,1,0)ist kein gültiges Eingabeformat, aber beides 10101010und (["10101010"])sind.
    • Sie müssen die Eingabe in der "normalen" Richtung vornehmen. 1110ist 14nicht 7.

Testfälle:

1
1

10
2

101010
42

1101111111010101100101110111001110001000110100110011100000111
2016120520371234567

Diese Herausforderung hängt mit einigen anderen Herausforderungen zusammen, zum Beispiel mit dieser , dieser und dieser .

Stewie Griffin
quelle
Related
mbomb007
Muss die Ausgabe nicht signiert sein oder kann sie signiert werden? Kann die Ausgabe auch in beiden Bereichen signiert werden, wenn meine Sprache je nach Länge des Werts automatisch zwischen 32-Bit- und 64-Bit-Ganzzahlen wechselt? Es gibt zwei Binärwerte, die in Dezimalzahlen -1( 32 1'sund 64 1's) umgewandelt werden
Milch
Kann der Ausgang auch schwebend sein, muss er eine Ganzzahl sein?
Carcigenicate
@Carcigenicate Es muss eine Ganzzahl sein, es kann sich jedoch um einen beliebigen Datentyp handeln. Solange es round(x)==xdir gut geht :) 2.000wird die Ausgabe für akzeptiert 10.
Stewie Griffin
Oh wie süß. Vielen Dank.
Carcigenicate

Antworten:

56

Gelee , 5 Bytes

DḤ+¥/

Probieren Sie es online!

Erläuterung

Bildbeschreibung hier eingeben

Die Besetzung

  • Dist eine Monade (Funktion mit einem Argument): Ziffern, verwandeln sich 1234in [1, 2, 3, 4].

  • ist eine Monade, die ihr einziges Argument verdoppelt.

  • + ist eine Dyade (Funktion mit zwei Argumenten), die ihre linken und rechten Argumente hinzufügt.

Von da an wird es etwas knifflig.

Folgendes passiert zum Zeitpunkt der Analyse

  • D,, und +werden gelesen. Die Kette sieht aus wie [D, Ḥ, +].

  • Die nächsten beiden Zeichen sind Quick -Operatoren, die sich auf die bisher gelesenen Links (Funktionen) wie Postfix-Operatoren während der Analyse auswirken .

  • Wenn ¥gelesen wird, werden die letzten beiden Links angezeigt und durch einen Link ersetzt, der sich wie die Dyade verhält, die durch das Erstellen dieser Links erstellt wurde. So sieht die Kette jetzt aus [D, dyad(Ḥ+)].

  • Wenn /gelesen wird, das letzte Glied (das sollte eine Dyade sein) wird durch eine Monade knallt und ersetzt, faltet diese Dyade mit (intuitiv: f/nimmt eine Liste, ersetzt die Kommas in ihm mit f, und wertet das Ergebnis.)

  • Die letzte Kette sieht aus wie [D, fold(dyad(Ḥ+))]zwei Monaden.

Folgendes passiert zur Laufzeit

  • Die Eingabe (eine Zahl) wird implizit in den Arbeitswert (z. B. 101010) eingelesen .

  • Dwird ausgeführt, wobei der Arbeitswert durch seine Ziffern ( [1,0,1,0,1,0]) ersetzt wird.

  • fold(dyad(Ḥ+))wird ausgeführt, wobei der Arbeitswert durch ersetzt wird 1∗0∗1∗0∗1∗0, wo sich die Dyade befindet Ḥ+.

Also, was x∗ywertet aus?

  • In einer dyadischen Definition ist der Arbeitswert zunächst das linke Argument x.

  • , die Doppelmonade , verdoppelt diesen Wert. Der Arbeitswert ist jetzt 2x.

  • +, der Plus- Dyade, fehlt ein richtiges Argument, also ist dies ein Haken : ein spezielles syntaktisches Muster, in das das richtige Argument dieser Dyade eingefügt wird +. Dies ergibt 2x + yden endgültigen Arbeitswert, der zurückgegeben wird.

Der gesamte Ausdruck ergibt also:

1∗0∗1∗0∗1∗0 = 2×(2×(2×(2×(2×1+0)+1)+0)+1)+0
            = 32×1 + 16×0 + 8×1 + 4×0 + 2×1 + 1×0
            = 42
Lynn
quelle
10
Ihre Erklärungen werden immer besser :-)
Luis Mendo
2
Heh, ich denke du machst es von jetzt an? Das ist großartig, +1.
Erik the Outgolfer
4
Ich denke, dies ist das erste Stück Gelee, das ich je verstanden habe. +1!
Blue
Bravo. Ich verstehe tatsächlich, was ich anfangs für ein Durcheinander scheinbar zufälliger Charaktere hielt. Wunderbare Erklärung.
Schweinefisch
1
@ Mark Jelly hat eine eigene Codepage, mit der die Programme lesbar aussehen, aber die Programme können auch nur Bytestrings sein.
Lynn
20

Python 2, 49 37 31 30 Bytes

Dies wird nun eine Binärzahl in einer Dezimaldarstellung annehmen, da Python beliebig große Ganzzahlen verarbeiten kann.

b=lambda n:n and n%2+2*b(n/10)

danke an xnor für das speichern eines bytes :)

Der einfachste Weg, um zu sehen, wie dies funktioniert, besteht darin, eine Grundformel für die Konvertierung von Binärdaten in Dezimalzahlen zu sehen:

= 101010 
= 1*(2^5) + 0*(2^4) + 1*(2^3) + 0*(2^2) + 1*(2^1) + 0*(2^0)
= 1*32 + 0*16 + 1*8 + 0*4 + 1*2 + 0*1
= 42

Dies ist eine "Standard" -Konvertierungsmethode. Sie können die dritte Zeile folgendermaßen erweitern:

= ((((1*2 + 0)*2 + 1)*2 + 0)*2 + 1)*2 + 0

Und das ist im Wesentlichen das, was die rekursive Methode ist, die ich gemacht habe.

Alternative Lösungen, die ich hatte:

b=lambda n:n and n%10+2*b(n/10)
b=lambda n:n%10+2*(n and b(n/10))
b=lambda n:0if n<1else n%10+2*b(n/10)
b=lambda n:0**(n/10)or n%10+2*b(n/10)
b=lambda n,o=0:o*(n<'0')or b(n[1:],2*o+int(n[0]))
lambda j:sum(int(b)*2**a for a,b in enumerate(j,1))
Kade
quelle
6
Sie können n%5oder n%2statt n%10.
Xnor
@xnor Ah, nicht sicher, wie ich das verpasst habe! Danke :)
Kade
12

05AB1E , 6 Bytes

Code:

$¦v·y+

Nehmen wir zur Erläuterung das Beispiel 101010 . Wir beginnen mit der Nummer 1 (die durch die erste Ziffer dargestellt wird). Danach haben wir zwei Fälle:

  • Wenn die Ziffer eine 0 ist , multiplizieren Sie die Zahl mit 2.
  • Wenn die Ziffer eine 1 ist , multiplizieren Sie die Zahl mit 2 und addieren Sie 1.

Für den Fall 101010 wird also Folgendes berechnet:

  • 1 01010, beginne mit der Nummer 1 .
  • 1 0 1010, multiplizieren Sie mit zwei und erhalten Sie 2 .
  • 10 1 010, multiplizieren Sie mit zwei und addieren Sie eins, was zu 5 führt .
  • 101 0 10, multiplizieren Sie mit zwei und erhalten Sie 10 .
  • 1010 1 0, multiplizieren Sie mit zwei und addieren Sie eins, was zu 21 führt .
  • 10101 0 , multiplizieren mit zwei, was zu 42 führt , was das gewünschte Ergebnis ist.

Code Erklärung:

$         # Push 1 and input
 ¦        # Remove the first character
  v       # For each character (starting with the first)
   ·      #   Multiply the carry number by two
    y+    #   Add the current character (converted automatically to a number)

Verwendet die CP-1252- Codierung. Probieren Sie es online!

Adnan
quelle
Schön! (funktioniert nicht für 0, obwohl ich gerade bemerkt habe)
Emigna
@Emigna Ja, zum Glück muss Ihr Code nur für positive Binärzahlen funktionieren.
Adnan
Habe diesen Teil nicht mal gesehen. Sehr schön dann :)
Emigna
9

Haskell, 16 111 + 57 = 168 Bytes

import Data.String
instance IsString[Int]where fromString=map((-48+).fromEnum)
f::[Int]->Int
f=foldl1((+).(2*))

+57 Bytes für die Kompilierung - Flags -XOverloadedStrings, -XOverlappingInstancesund -XFlexibleInstances.

Die Herausforderung hat ein umständliches E / A-Format , da es stark davon abhängt, wie Datentypen im Quellcode ausgedrückt werden. Meine erste Version (16 Bytes) nämlich

foldl1((+).(2*))

Nimmt eine Liste von ganzen Zahlen, zB [1,0,1,0,1,0]und wurde für ungültig erklärt, weil wörtliche Haskell-Listen ,zwischen den Elementen stehen. Listen an sich sind nicht verboten. In meiner neuen Version verwende ich dieselbe Funktion, die fich jetzt benenne , aber ich überlade "Zitiere eingeschlossene Zeichenfolgen". Die Funktion nimmt immer noch eine Liste von Ganzzahlen auf, wie Sie in der Typanmerkung sehen können [Int] -> Int, aber Listen mit einstelligen Ganzzahlen können jetzt so geschrieben werden, wie "1234"z

f "101010"

die auswertet zu 42. Pech für Haskell, denn das native Listenformat entspricht nicht den Herausforderungsregeln. Übrigens f [1,0,1,0,1,0]funktioniert immer noch.

nimi
quelle
2
Leider ist eine Liste keine gültige Eingabe.
Jonathan Allan
@ JonathanAllan: Warum? Und wenn ja, wie sollte es überhaupt Eingang nehmen? In Haskell ist eine Zeichenfolge nur eine Liste von Zeichen.
Nimi
Ich weiß nicht warum ... aber ich habe mich früh danach erkundigt und eine Änderung vorgenommen, um hinzuzufügen " (1,0,1,0,1,0,1,0)ist kein gültiges Eingabeformat, aber beides 10101010und (["10101010"])ist". Ein Kommentar legt außerdem nahe, dass das Array von Zeichen akzeptabel ist, wenn eine Zeichenfolge-Eingabe auf diese Weise interpretiert wird.
Jonathan Allan
1
@JonathanAllan: Jede "binäre Ganzzahl" (die Eingabe, die wir nehmen müssen) ist von Natur aus getrennt, es ist eine Folge von Potenzen von 2. Bei der Einschränkung geht es um explizite Trennzeichen (zwischen den Ziffern) und nicht um Trennung. Irgendwie muss ich getrennte Ziffern nehmen.
Nimi
2
Op hier: wenn es möglich ist die Eingabe 10101010, "10101010"oder etwas ähnliches und damit es funktioniert dann die Vorlage gültig ist. Sie können es eine Zeichenfolge, Liste, Ganzzahl oder was auch immer nennen. Eingabe [1][0][1][0]oder [1,0,1,0]nicht ok. Grundsätzlich sollte es möglich sein, einfach eine Reihe von Einsen und Nullen hintereinander zu treffen. Ist das klar?
Stewie Griffin
7

Retina, 15 Bytes

Konvertiert von binär nach unär, dann von unär nach dezimal.

1
01
+`10
011
1

Probieren Sie es online aus

mbomb007
quelle
Sie dürfen keine eingebauten Basisumwandlungsfunktionen verwenden. ~ OP
Roman Gräf
10
@ RomanGräf Es gibt keine. Ich habe lediglich den Prozess meiner Lösung beschrieben.
mbomb007
7

PHP, 44 Bytes

for(;""<$c=$argv[1][$i++];)$n+=$n+$c;echo$n;

Ich hätte schwören können, dass ich diese Frage schon einmal gesehen habe. Aber gut.

Liest die Zahl von links nach rechts, verschiebt sich nach links und fügt das aktuelle Bit hinzu.

Titus
quelle
7

JavaScript (ES6), 33 31 Bytes

s=>[...s].map(c=>r+=+c+r,r=0)|r

Bearbeiten: Kürzere aber weniger süß: 2 Bytes dank @ETHproductions gespeichert.

Neil
quelle
Wie so oft, .mapist kürzer:s=>[...s].map(c=>+c+r+r,r=0)|r
ETHproductions
@ETHproductions Wie gibt Ihre Funktion etwas anderes als 0 zurück?
Neil
Entschuldigung, es sollte seins=>[...s].map(c=>r+=+c+r,r=0)|r
ETHproductions
7

Labyrinth , 17-15 Bytes

-+:
8 +
4_,`)/!

Probieren Sie es online!

Bild des Codes

Labyrinth ist eine zweidimensionale, stapelbasierte Sprache. Im Labyrinth folgt die Codeausführung dem Pfad des Codes wie ein Labyrinth, in dem Leerzeichen als Wände fungieren und am Zeichen ganz oben links beginnen, das kein Leerzeichen ist. Der Code-Fluss wird durch das Vorzeichen oben auf dem Stapel bestimmt. Da der Stapel unten implizite Nullen hat, haben die ersten vier Anweisungen ( -+:+) keine Wirkung.

Schleife ab dem ,

  • , Schieben Sie den ASCII-Codewert des nächsten eingegebenen Zeichens an das Ende des Stapels oder drücken Sie -1, wenn EOF.
  • _48 drückt 48 nach oben auf den Stapel
  • -Pop y, Pop x, drücken x-y. Die vorherigen Anweisungen haben den Effekt, 48 von der Eingabe zu subtrahieren, was 0 für "0" und 1 für "1" ergibt.
  • +Pop y, Pop x, drücken x+y.
  • : Duplizieren Sie die Oberseite des Stapels
  • + Diese und die vorherige Anweisung bewirken, dass der aktuelle Wert mit 2 multipliziert wird

Der kreisförmige Teil des Codes multipliziert also die aktuelle Zahl mit 2 und fügt entweder eine 1 oder eine 0 hinzu, je nachdem, ob das Zeichen 1 oder 0 eingegeben wurde.

Schwanz

Wenn die Oberseite des Stapels negativ ist (was bedeutet, dass EOF gefunden wurde), biegt der Code an der Kreuzung links ab (in Richtung des Semikolons).

  • `` `Negiere die Spitze des Stapels, um 1 zu erhalten
  • ) Ikrementiere den oberen Teil des Stapels, um 2 zu erhalten
  • /Pop y, pop x, push x / y (ganzzahlige Division). Dies hat den Effekt, dass der letzte Teil *2der Schleife rückgängig gemacht wird.
  • !Gibt die ganzzahlige Darstellung des oberen Bereichs des Stapels aus. Zu diesem Zeitpunkt dreht sich das Programm um, weil es eine Sackgasse erreicht hat, und wird dann mit einem Fehler beendet, weil es versucht, durch Null zu dividieren.

Vielen Dank an @Martin Ender , der mir 2 Bytes gespart hat (und mir beigebracht hat, wie ich im Labyrinth besser denken kann).

Robert Hickman
quelle
Anstelle von _48-dir kann man das einfach machen, #%aber leider sehe ich nicht, wie es bei der Byteanzahl helfen könnte.
Martin Ender
Sie können ein Byte mit speichern, `)anstatt mit ;_2.
Martin Ender
@ MartinEnder, ich verstehe Ihren Kommentar nicht #%. Können Sie erklären, wie das als Ersatz für _48-die Konvertierung von ASCII nach int funktioniert ? Danke für den )Tipp. Ich werde das ändern.
Robert Hickman
Zu diesem Zeitpunkt in Ihrem Programm befinden sich immer zwei Werte auf dem Stapel, daher #ist dies nur eine Abkürzung für _2. Obwohl _2%es sich nicht um eine allgemeine Konvertierungsmethode für ASCII in eine Ganzzahl handelt, funktioniert dies hier, da Sie nur an den ersten beiden Ziffern als mögliche Eingabe interessiert sind. Eine Alternative wäre _1&(da Modulo 2 einfach das niedrigstwertige Bit extrahiert).
Martin Ender
Oh. Das ist hervorragend. Aber ich bin mir nicht sicher, wie ich diese Ersetzung ( #%) verwenden soll, um den Code insgesamt zu verkürzen.
Robert Hickman
6

Brain-Flak , 46 , 28 Bytes

([]){{}({}<>({}){})<>([])}<>

Probieren Sie es online!

Vielen, vielen Bytes dank @Riley gespart!

Da Brain-Flak keine Binäreingabe akzeptieren kann, ist die Eingabe eine Liste von '0' und '1'.

Erläuterung:

#Push the height of the stack
([])

#While true:
{

 #Pop the height of the stack
 {}

 #Push this top number to (the other stack * 2)
 ({}<>({}){})

 #Toggle back on to the main stack
 <>

 #Push the new height of the stack
 ([])

#endwhile
}

#Toggle back to the other stack, implicitly display.
<>
DJMcMayhem
quelle
Liebe die Erklärung! So schwer zu lesen Brain-Flak ohne :)
Emigna
2
^. Ich kann nicht einmal meine eigenen Programme lesen, wenn ich nicht ein paar Kommentare hinterlasse.
Riley
Sie können es auf 32 Bytes reduzieren, indem Sie den gesamten if-Teil entfernen und ihn für den Schritt "Nummer zu anderem Stapel hinzufügen" einfach zum (anderen Stapel) * 2 hinzufügen. ([]){({}[()]<({}<>({}){})><>)}<>
Riley
Und Sie können weitere 4 sparen, indem Sie am Anfang der Zeit einfach auftauchen und am Ende die Höhe erneut drücken. ([]){{}({}<>({}){})<>([])}<>
Riley
@ Riley Oh mein Gott, das ist genial. Vielen Dank!
DJMcMayhem
6

Java, 84 79 46 48 Bytes

  • Version 3.1

Geändert zu long/ 48 Bytes:

s->{long x=0;for(char c:s)x=c-48l+x*2;return x;}
  • Version 3.0

Haben Sie etwas Golf gespielt / 46 Bytes:

s->{int x=0;for(char c:s)x=c-48+x*2;return x;}
  • Version 2.0

Vielen Dank an @Geobits! / 79 Bytes:

s->{int i=Math.pow(2,s.length-1),j=0;for(char c:s){j+=c>48?i:0;i/=2;}return j;}
  • Version 1.0

84 Bytes:

s->{for(int i=-1,j=0;++i<s.length;)if(s[i]>48)j+=Math.pow(2,s.length-i+1);return j;}
Roman Gräf
quelle
1
denke, ich hätte eine iterative Lösung tun sollen. lulz. gute Arbeit
Poke
Entspricht Ihr Eingabetyp Liste <Zeichen> oder Zeichenfolge? Wenn es das letztere ist, wusste ich nicht, dass Java8 das kann! Wenn es das erstere ist, ist das durch die Herausforderung erlaubt?
Poke
ssollte sein char[]. Ich hoffe, das ist erlaubt ...
Roman Gräf
Was ist die Rückgabeart hier? Ich denke, es sollte lang sein, weil "der Code Binärzahlen bis zu dem höchsten numerischen Wert unterstützen muss, den Ihre Sprache unterstützt" pro OP, aber für kleinere Werte würde ich denken, dass es einen int
Poke
1
Wahrscheinlich fein auf Eingabetyp pro dies . Vielleicht möchten Sie den 2-Byte-Hit für die Ausgabe imo nehmen
Poke
4

Befunge-98, 12 Bytes

2j@.~2%\2*+

Probieren Sie es online!

Liest jeweils ein Zeichen von der Eingabe, konvertiert es in 0 oder 1, indem es seinen Wert modulo 2 annimmt (0 ist char (48), 1 ist char (49)), und verwendet dann den üblichen Algorithmus zum Verdoppeln des aktuellen Werts und Addieren von jedes Mal eine neue Ziffer.

Bonus: Das funktioniert mit jeder Art von Eingabezeichenfolge. Ich habe schon eine Weile versucht, eine lustige Eingabe-> Ausgabe-Kombination zu finden, aber ich konnte nichts produzieren (leider "Antwort" = 46). Können Sie?

Löwe
quelle
LOL. Ich habe das gleiche Spiel mit meiner Antwort gespielt. Die interessanteste Zahl, die ich generieren konnte, war 666 .
James Holderness
Schön! Ich hatte es nicht geschafft, etwas Passendes für 666 zu finden: D Es wäre viel einfacher, wenn sich die Kapitalisierung auf die Werte auswirken würde ...
Leo
@ James Holderness - Ich habe das Gleiche getan und ich habe nur 'das letzte Jahr' gefunden, um 366 zurückzubringen, deins ist wirklich gut.
Teal Pelikan
4

Javascript (ES7) 41 40 36 Bytes

f=([c,...b])=>c?c*2**b.length+f(b):0

Nimmt einen String als Eingabe

Dank ETHproductions ein Byte rasiert

f=([c,...b])=>c?c*2**b.length+f(b):0
document.write([
    f('101010'),
    f('11010'),
    f('10111111110'),
    f('1011110010110'),
].join("<br>"))

Shaun H
quelle
1
Die Assoziativität von rechts nach links **ist seltsam, aber ein guter Job, wenn man sie hier verwendet. 1<<b.lengthwürde dasselbe tun, aber es würde Klammern erfordern, um nicht analysiert zu werden als (c*1)<<(b.length+...). Ich glaube , Sie durch Ersetzen eines Byte speichern kann b[0]mit b+b( siehe hier ).
ETHproductions
4

C # 6, 85 37 36 Bytes

long b(long n)=>n>0?n%2+2*b(n/10):0;
  • Danke an Kade für das Speichern von 41 Bytes!
  • Der Wechsel zu C # 6 sparte weitere 7 Bytes.
Yytsi
quelle
Vielleicht könnte dies Inspiration liefern? ;)
Kade
@Kade Tut es, danke! Ich habe mir die Python-Antwort angesehen, die im selben Moment, in dem Sie verlinkt haben, dieselbe Technik verwendet: DI kann mit C # 6 sogar noch kürzer werden.
Yytsi
3

05AB1E , 7 Bytes

RvNoy*O

Probieren Sie es online!

Erläuterung

R         # reverse input
 v     O  # sum of
  No      # 2^index
     *    # times
    y     # digit
Emigna
quelle
3

C 53

v(char*s){int v=0,c;while(c=*s++)v+=v+c-48;return v;}

Entspricht meiner Javascript-Antwort

Testen Sie Ideone

edc65
quelle
Sie können 4 Bytes sparen, indem Sie vund cals globale Variablen deklarieren (obwohl Sie vden Namen der Funktion ändern müssen , da dies bereits der Name der Funktion ist):w=0;c;v(char*s){while(c=*s++)w+=w+c-48;return w;}
Steadybox
@Steadybox könnte es sein, w,c;aber ich möchte keine Globals verwenden, wenn die Antwort eine Funktion ist (auch in Code-Golf)
edc65
@Steadybox Globals ist ebenfalls standardmäßig auf 0 eingestellt, sodass Sie die fallen lassen können =0.
Algmyr
3

Perl, 25 Bytes

-3 Bytes dank @Dom Hastings.

24 Byte Code + 1 Byte für -pFlag.

$\|=$&<<$v++while s/.$//

Um es auszuführen:

perl -pe '$\|=$&<<$v++while s/.$//' <<< 101010

Erklärungen:

$\|=$&<<$v++  # Note that: we use $\ to store the result
              # at first $v=0, and each time it's incremented by one
              # $& contains the current bit (matched with the regex, see bellow)
              # So this operation sets a $v-th bit of $\ to the value of the $v-th bit of the input
while         # keep doing this while...
s/.$//        #  ... there is a character at the end of the string, which we remove.
         # $\ is implicitly printed thanks to -p flag
Dada
quelle
3

Aufdringlich , 10 Bytes

Nimmt die Eingabe als eine Liste von 0/1 auf der Kommandozeile: $ pushy binary.pshy 1,0,1,0,1,0.

L:vK2*;OS#

Der Algorithmus zeigt wirklich die Schönheit eines zweiten Stapels:

            \ Implicit: Input on stack
L:    ;     \ len(input) times do:
  v         \   Push last number to auxiliary stack
   K2*      \   Double all items
       OS#  \ Output sum of auxiliary stack

Diese Methode funktioniert, weil der Stapel stack length - nvor Erreichen der Zahl zweimal verdoppelt nwird, und dann für später im zweiten Stapel abgelegt wird. So sieht der Vorgang bei der Eingabe aus 101010:

1: [1,0,1,0,1,0]
2: []

1: [2,0,2,0,2]
2: [0]

1: [4,0,4,0]
2: [2]

1: [8,0,8]
2: [2,0]

1: [16,0]
2: [2,0,8]

1: [32]
2: [2,0,8,0]

1: []
2: [2,0,8,0,32]

2 + 8 + 32 -> 42
FlipTack
quelle
3

Matlab, 30 Bytes

@(x)sum(2.^find(flip(x)-48)/2)

Der letzte Testfall weist (wegen double) Rundungsfehler auf. Wenn Sie also die volle Genauigkeit benötigen:

@(x)sum(2.^uint64(find(flip(x)-48))/2,'native')

mit 47 Bytes.

Jonas
quelle
Ich kann das nicht testen, aber ich glaube @(x)sum(2.^(find(flip(x)-48)-1)), dass es für 32 Bytes in allen Fällen das richtige Ergebnis gibt. flipfunktioniert wie fliplrwenn xist eindimensional.
Stewie Griffin
Schöne lösung! Ich bin auch auf den Rundungsfehler gestoßen, danke für die Korrektur. Was ist das Format von x? Durch Anrufen von flip oder fliplr auf einer Nummer wird nur diese Nummer zurückgegeben.
MattWH
x ist die Binärzeichenfolge, also rufen Sie sie mit auf f=@(x)..; f('1111001010').
Jonas
3

Retina , 12 Bytes

Die Anzahl der Bytes setzt die Kodierung nach ISO 8859-1 voraus.

+%`\B
¶$`:
1

Probieren Sie es online!

Alternative Lösung:

+1`\B
:$`:
1

Erläuterung

Dies wird wahrscheinlich einfacher zu erklären sein, basierend auf meiner alten, weniger golfenen Version, und dann zu zeigen, wie ich es verkürzt habe. Früher habe ich Binär in Dezimal konvertiert:

^
,
+`,(.)
$`$1,
1

Der einzig sinnvolle Weg, eine Dezimalzahl in Retina zu erstellen, ist das Zählen von Dingen (da Retina über einige Funktionen verfügt, mit denen eine Dezimalzahl ausgegeben werden kann, die einen Betrag darstellt). Der einzig mögliche Ansatz besteht also darin, die Binärzahl in eine unäre Zahl umzuwandeln und dann die Anzahl der unären Stellen zu zählen. Die letzte Zeile zählt, also wandeln die ersten vier Binär in Unär um.

Wie machen wir das? Um von einer Liste von Bits in eine Ganzzahl zu konvertieren, initialisieren wir das Ergebnis auf 0und gehen dann die Bits von der höchsten bis zur niedrigsten Wertigkeit durch, verdoppeln den bereits vorhandenen Wert und addieren das aktuelle Bit. Wenn zum Beispiel die Binärzahl ist 1011, würden wir wirklich berechnen:

(((0 * 2 + 1) * 2 + 0) * 2 + 1) * 2 + 1 = 11
           ^        ^        ^        ^

Wo ich die einzelnen Bits der Übersichtlichkeit halber markiert habe.

Der Trick dabei ist a) dass das Verdoppeln einfach das Wiederholen der Zahl bedeutet und b) da wir das 1s am Ende zählen, brauchen wir nicht einmal zwischen 0s und 1s zu unterscheiden . Dies wird in einer Sekunde klarer.

Was das Programm macht, ist, dass es zuerst ein Komma an den Anfang fügt, um zu markieren, wie viel von der Eingabe wir bereits verarbeitet haben:

^
,

Links vom Marker wird der Wert angezeigt, den wir akkumulieren (der korrekt auf die unäre Darstellung von Null initialisiert ist), und rechts vom Wert wird das nächste zu verarbeitende Bit angezeigt. Jetzt wenden wir die folgende Substitution in einer Schleife an:

,(.)
$`$1,

Wenn Sie nur auf ,(.)und schauen $1,, wird der Marker jedes Mal ein Stück nach rechts verschoben. Wir fügen aber auch ein $`, was alles vor dem Marker ist, dh den aktuellen Wert, den wir verdoppeln. Hier sind die einzelnen Schritte bei der Verarbeitung von Eingaben 1011, bei denen ich das Ergebnis des Einfügens $`über jeder Zeile markiert habe (für den ersten Schritt ist es leer):

,1011

1,011
 _
110,11
   ___
1101101,1
       _______
110110111011011,

Sie werden sehen, dass wir die Null beibehalten und zusammen mit allem anderen verdoppelt haben, aber da wir sie am Ende ignorieren, spielt es keine Rolle, wie oft wir sie verdoppelt haben, solange die Anzahl der 1s beträgt richtig. Wenn Sie sie zählen, gibt es 11von ihnen genau das, was wir brauchen.

Damit bleibt die Frage, wie dies auf 12 Bytes reduziert werden kann. Der teuerste Teil der 18-Byte-Version ist die Verwendung des Markers. Das Ziel ist es, das loszuwerden. Wir wollen wirklich das Präfix jedes Bits verdoppeln, daher könnte eine erste Idee sein:

.
$`$&

Das Problem ist, dass diese Ersetzungen gleichzeitig stattfinden, sodass das erste Bit nicht für jedes Bit verdoppelt wird , sondern jedes Mal nur einmal kopiert wird. Für die Eingabe würden 1011wir erhalten (Markierung der eingefügten $`):

 _ __ ___
1101011011

Wir müssen die Eingabe immer noch rekursiv verarbeiten, sodass das verdoppelte erste Präfix erneut durch das zweite Präfix verdoppelt wird und so weiter. Eine Idee ist, Marker überall einzufügen und sie wiederholt durch das Präfix zu ersetzen:

\B
,
+%`,
¶$`

Nachdem wir zum ersten Mal jeden Marker durch das Präfix ersetzt haben, müssen wir uns merken, wo der Anfang der Eingabe war, damit wir auch Zeilenvorschübe einfügen und die %Option verwenden, um sicherzustellen, dass der nächste $`nur die Dinge aufnimmt, die dem nächsten Zeilenvorschub am nächsten sind.

Dies funktioniert, ist aber immer noch zu lang (16 Bytes beim Zählen von 1s am Ende). Wie wäre es, wenn wir die Dinge umdrehen? Die Stellen, an denen wir Marker einfügen möchten, sind durch \B(eine Position zwischen zwei Ziffern) gekennzeichnet. Warum fügen wir nicht einfach Präfixe in diese Positionen ein? Das funktioniert fast, aber der Unterschied besteht darin, dass wir in der vorherigen Lösung tatsächlich einen Marker in jeder Ersetzung entfernt haben. Dies ist wichtig, damit der Prozess beendet wird. Es \Bsind jedoch nicht die Charaktere, sondern nur Positionen, sodass nichts entfernt wird. Wir können das aber aufhalten\Bdurch stattdessen Einfügen eines nicht-stelligen Zeichens an dieser Stelle. Das verwandelt die Nicht-Wortgrenze in eine Wortgrenze, was dem Entfernen des Markierungszeichens früher entspricht. Und genau das leistet die 12-Byte-Lösung:

+%`\B
¶$`:

Der Vollständigkeit halber sind hier die einzelnen Verarbeitungsschritte 1011mit einer leeren Zeile nach jedem Schritt:

1
1:0
10:1
101:1

1
1:0
1
1:0:1
1
1:0
10:1:1

1
1:0
1
1:0:1
1
1:0
1
1:0:1:1

Auch hier werden Sie feststellen, dass das letzte Ergebnis genau 11 1s enthält .

Können Sie als Übung für den Leser sehen, wie sich dies auf andere Basen verallgemeinern lässt (für ein paar zusätzliche Bytes pro Inkrement in der Basis)?

Martin Ender
quelle
2

T-SQL, 202 Bytes

DECLARE @b varchar(max)='1',@ int=1 declare @l int=LEN(@b)declare @o bigint=CAST(SUBSTRING(@b,@l,1)AS bigint)WHILE @<@l BEGIN SET @o=@o+POWER(CAST(SUBSTRING(@b,@l-@,1)*2AS bigint),@)SET @=@+1 END PRINT @o
Nelz
quelle
2

PHP, 64 Bytes

foreach(str_split(strrev($argv[1]))as$k=>$v)$t+=$v*2**$k;echo$t;

Wir kehren unsere Binärzahl um, teilen sie in ihre einzelnen Ziffern auf und addieren sie nach ihrer Position.

Xanderhall
quelle
2

Bash + GNU-Dienstprogramme, 29 Bytes

sed 's/./2*&+/g;s/.*/K&p/'|dc

I / O über stdin / stdout.

Der sedAusdruck teilt die Binärzahl in jede Ziffer auf und erstellt einen RPN-Ausdruck für dcdie Auswertung.

Digitales Trauma
quelle
2

PowerShell v2 +, 55 Byte

param($n)$j=1;$n[$n.length..0]|%{$i+=+"$_"*$j;$j*=2};$i

Fühlt sich zu lang an ... Ich kann es nicht so scheinen, als würde ich Golf spielen - Tipps sind willkommen.

Erläuterung

param($n)$j=1;$n[$n.length..0]|%{$i+=+"$_"*$j;$j*=2};$i
param($n)$j=1;                                          # Take input $n as string, set $j=1
              $n[$n.length..0]                          # Reverses, also converts to char-array
                              |%{                  };   # Loop over that array
                                 $i+=+"$_"*$j;          # Increment by current value of $j times current digit
                                              $j*=2     # Increase $j for next loop iteration
                                                     $i # Leave $i on pipeline
                                                        # Implicit output
AdmBorkBork
quelle
2

JavaScript (ES6), 32 Byte

f=([...n])=>n+n&&+n.pop()+2*f(n)

Rekursion rettet den Tag wieder! Obwohl die Parametrisierung etwas langwierig erscheint ...

ETHproductions
quelle
Müssen Sie das Argument [...n]in Klammern setzen, da es sich um ein einzelnes "Argument" handelt ?
Cyoce
@Cyoce Leider ja, oder JS wirft einen SyntaxError.
ETHproductions
2

Mathematica, 27 13 11 Bytes

Fold[#+##&]

Nimmt ein Listvon Bits als Eingabe (zB {1, 0, 1, 1, 0}- Mathematica ‚s binäre Darstellung der Zahl 22)

JungHwan min
quelle
Nach dem Kommentar zu Gregs Antwort: Wie ist "Aufteilen aller Ziffern in der Eingabe" keine Basisumwandlungsfunktion?
Martin Ender
@MartinEnder Ich benutze es wie die CharactersFunktion.
JungHwan Min
@MartinEnder Wie in @ nimis Antwort zu sehen ist , könnte ich einfach eine Liste von Einsen und Nullen akzeptieren, da dies die einzige Möglichkeit ist, eine Binärzahl in Mathematica darzustellen , was bedeutet, dass ich sie überhaupt nicht brauche IntegerDigits.
JungHwan Min
Dies setzt voraus, dass Basis 10 die "natürliche" Darstellung einer ganzen Zahl ist. An einen tatsächlichen Integer-Wert ist keine bevorzugte Basis angehängt (ich denke, man könnte sagen, dass die Art und Weise, wie er gespeichert wird, wahrscheinlich Basis 256 oder sogar Basis 2 ist, aber das ist ein Implementierungsdetail). Nur weil wir (normalerweise) die Basis 10 verwenden, um ganzzahlige Literale zu schreiben, heißt das nicht, dass ganzzahlige Werte bereits in der Basis 10 sind.
Martin Ender
@MartinEnder @ Lynns Jelly-Code verwendet D, der das Gleiche tut wieIntegerDigits
JungHwan Min
2

Clojure, 114 105 63 41 Bytes

V4: 41 Bytes

-22 Bytes dank @cliffroot. Da digites sich um ein Zeichen handelt, kann es über in seinen Code konvertiert werden int. Dann müssen 48 davon subtrahiert werden, um die tatsächliche Zahl zu erhalten. Die Karte wurde ebenfalls ausgeklammert. Ich weiß nicht, warum es notwendig schien.

#(reduce(fn[a d](+(* a 2)(-(int d)48)))%)

V3: 63 Bytes

(fn[s](reduce #(+(* %1 2)%2)(map #(Integer/parseInt(str %))s)))

-42 Bytes (!) Durch Betrachten anderer Antworten. Mein "Zippen" war offensichtlich sehr naiv. Anstatt 2 zur Potenz der aktuellen Stelle zu erhöhen, sie dann mit der aktuellen Ziffer zu multiplizieren und das Ergebnis zum Akkumulator hinzuzufügen, multipliziert es nur den Akkumulator mit 2, addiert die aktuelle Ziffer und addiert sie dann zum Akkumulator. Außerdem wurde die Reduktionsfunktion in ein Makro umgewandelt, um ein wenig zu rasieren.

Vielen Dank an @nimi und @Adnan!

Ungolfed:

(defn to-dec [binary-str]
  (reduce (fn [acc digit]
            (+ (* acc 2) digit))
          (map #(Integer/parseInt (str %)) binary-str)))

V2: 105 Bytes

#(reduce(fn[a[p d]](+ a(*(Integer/parseInt(str d))(long(Math/pow 2 p)))))0(map vector(range)(reverse %)))

-9 Bytes durch Umkehren der Zeichenfolge, damit kein unangenehmer absteigender Bereich erstellt werden muss.

V1: 114 Bytes

Nun, ich gewinne bestimmt nicht! Zu meiner Verteidigung ist dies das erste Programm, das ich jemals geschrieben habe und das zwischen Basen konvertiert. Daher musste ich lernen, wie man das macht. Es hilft auch nicht, dass Math/powein Double zurückgegeben wird, von dem konvertiert werden muss, und Integer/parseIntdass kein Zeichen akzeptiert wird. Daher muss die Ziffer vor dem Übergeben umbrochen werden.

#(reduce(fn[a[p d]](+ a(*(Integer/parseInt(str d))(long(Math/pow 2 p)))))0(map vector(range(dec(count %))-1 -1)%))

Zippt die Zeichenfolge mit einem absteigenden Index, der die Ortsnummer darstellt. Reduziert die resultierende Liste.

Ungolfed:

(defn to-dec [binary-str]
  (reduce (fn [acc [place digit]]
            (let [parsed-digit (Integer/parseInt (str digit))
                  place-value (long (Math/pow 2 place))]
              (+ acc (* parsed-digit place-value))))
          0
          (map vector (range (dec (count binary-str)) -1 -1) binary-str)))
Karzigenat
quelle
#(reduce(fn[a b](+(* a 2)(-(int b)48)))0 %)verbesserte Version. Ein mapTeil des Codes wurde direkt in die reducegeänderte Integer-Parsing-Methode verschoben. Externe Funktionen werden mit der Lambda-Kurzschrift-Syntax erstellt.
Cliffroot
@ Cliffroot intkann zum Parsen verwendet werden !? Das klopft bei jeder Herausforderung, die ich hier gemacht habe, um die 10 Bytes.
Carcigenicate
Oh, ich verstehe, was du tust. Nehmen Sie den ASCII-Code und subtrahieren Sie ihn, um den Wert zu erhalten. Ich denke, das würde nur unter bestimmten Umständen funktionieren. Na ja, danke für den Tipp.
Carcigenicate
2

Perl, 21, 19, 16 + 4 = 20 Bytes

-4 Bytes dank @Dada

Führen Sie mit -F -p(einschließlich des zusätzlichen Leerzeichens nach dem F) aus. Pipe Werte zur Funktion mitecho -n

$\+=$_+$\for@F}{

Rennen wie echo -n "101010" | perl -F -pE '$\+=$_+$\for@F}{'

Ich bin der Meinung, dass dies ausreichend von @ Dadas Antwort abweicht, sodass es einen eigenen Eintrag verdient.

Erläuterung:

-F                              #Splits the input character by character into the @F array
-p                              #Wraps the entire program in while(<>){ ... print} turning it into
while(<>){$\+=$_+$\for@F}{print}
                   for@F        #Loops through the @F array in order ($_ as alias), and...
          $\+=$_+$\             #...doubles $\, and then adds $_ to it (0 or 1)...
while(<>){              }       #...as long as there is input.
                         {print}#Prints the contents of $_ (empty outside of its scope), followed by the output record separator $\

Dabei wird mein persönlicher Algorithmus zur Umwandlung von Binär in Dezimal verwendet. Starten Sie Ihren Akkumulator bei einer gegebenen Binärzahl bei 0 und gehen Sie die Bits nacheinander durch. Verdoppeln Sie den Akkumulator für jedes Bit, fügen Sie das Bit selbst zu Ihrem Akkumulator hinzu, und Sie erhalten den Dezimalwert. Dies funktioniert, weil jedes Bit entsprechend der Anzahl der für seine Position verbleibenden Bits in der ursprünglichen Binärzahl entsprechend oft verdoppelt wird.

Gabriel Benamy
quelle
Noch kürzer:perl -F -pE '$\+=$_+$\for@F}{'
Dada
Ich habe ehrlich darüber gelacht, wie kurz das jetzt ist. Vielen Dank.
Gabriel Benamy
Ja, es ist ziemlich ordentlich, gut gemacht!
Dada
2

R (32 Bit), 64 Byte

Die Eingabe für die Funktion sollte als Zeichen erfolgen. Die Basisfunktionen von R unterstützen 32-Bit-Ganzzahlen.

Eingang:

# 32-bit version (base)
f=function(x)sum(as.double(el(strsplit(x,"")))*2^(nchar(x):1-1))
f("1")
f("10")
f("101010")
f("1101111111010101100101110111001110001000110100110011100000111")

Ausgabe:

> f("1")
[1] 1
> f("10")
[1] 2
> f("101010")
[1] 42
> f("1101111111010101100101110111001110001000110100110011100000111")
[1] 2.016121e+18

R (64-Bit), 74 Bytes

Die Eingabe für die Funktion sollte als Zeichen erfolgen. Das Paket bit64muss für 64-Bit-Ganzzahlen verwendet werden.

Eingang:

# 64-bit version (bit64)
g=function(x)sum(bit64::as.integer64(el(strsplit(x,"")))*2^(nchar(x):1-1))
g("1")
g("10")
g("101010")
g("1101111111010101100101110111001110001000110100110011100000111")

Ausgabe:

> g("1")
integer64
[1] 1
> g("10")
integer64
[1] 2
> g("101010")
integer64
[1] 42
> g("1101111111010101100101110111001110001000110100110011100000111")
integer64
[1] 2016120520371234567
Djhurio
quelle
2
Sie können Folgendes tun: el(strsplit(x,""))Anstatt strsplit(x,split="")[[1]]ein paar Bytes zu speichern.
Billywob
Vielen Dank! Vor allem für die elFunktion - ich war mir dessen nicht bewusst.
Djhurio
2

Dyalog APL , 12 Bytes

(++⊢)/⌽⍎¨⍞

Zeichenketteneingabe erhalten

⍎¨ Wandle jedes Zeichen in eine Zahl um

umkehren

(... )/füge die folgende Funktion zwischen die Zahlen ein

++⊢ die Summe der Argumente plus das richtige Argument


ngn rasierte 2 Bytes.

Adam
quelle
1

k, 8 Bytes

Gleiche Methode wie bei der obigen Haskell-Antwort.

{y+2*x}/

Beispiel:

{y+2*x}/1101111111010101100101110111001110001000110100110011100000111b
2016120520371234567
Skeevey
quelle