Komplexe Binärzahlen

36

Lassen Sie uns eine einfache, surjektive Zuordnung von positiven Ganzzahlen zu Gaußschen Ganzzahlen erstellen , bei denen es sich um komplexe Zahlen handelt, bei denen der Real- und Imaginärteil Ganzzahlen sind.

Wenn Sie zum Beispiel eine positive Ganzzahl haben 4538, drücken Sie sie in Binärform ohne führende 0Zeichen aus:

4538 base 10 = 1000110111010 base 2

Entfernen Sie alle folgenden 0Elemente:

100011011101

Ersetzen Sie alle Läufe von einem oder mehreren 0durch einen einzigen +:

1+11+111+1

Ersetzen Sie alle 1durch i's:

i+ii+iii+i

Bewerten Sie den resultierenden komplexen Ausdruck und geben Sie die vereinfachte Gaußsche Ganzzahl aus:

i+ii+iii+i = i+i*i+i*i*i+i = 2i+i^2+i^3 = 2i+(-1)+(-i) = -1+i

Die Ausgabe kann auf herkömmliche mathematische Weise ausgedrückt oder als zwei separate Ganzzahlen für den Realteil und den komplexen Teil angegeben werden. Für das 4538Beispiel wäre eines dieser Beispiele in Ordnung:

-1+i
i-1
-1+1i
(-1, 1)
-1 1
-1\n1

Für Eingänge , wie 29, mathy formatiert Ausgänge wie 0, 0ioder 0+0isind alle in Ordnung.

Verwenden j(oder etwas anderes) anstelle von iist in Ordnung, wenn dies für Ihre Sprache natürlicher ist.

Der kürzeste Code in Bytes gewinnt.

Calvins Hobbys
quelle
Vom Titel her dachte ich, dass die Herausforderung über komplexe Zahlen in Binär sein würde, zB 4+2j-> 100+10j...
Erik the Outgolfer

Antworten:

22

MATL , 7 Bytes

BJ*Y'^s

Probieren Sie es online!

Wie es funktioniert

Betrachten Sie 4538zum Beispiel die Eingabe .

B     % Implicit input. Convert to binary
      % STACK: [1 0 0 0 1 1 0 1 1 1 0 1 0]
J*    % Multiply by 1i
      % STACK: [1i 0 0 0 1i 1i 0 1i 1i 1i 0 1i 0]
Y'    % Run-length encoding
      % STACK: [1i 0 1i 0 1i 0 1i 0], [1 3 2 1 3 1 1 1]
^     % Power, element-wise
      % STACK: [1i 0 -1 0 -1i 0 1i 0]
s     % Sum of array. Implicit display
      % STACK: -1+1i
Luis Mendo
quelle
2
7 Bytes in MATL, und das Beste, was ich bekommen kann, ist 58 in MATLAB ... Sie haben dort eine nette kleine Sprache gemacht! =)
Stewie Griffin
1
@StewieGriffin ist mit Abstand das Beste in Sachen Grafik oder Plotten, vielleicht auch für Matrix-Arithmetik.
Magic Octopus Urn
13

Gelee , 8 Bytes

BŒgaıP€S

Probieren Sie es online!

Wie es funktioniert

BŒgaıP€S  Main link. Argument: n (integer)

B         Convert to binary.
          If n = 4538, this yields [1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0].
 Œg       Group equal elements.
          This yields [[1], [0, 0, 0], [1, 1], [0], [1, 1, 1], [0], [1], [0]].
   aı     Logical AND with the imaginary unit.
          This yields [[ı], [0, 0, 0], [ı, ı], [0], [ı, ı, ı], [0], [ı], [0]].
     P€   Product each.
          This yields [ı, 0, -1, 0, -ı, 0, ı, 0].
       S  Sum.
          This yields -1+ı.
Dennis
quelle
10

Python 2, 53 Bytes

f=lambda n,k=0:(n and f(n/2,n%2*(k or 1)*1j))+~n%2*k

Ich habe versucht, dies zu golfen, und es scheint golfen zu können, aber ich habe keine A ...

Sp3000
quelle
1
Das (k or 1)scheint nicht optimal zu sein, aber das einzige, (k+0**k)
woran
@ETHproductions Meine Gedanken genau, aber leider 0**knicht für komplexe k...
Sp3000
6

Mathematica, 44 38 Bytes

Tr[1##&@@@Split[I*#~IntegerDigits~2]]&

Erläuterung

#~IntegerDigits~2

Konvertiere die Eingabe in Basis 2. ( 4538wird {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0})

I*

Multiplizieren mit I( {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0}wird {I, 0, 0, 0, I, I, 0, I, I, I, 0, I, 0})

Split

Nach Läufen {I, 0, 0, 0, I, I, 0, I, I, I, 0, I, 0}aufteilen ( wird {{I}, {0, 0, 0}, {I, I}, {0}, {I, I, I}, {0}, {I}, {0}})

1##&@@@ ...

Finde das Produkt auf Stufe 2. ( {{I}, {0, 0, 0}, {I, I}, {0}, {I, I, I}, {0}, {I}, {0}}wird {I, 0, -1, 0, -I, 0, I, 0})

Tr

Summiere das Ergebnis. ( {I, 0, -1, 0, -I, 0, I, 0}Wird -1 + I)

JungHwan min
quelle
minus 1 Byte:Tr[Times@@@(I*Split@RealDigits[#,2][[1]])]&
Martin
1
@ Martin Nun, ich habe deine Idee, zuerst zu multiplizieren I, benutzt, IntegerDigitsbin aber kürzer geworden.
JungHwan Min
ja - viel besser :)
Martin
5

Python 2 , 77 76 71 Bytes

p=r=0
for n in bin(input()*2):t=n=='1';r-=p*~-t;p=p*t*1jor t*1j
print r

Vielen Dank an @ZacharyT für das Golfen ab 1 Byte!

Probieren Sie es online!

Dennis
quelle
5

JavaScript (ES6), 67 64 Bytes

f=(n,q=0,a=[0,0])=>q|n?f(n/2,n&1?q+1:q&&0*(a[q&1]+=1-(q&2)),a):a
<input oninput="O.innerHTML=f(this.value)" type="number" step=1 min=0 value="4538">
<pre id=O></pre>

Ausgabe als 2-Element-Array.

Erläuterung

Da JavaScript keine imaginären Zahlen hat, müssen wir die Real- und Imaginärteile in separaten Variablen verfolgen. Der einfachste Weg, dies zu tun, ist ein einzelnes Array, wobei der Realteil an erster Stelle steht. i wird als [0,1] , i 2 (oder -1 ) als [-1,0] , i 3 (oder -i ) als [0, -1] und i 4 (oder 1 ) als [1] dargestellt , 0] .

Erstens teilen wir die Zahl wiederholt durch 2 und sammeln jeden Lauf von Einsen in seiner binären Darstellung. Jeder Lauf von n Einsen entspricht i n . Dies entspricht dem Hinzufügen von 1 - (n & 2) zu dem Element am Index n & 1 im Array mit zwei Elementen. Das machen wir also.

Ich sollte wahrscheinlich mehr Erklärungen hinzufügen, aber ich kann mir nicht vorstellen, was noch zu erklären ist. Wenn Sie Fragen haben, können Sie diese gerne kommentieren.

ETHproductions
quelle
5

Python, 199 129 124 116 94 90 71 63 61 Bytes

print sum(1j**len(s)for s in bin(input())[2:].split('0')if s)

Die Eingabe ist nur die Zahl selbst.
Die Ausgabe erfolgt in dem Format (a+bj), in dem jsich die imaginäre Einheit befindet. 0jwird ausgegeben statt(0+0j)

Zuerst ins Binäre konvertieren. Abschneiden '0b'. Töte die nachgestellten Nullen. Teilen mit einem Block von Null (en) als Trennzeichen. Ordnen Sie jeden Block zu 1j ** len. Dann nimm die Summe des Ganzen.

-70 Bytes, indem nicht in Plus konvertiert wird.
-5 Bytes Regex ist kürzer.
-8 Bytes, indem die beiden unnötigen Variablen entfernt werden, die nur einmal aufgerufen wurden.
-22 Bytes durch die Verwendung komplexer Zahlen anstelle meiner seltsamen Sache. Vielen Dank an @Dennis 'Antwort, die mich über komplexe Zahlen informiert hat!
-4 Bytes durch die Erkenntnis, dass dies mapnur eine ausgefallene Art ist, Listenverständnisse zu erstellen, außer länger.
-19 Bytes durch Umschalten auf eine leicht arkane Methode zur Vermeidung von Fehlern j ** 0und zur Vermeidung von Regex. Inspiriert von @ Griffins Kommentar. Vielen Dank! :)
-8 Bytes durch Verschieben des ifTeils an das Ende.
-2 Bytes Vielen Dank an @Griffin für das Speichern von 2 Bytes durch Entfernen der eckigen Klammern, damit es stattdessen ein Generator-Ausdruck wird!

HyperNeutrino
quelle
Ich habe etwas ziemlich Ähnliches, daher werde ich keine separate Antwort veröffentlichen, allerdings etwas kürzersum(1j**x.count('1')for x in bin(input()).split('0')if x)
Griffin
@Griffin Schön. Ich denke, es ist unterschiedlich genug, dass Sie eine separate Antwort posten könnten, da es eine andere Methode zum Zählen der 1Blöcke verwendet und nicht wie ich Regex verwendet. Außerdem möchte ich Ihnen den Code nicht stehlen, da er viel besser ist als meine Version. :)
HyperNeutrino
@Griffin Ich habe eine andere Lösung gefunden, die dieselbe Länge hat wie Ihre Lösung, außer dass statt 1s die Länge gezählt wird, der 0xTeil zuerst von vorne entfernt wird. Vielen Dank für die Idee, die ifzum Ende zu bewegen ; Ich hätte nie gewusst, dass das anders funktioniert!
HyperNeutrino
Sie brauchen das Listenverständnis nicht. Entfernen Sie die eckigen Klammern, um einen Generatorausdruck zu erhalten
Griffin
@Griffin Oh. Okay danke! Ich werde mich daran erinnern, dass
wir in
4

MATLAB, 58 Bytes

@(x)eval([strrep(strrep(dec2bin(x),48,43),49,'i*1'),'.0'])

dec2bin(x) % converts the decimal value to a binary string of 1s and 0s.
strrep(dec2bin(x),48,43) % Substitutes ASCII character 48 with 43 (0s become +)
strrep(___,49,'i*1')     % Substitutes ASCII character 49 with 'i*1'
                         % 1s become 'i*1' (this is the gem)
eval([___,'.0']          % Appends .0 in the end and evaluates the expression.   

Lassen Sie uns 285den Prozess veranschaulichen:

temp1 = dec2bin(285)
      = 100011101

temp2 = strrep(temp1,48,43)
      = 1+++111+1

Zum Glück 1+++1verhält es sich genauso wie 1+1in MATLAB 1+111+1.

temp3 = strrep(temp2,49,'i*1')
      = i*1+++i*1i*1i*1+i*1

Jetzt ist dieser strrepAnruf der wahre Schatz! Durch Einsetzen i*1für 1uns etwas wirklich schön bekommen. Wenn es nur einen gibt 1, bekommen wir einfach i*1den i. Wenn es mehr ist , als man dann i*1in eine Sequenz wiederholt und verkettet wird: i*1i*1i*1i*1. Da i==1iin MATLAB und das 1i*1==iist einfach: i*i*i*i.

temp4 = [temp3,'.0']
      = i*1+++i*1i*1i*1+i*1.0

Das Anhängen .0erscheint hier unnötig, wird aber benötigt, wenn das letzte Zeichen von a temp3ist +. Wir können nicht einfach eine Null anhängen, da dies i*10im obigen Fall zu einem falschen Ergebnis führen würde.

Und schlussendlich:

eval(temp4)
0.0000 + 1.0000i

Dies funktioniert in Octave aus mehreren Gründen nicht. strrepASCII-Werte können nicht als Eingabe verwendet werden, es werden die tatsächlichen Zeichen ( '0'anstelle von 48) benötigt. Auch +++wird nicht nur +in Oktave ausgewertet , da dies die Inkrement / Dekrement-Verknüpfungen x++und stören würde x--.

Stewie Griffin
quelle
1
Immer +1 für die Verwendung von eval:-P Können Sie nicht 1ianstelle von verwenden 1*i?
Luis Mendo
1
Oh, du benutzt es anders. Sehr schlau!
Luis Mendo
Danke :-) Ich muss zugeben, ich war sehr zufrieden mit dem i*1Teil ...
Stewie Griffin
3

Pyth - 15 Bytes

Frustrierend lang.

s^L.j)hMe#r8jQ2

Test Suite .

Maltysen
quelle
2

Mathematica, 84 Bytes

ToExpression[#~IntegerString~2~StringTrim~"0"~StringReplace~{"0"..->"+","1"->"I "}]&

Anonyme Funktion. Nimmt eine Zahl als Eingabe und gibt eine komplexe Zahl als Ausgabe zurück.

LegionMammal978
quelle
6
Wow, ich bin überrascht, dass Mathematica dafür kein eingebautes Programm hat!
HyperNeutrino
2

Mathematica, 75 Bytes

ToExpression[#~IntegerString~2~StringReplace~{"1"->"I ","0"..->"+"}<>"-0"]&

Independent hat sich fast dieselbe Lösung ausgedacht, die LegionMammal978 vor 23 Minuten gepostet hat! Ersetzen 1durch I (das interne Symbol von Mathematica für die Quadratwurzel von -1) funktioniert, weil Leerzeichen als Multiplikation benachbarter Ausdrücke behandelt werden. Der Platz, den ich bei der anderen Lösung gespart habe, nämlich indem ich das Erfordernis vermieden habe StringTrim, besteht darin, immer anzuhängen -0: Wenn die Binärzahl auf endet 1, endet dieser Ausdruck, ...I-0der seinen Wert nicht beeinflusst; Wenn die Binärzahl mit '0' endet, endet dieser Ausdruck, ...+-0der als "negative 0 hinzufügen" analysiert wird und somit das nachfolgende Pluszeichen beseitigt.

Greg Martin
quelle
2

Matlab, 99 Bytes

function c=z(b)
c=0;b=strsplit(dec2bin(b),'0');for j=1:numel(b)-isempty(b{end});c=c+i^nnz(b{j});end

Testfälle:

z(656) = 3i
z(172) = -1 + 2i
z(707) = -2 + i
z(32)  = i
z(277) = 4i
Owen Morgan
quelle
2

Haskell, 102 91 89 87 Bytes

0%a=a
n%c@[a,b]|odd n=div n 2%[-b,a]|d<-div n 2=zipWith(+)c$d%[mod d 2,0]
(%[0,0]).(*2)

Dividiert wiederholt durch zwei und überprüft das Bit. Behält einen Akkumulator bei, i^(number of odds)in dem angegeben a+b*iist, wie [a,b]und wie er *iist [a,b]↦[-b,a](Drehung um 90 Grad). Die Initiale (*2)besteht darin, eine Suche nach dem ersten Bit zu vermeiden.

Verwendung (Danke an @OwenMorgan für die Beispiele):

(%[0,0]).(*2)<$>[656,172,707,32,277]
[[0,3],[-1,2],[-2,1],[0,1],[0,4]]
Angs
quelle
1

Java, 172 Bytes

l->{int i=0,j=i;for(String x:l.toString(2).split("0")){int a=x.length();j+=a&1>0?(a&3>2?(a-3)/-4+1:(a-3)/4+1):0;i+=a&1<1?(a&3>1?(a-3)/4+1:(a-3)/-4+1):0;}return i+"|"j+"i";}
Roman Gräf
quelle
1

Clojure, 183 Bytes

#(loop[x(clojure.string/split(Integer/toString % 2)#"0+")y[0 0]a 0](if(= a(count x))y(recur x(let[z([[1 0][0 1][-1 0][0 -1]](mod(count(x a))4))][(+(y 0)(z 0))(+(y 1)(z 1))])(inc a))))

Darf ich das tun?

Verwenden Sie die Funktion wie folgt:

(#(...) {num}) -> (Wrap the # function in brackets first!)
Clismique
quelle
1

Eigentlich 35 Bytes

├'0' aÆô' @s"j+"j'jo`"1j*1"'1τ(Æ`Y≡

Probieren Sie es online!

Erläuterung:

├'0' aÆô' @s"j+"j'jo`"1j*1"'1τ(Æ`Y≡
├                                    binary representation of input
 '0' aÆ                              replace 0s with spaces
       ô                             trim leading and trailing spaces
        ' @s                         split on spaces
            "j+"j                    join with "j+"
                 'jo                 append "j"
                    `"1j*1"'1τ(Æ`Y   do until the string stops changing (fixed-point combinator):
                     "1j*1"'1τ(Æ       replace "11" with "1j*1"
                                  ≡  evaluate the resulting string to simplify it

Etwa gleichwertiger Python 3-Code:

a='j+'.join(bin(eval(input()))[2:].replace('0',' ').strip().split())+'j'
b=0
while a!=b:b,a=a,a.replace("11","1j*1")
print(eval(a))

Probieren Sie es online!

Mego
quelle
Wenn Sie die Nullen mit '0@sund mit ``░teilen, um alle nachgestellten leeren Zeichenfolgen abzuschneiden, sparen Sie vier Bytes.
Sherlock9
1

Gelee , 10 Bytes

Dies ist nicht besser als Dennis 'Gelee-Antwort, aber ich wollte mich trotzdem an einer Gelee-Antwort versuchen. Golfvorschläge willkommen! Probieren Sie es online!

BŒrm2Ṫ€ı*S

Ungolfing

BŒrm2Ṫ€ı*S   Main link. Argument: n (integer)

B            Convert n to binary.
 Œr          Run-length encode the binary list.
   m2        Every 2nd element of the run_length encoding, getting only the runs of 1s.
     Ṫ€      Tail each, getting only the lengths of the runs.
       ı*    The imaginary unit raised to the power of each run (as * is vectorized).
         S   Sum it all into one complex number.
Sherlock9
quelle
Im obigen Link Der Eingang 1 gibt 1j zurück, der Eingang 2 gibt 1j zurück. Stimmt das?
RosLuP
@RosLuP Ja, das stimmt? Da wir nachfolgende Nullen entfernen, 1 => 1 => 1jist dies äquivalent zu 2 => 10 => 1 => 1j.
Sherlock9
1

Eigentlich 15 Bytes

Golfvorschläge willkommen! Probieren Sie es online!

├'0@s``░`lïⁿ`MΣ

Ungolfing:

         Implicit input n.
├        Convert n to binary.
'0@s     Split by '0's.
``░      Filter out non-truthy values.
`...`M   Map over the filtered result, a list of runs of '1's.
  l        Yield the length of the run of '1's.
  ïⁿ       Yield the imaginary unit to the power of that length.
Σ        Sum all of this into one complex number.
Sherlock9
quelle
0

Axiom, 140, 131, 118, 108 Bytes

b(x)==(s:=0;repeat(x=0=>break;r:=x rem 2;repeat(x rem 2=1=>(r:=r*%i;x:=x quo 2);break);s:=s+r;x:=x quo 2);s)

% i ist der imaginäre Costant.Ungolfed

sb(x:NNI):Complex INT==
  r:Complex INT;s:Complex INT:=0
  repeat
    x=0=>break
    r:=x rem 2
    repeat
       x rem 2=1=>(r:=r*%i;x:=x quo 2)
       break
    s:=s+r
    x:=x quo 2
  s

Ergebnisse

(3) -> b 4538
   The type of the local variable r has changed in the computation.
   We will attempt to interpret the code.
   (3)  - 1 + %i
                                                    Type: Complex Integer
(4) -> b 29
   (4)  0
                                                    Type: Complex Integer
(5) -> sb 299898979798233333333333333339188888888888888888222
   Compiling function sb with type NonNegativeInteger -> Complex Integer
   (5)  - 7 + 12%i
                                                    Type: Complex Integer
(6) -> b 299898979798233333333333333339188888888888888888222
   (6)  - 7 + 12%i
                                                    Type: Complex Integer
RosLuP
quelle
0

Perl 6 ,  40  46 Bytes

Das habe ich mir ziemlich schnell ausgedacht

*.base(2).comb(/1+/).map(i***.chars).sum

Leider ist es derzeit in der Rakudo- Implementierung auf MoarVM ungenau .
say i ** 3; # -1.83697019872103e-16-1i

Also musste ich das nächstbeste machen:

*.base(2).comb(/1+/).map({[*] i xx.chars}).sum

Erweitert:

*\             # Whatever lambda
.base(2)       # convert to a Str representation in base 2
.comb(/ 1+ /)  # get a list of substrings of one or more 「1」s
.map({         # for each of those

  [*]            # reduce using 「&infix:<**>」
    i xx .chars    # 「i」 list repeated by the count of the characters matched

}).sum          # sum it all up

Prüfung:

.say for (4538, 29).map:

    *.base(2).comb(/1+/).map({[*] i xx.chars}).sum

# -1+1i
# 0+0i
Brad Gilbert b2gills
quelle
Fehlerbericht
0

PHP, 87 Bytes

for($n=$argv[1];$n|$i;$n>>=1)$n&1?$i++:($i?$i=0*${$i&1}+=1-($i&2):0);echo"(${0},${1})";

Fast wie die Lösung von ETHproductions; nur iterativ statt rekursiv.
Übernimmt Eingaben von der Kommandozeile, setzt Variablen ${0}und ${1}.

Titus
quelle
0

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

Prompt X
0→S
0→N
While X
If remainder(X,2
Then
N+1→N
int(X/2→X
Else
S+i^Nnot(not(N→S
X/2→X
0→N
End
End
S+i^Nnot(not(N

Es gibt keinen eingebauten Code zum Konvertieren in eine Binärzeichenfolge (und auch keinen zum Parsen einer Zeichenfolge). Daher teilt dieses Programm manuell durch 2, inkrementiert N jedes Mal, wenn es eine 1 sieht, und fügt i ^ N zu S (N> 0) hinzu und setzt zurück N, wenn eine Null angezeigt wird.

Pizzapants184
quelle
0

R , 54 Bytes

function(n,x=rle(n%/%2^(0:log2(n))%%2))sum(1i^x$l*x$v)

Probieren Sie es online!

n%/%2^(0:log2(n))%%2berechnet einen Vektor der Binärziffern. Unter Verwendung der Lauflängencodierung verwenden wir den complexTyp von R , um die entsprechende Summe zu berechnen, und multiplizieren sie mit x$values, um Nullen zu entfernen.

Gibt einen complexVektor eines Elements zurück.

Giuseppe
quelle