Addition in der Basis -1 + i

64

Gaußsche Ganzzahlen sind komplexe Zahlen der Form a+biwobei aund bbeide Ganzzahlen sind. In der Basis -1 + i können alle Gaußschen Ganzzahlen mit den Ziffern 0und eindeutig dargestellt werden 1, ohne dass ein Symbol für das Vorzeichen erforderlich ist.

Zum Beispiel steht 1100in der Basis -1 + i für die Dezimalzahl 2, da

1*(-1+i)^3 + 1*(-1+i)^2 + 0*(-1+i)^1 + 0*(-1+i)^0
= (2+2i) + (-2i) + 0 + 0
= 2

Die Eingabe besteht aus zwei Gaußschen Ganzzahlen zur Basis -1 + i, die anhand der Ziffern dargestellt werden 01. Dies kann eine der folgenden Formen annehmen:

  • Zwei getrennte Ziffernfolgen,
  • Zwei Dezimalzahlen, die aus der 01Darstellung der Zahlen zur Basis -1 + i bestehen (z. B. 1100für 2 zur Basis -1 + i),
  • Zwei binäre Ganzzahlen, die die Basis-1 + i-Zahlen darstellen (z. B. dezimal 12oder 0b1100für 2 in Basis-1 + i)
  • Eine einzelne Zeichenfolge, die zweistellige Zeichenfolgen / binäre Ganzzahlen durch ein einzelnes nicht-alphanumerisches Trennzeichen trennt (z. B. 1100 1100oder 12,12für 2 + 2)

Geben Sie die Summe der beiden Gaußschen Ganzzahlen aus, ebenfalls in der Basis -1 + i und mit den Ziffern dargestellt 01(in einem der als Eingabe zulässigen Formate, nicht unbedingt die gleiche Wahl). Die Ausgabe darf eine endliche Anzahl führender Nullen enthalten.

Ihre Funktion oder Ihr Programm muss bei Eingaben mit jeweils höchstens 30 Stellen innerhalb von 2 Sekunden beendet sein.

Zusätzliche Klarstellungen

  • Sie können davon ausgehen, dass die Eingabe keine führenden Nullen enthält. Für den Sonderfall 0 können Sie entweder eine 0oder eine leere Zeichenfolge als Darstellung auswählen .

Testfälle

0, 0 => 0                                      # 0 + 0 = 0
0, 1 => 1                                      # 0 + 1 = 1
1, 1 => 1100                                   # 1 + 1 = 2
1100, 1100 => 111010000                        # 2 + 2 = 4
1101, 1101 => 111011100                        # 3 + 3 = 6
110111001100, 1110011011100 => 0               # 42 + (-42) = 0
11, 111 => 0                                   # i + (-i) = 0
11, 110 => 11101                               # i + (-1-i) = -1
10101, 11011 => 10010                          # (-3-2i) + (-2+3i) = (-5+i)
1010100101, 111101 => 1110100000100            # (-19+2i) + (3-4i) = (-16-2i)

Längere Testfälle:

11011011010110101110010001001, 111100010100101001001010010101 => 0
111111111111111111111111111111, 111111111111111111111111111111 => 100100100100100100100100100100
101101110111011101110111011101, 101101110111011101110111011101 => 11101001010001000100010001000100011100
100100010101001101010110101010, 100010011101001011111110101000 => 110000110010101100001100111100010
Sp3000
quelle
Keine Ziffernlisten?
CalculatorFeline
@CatsAreFluffy Keine Ziffernlisten, sorry.
Sp3000
96
Sie können , indem ein Byte speichern , -1+ium i-1in dem Titel.
mbomb007
1
Jetzt brauchen wir eine Umstellung in umgekehrter Richtung. : P
Rɪᴋᴇʀ
3
Es gibt 1100 Arten von Menschen auf der Welt. Diejenigen, die binär verstehen, die nicht, die, die es mit ternär verwechseln, die, die es mit Basis 4 verwechseln, die, die es mit Basis 5 verwechseln, die, die es mit Basis -1 + i verwechseln, die, die es mit Basis 5 verwechseln Basis 6, diejenigen, die es mit Basis 7 verwechseln, diejenigen, die es mit Basis 8 verwechseln, diejenigen, die es mit Basis 9 verwechseln ...
wizzwizz4

Antworten:

42

Python 2, 98 97 91 84 Bytes

s=input();L=1
for _ in`s`*8:s+=1098*int(str(s).translate('0011'*64));L*=10
print s%L

Dies führt E / A dezimal aus. Die Ganzzahlen müssen durch nicht alphanumerische Zeichen getrennt werden +.

Vielen Dank an @xnor für das Golfen mit 2 Bytes!

Probieren Sie es auf Ideone .

Wie es funktioniert

In Arithmetic in Complex Bases zeigt der Autor, wie komplexe Zahlen in Basen der Form -n + i addiert und multipliziert werden .

Für die Basis -1 + i erfolgt die Addition ähnlich wie bei der regulären binären Addition mit Übertrag, mit zwei Unterschieden:

  • Anstatt 1 zur nächsthöheren Position zu tragen, tragen wir 110 zu den nächsten drei.

  • Carry Digits können sich unbegrenzt ausbreiten. Ohne führende Nullen hat die Summe a + b höchstens acht Stellen mehr als das Maximum von a und b .

Wir gehen wie folgt vor.

  1. Zuerst fügen wir a und b so hinzu, als ob ihre Ziffern Dezimalstellen wären.

    Für a = 10101 und b = 11011 ergibt dies 21112 .

  2. Als nächstes bilden wir eine neue Zahl, indem wir die Ziffern größer als 1 durch eine 1 ersetzen , andere durch eine 0 . 1

    Für die Summe 21112 ergibt dies 10001 .

  3. Für jede Ziffer, die größer als 1 ist , müssen wir 2 von dieser Ziffer abziehen und 110 zu den nächsten drei höheren Stellen befördern. Da 1098 = 10 * 110 - 2 , können wir dies erreichen, indem wir das Ergebnis aus Schritt 2 mit 1098 multiplizieren und dieses Produkt dann zur Summe addieren. 2

    Für die Summe 21112 ergibt sich 21112 + 1098 * 10001 = 21112 + 10981098 = 11002210 .

  4. Wir wiederholen die Schritte 2 und 3 insgesamt 8 Mal, wobei d die Anzahl der Stellen von a + b ist . 3

    Für die Anfangssumme 21112 lauten die Ergebnisse

                          11002210
                          12210010
                        1220010010
                      122000010010
                    12200000010010
                  1220000000010010
                122000000000010010
              12200000000000010010
            1220000000000000010010
          122000000000000000010010
        12200000000000000000010010
      1220000000000000000000010010
    122000000000000000000000010010
                                 .
                                 .
                                 .
    
  5. Wir nehmen die Endsumme modulo 10 d + 8 und verwerfen alle bis auf die letzten d + 8 Ziffern.

    Für die Anfangssumme 21112 lautet das Endergebnis 10010 .


1 Dies wird mit translate erreicht . Das 64-fache Wiederholen der Zeichenfolge 0011 bewirkt, dass eine Wiederholung mit der Folge der ASCII-Zeichen 0123 übereinstimmt und die gewünschte Ersetzung erzielt wird.

2 anzumerken , dass die Ziffern dieser Summe können nicht überschreiten 3 (Anfangswert 1 plus zwei 1 ‚s aus trägt).

3 Dies funktioniert ansonsten für d = 1 und d * 8> d + 8 . Der Code kann die Schritte (d + 1) * 8 Mal wiederholen , da s ein nachgestelltes L hat, wenn s eine lange Ganzzahl ist.

Dennis
quelle
7
Das ist tiefe Magie . Welches Format input()erwartet Sie? (Ich bekomme, 21112wenn ich 10101, 11011
eingebe
1
Keine Ursache; Das war eine Version, die in Python 3 übersetzt wurde (anscheinend ohne Erfolg). Unter Python 2 funktioniert sie einwandfrei .
Tim Pederick
9
...Wie. Bitte. Erklären.
Nic Hartley
@ QPaysTaxes Ich habe meine Antwort bearbeitet.
Dennis
@Dennis Könntest du jetzt erklären, warum das funktioniert? Zum Beispiel warum d+8und nicht sagen d+9? Wie????
Nic Hartley
16

Pyth, 34 Bytes

_shM.u,%J/eMeN\12-+PMeNm.B6/J2k,kQ

Probieren Sie es online aus: Demo oder Test Suite (dauert eine Weile). Es sollte die zeitliche Beschränkung allerdings problemlos erfüllen, da der Online-Compiler im Vergleich zum normalen (Offline-) Compiler recht langsam ist.

Erläuterung:

Mein Algorithmus ist im Grunde eine Implementierung der Addition mit dem Tragen. Aber anstatt zu tragen 1, muss ich tragen 110( 1100in der Basis -1+iist das gleiche wie 2in der Basis -1+i). Dies funktioniert meistens gut, aber Sie können in einer Endlosschleife stecken bleiben und Nullen drucken. Zum Beispiel , wenn Sie hinzufügen , 1mit , 11und haben zur Zeit den Übertrag 110. Also füge ich im Grunde hinzu, bis ich in einer Schleife stecke und dann aufhöre. Ich denke, dass eine Schleife, die eine Schleife immer Nullen drucken wird und daher sollte dies in Ordnung sein.

_shM.u,%J/eMeN\12-+PMeNm.B6/J2k,kQ   implicit: Q = input list of strings
                               ,kQ   create the pair ["", Q]
    .u                               modify the pair N (^) until loop:
      ,                                replace N with a new pair containing:
            eN                           N[1] (the remaining summand)
          eM                             take the last digits of each summand
         /    \1                         count the ones
        J                                store the count in J
       %J       2                        J % 2 (this is the first element of the new pair)
                   PMeN                  remove the last digit of each summand
                  +    m   /J2           and add J / 2 new summand:
                        .B6                 with the value "110" (binary of 6)
                 -            k          remove empty summand
    .u                               returns all intermediate results
  hM                                 extract the digits
 s                                   sum them up to a long string
_                                    reverse
Jakube
quelle
13

Python 2, 69 67 Bytes

f=lambda a,b:a*a+b*b^58and 2*f(a*b%2*6,f(a/2,b/2))|a+b&1if a else b

Die Ein- / Ausgabe erfolgt mit Ganzzahlen zur Basis 2.

-2 Danke @Dennis.

Feersum
quelle
Ich nehme es a*a+b*b^58==0wann aund bsind invers? Wie funktioniert das?
Xnor
@xnor Nein, a*a+b*b==58wenn einer von ihnen 3 ist und der andere 7.
feersum
1
Mir (3,7)ist nicht klar, dass dies das einzige Paar ist, das einen Zyklus gibt und eine spezielle Hülle benötigt. Wenn dies zutrifft, müssen Sie (a,b)==(3,7)diese Reihenfolge nur einchecken , da dies (7,3)wiederholt (3,7)wird. Vielleicht gibt es dafür einen kürzeren Ausdruck.
Xnor
1
Dies wird jetzt garantiert jeden verwirren, der nicht weiß (oder vergisst), dass (a) ^XOR ist, keine Potenzierung, oder (b) XOR hat eine niedrigere Priorität als +.
Tim Pederick
12

Retina , 100 Bytes

r+`(.*)(\d|(?!\4))( .*)(.?)
$2$4:$1$3
T` 0
+`1:11(1*:1*)11
:$1
^:*
:::
}`:(1*:1*:)11
1:1$1
(1)*:
$#1

Dies nimmt die Eingabe mit einem Komma getrennt. Die Ausgabe beginnt immer mit drei führenden Nullen.

Probieren Sie es online!

Ich frage mich wirklich, ob es eine kürzere Lösung für die erste Stufe gibt ...

Martin Ender
quelle
2
Nein, nein, das Ergebnis ist perfekt wie es ist;)
Conor O'Brien
2
Nizza Punktzahl von -2i!
Nic Hartley
Beeindruckend. Ich habe diese Lösung nicht gesehen, als ich meine gepostet habe ... Viel überlegener als meine Lösung.
Undichte Nonne
@KennyLau Ich habe es nur angeschaut und gedacht "hm, ich denke, ich hätte irgendwann eine Erklärung hinzufügen sollen ..."
Martin Ender
...- 2i? Dies ist dezimal, aber das Programm verwendet eine Basis, die nicht.
User75200
12

Jelly, 29 28 26 24 21 20 Bytes

DBḅ1100ḌµDL+8µ¡Dṣ2ṪḌ

Dies führt E / A dezimal aus. Die Ganzzahlen müssen durch nicht alphanumerische Zeichen getrennt werden +.

Probieren Sie es online! oder überprüfen Sie alle Testfälle .

Hintergrund

In Arithmetic in Complex Bases zeigt der Autor, wie komplexe Zahlen in Basen der Form -n + i addiert und multipliziert werden .

Für die Basis -1 + i erfolgt die Addition ähnlich wie bei der regulären binären Addition mit Übertrag, mit zwei Unterschieden:

  • Anstatt 1 zur nächsthöheren Position zu tragen, tragen wir 110 zu den nächsten drei.

  • Carry Digits können sich unbegrenzt ausbreiten. Ohne führende Nullen hat die Summe a + b höchstens acht Stellen mehr als das Maximum von a und b .

Wir gehen wie folgt vor.

  1. Zuerst fügen wir a und b so hinzu, als ob ihre Ziffern Dezimalstellen wären.

    Für a = 10101 und b = 11011 ergibt dies 21112 .

  2. Für jede Ziffer, die größer als 1 ist , müssen wir 2 von dieser Ziffer abziehen und 110 zu den nächsten drei höheren Stellen befördern. Wir können dies erreichen , indem jede Dezimalziffer in binärer Umwandlung, die sie ergebenden binäre Arrays von der Basis 1100 zu ganzer Zahl und interpretiert die resultierende Liste von 0 's, 1 s, 1100 s und 1101 ' s als eine nicht-kanonischen Basen 10 Nummer. 1

    Für die Summe 21112 ergibt sich 21112 + 1098 * 10001 = 21112 + 10981098 = 11002210 .

  3. Wir wiederholen die Schritte 2 a insgesamt 8 Mal, wobei d die Anzahl der Stellen von a + b ist .

    Für die Anfangssumme 21112 lauten die Ergebnisse

                          11002210
                          12210010
                        1220010010
                      122000010010
                    12200000010010
                  1220000000010010
                122000000000010010
              12200000000000010010
            1220000000000000010010
          122000000000000000010010
        12200000000000000000010010
      1220000000000000000000010010
    122000000000000000000000010010
    
  4. Wir verwerfen alle bis auf die letzten d + 8 Ziffern des Endergebnisses. Dies wird erreicht, indem alles nach den letzten 2 verworfen wird . 2

    Für die Anfangssumme 21112 lautet das Endergebnis 10010 .

Wie es funktioniert

DBḅ1100ḌµDL+8µ¡Dṣ2ṪḌ  Main link. Argument: a + b (implicit sum)

        µ    µ¡       Execute the chain before the first µ n times, where n is
                      the result of executing the chain before the second µ.
         D            Convert a + b to base 10.
          L           Length; count the decimal digits.
           +8         Add 8 to the number of digits.
D                     Convert the initial/previous sum to base 10.
 B                    Convert each digit (0 - 3) to binary.
  ḅ1100               Convert each binary array from base 1100 to integer.
       Ḍ              Interpret the resulting list as a base 10 number.
               D      Convert the final sum to base 10.
                ṣ2    Split at occurrences of 2.
                  Ṫ   Select the last chunk.
                   Ḍ  Convert from base 10 to integer.

1 anzumerken , dass die Ziffern dieser Summe nicht überschreiten können 3 (Anfangswert 1 plus zwei 1 ‚s aus trägt).

2 Dies funktioniert, weil die letzte Ziffer, die gelöscht wird, keine 3 sein kann .

Dennis
quelle
6

Python 3, 289 Bytes

Dies führt eine ziffernweise Addition von der niedrigsten zur höchstwertigen Ziffer durch (mit anderen Worten, der exakt gleiche Algorithmus, den Sie in der Grundschule unterrichtet haben). Die Unterschiede bestehen darin, dass (a) es sich um eine Binärzahl und nicht um eine Dezimalzahl handelt. Sie tragen also immer dann, wenn eine Ziffer 2 oder mehr ist, und (b) 1 + 1 = 1100nicht 10.

Tatsächlich ist es auch notwendig zu beachten, dass 11 + 111 = 0andernfalls Summen, die Null werden sollten, niemals enden.

from collections import*
def a(*s,p=0):
 r=defaultdict(int,{0:0})
 for S in s:
  n=0
  for d in S[::-1]:r[n]+=d=='1';n+=1
 while p<=max(r):
  while r[p]>1:
   r[p]-=2
   if r[p+1]>1<=r[p+2]:r[p+1]-=2;r[p+2]-=1
   else:r[p+2]+=1;r[p+3]+=1
  p+=1
 return str([*map(r.get,sorted(r))])[-2::-3]

Mehr Golfen ist sicher möglich.

Tim Pederick
quelle
Wie sicher sind Sie sich, dass Ihr "Nulldetektor" ausreicht?
Yakk
4
@Yakk: Auf einer Skala von 1 bis Peer-Review-Journal, vielleicht noch keine Gegenbeispiele?
Tim Pederick
2

Retina, 157 151 134 133 124 123 Bytes

Dank an Martin Büttner 1 Byte weg.

(.+),(.+)
$.1$*0$2,$.2$*0$1,
1
0x
+`(0x*)(,.*)0(x*),
$2,$1$3
{`,

(^|0x0xx0xx)
000
(0x*)(0x*)(0x*0)xx
$1x$2x$3
)`^0+
0
0x
1

Probieren Sie es online!

Konvertiert nach Unary und wiederholt dann die folgenden Ersetzungen (hier in Dezimalzahl):

122 -> 000
0002 -> 1100 (this can also be 0012 -> 1110 and 1112 -> 2210 or even 2222 -> 3320 or even 3333 -> 4431)

Grundsätzlich gilt: Wenn größer als zwei, nehmen Sie zwei weg, fügen Sie nichts zur vorherigen Ziffer hinzu, fügen Sie eine zur vorherigen Ziffer hinzu und fügen Sie dann eine zur vorherigen Ziffer hinzu.

Im Pseudocode:

if(a[n]>2):
    a[n] -= 2;
    a[n-2] += 1;
    a[n-3] += 1;

Unäre Implementierung:

Jede Ziffer (z. B. 3) wird als Anzahl von xs (z. B. ) angezeigt xxxund mit einem Präfix versehen 0.

Zum Beispiel 1234würde ausgedrückt als 0x0xx0xxx0xxxx.

Dies bleibt 0unverändert, wie 101durch ausgedrückt werden würde 0x00x.

Da es anfangs und schließlich nur 0und gibt 1, könnte die Konvertierung leicht von 1->0xund durchgeführt werden 0x->1.

Klicken Sie hier, um alle Schritte anzuzeigen .

Undichte Nonne
quelle
1

JavaScript (ES6), 146 126 Bytes

r=n=>n&&n%2-r(n>>=1)-i(n)
i=n=>n&&r(n>>=1)-i(n)
g=(x,y,b=(x^y)&1)=>x|y&&b+2*g(b-x+y>>1,b-x-y>>1)
(x,y)=>g(r(x)+r(y),i(x)+i(y))

gwandelt eine Gaußsche ganze Zahl (Real- und Imaginärteil) in der Basis i-1, während rund iwandelt eine i-1Basisganzzahl in eine Gaußsche ganzen Zahl (Real- und Imaginärteil bzw.). Sobald die Konvertierungen abgeschlossen sind, muss ich nur noch rechnen.

Bearbeiten: Durch getrennte Berechnung von Real- und Imaginärteil werden 20 Byte gespeichert.

Neil
quelle
1

C ++ 416 Bytes plus #include <vector>\n#include <algorithm>\n(weitere 40)

using I=int;using v=std::vector<I>;void r(v&x){v r{rbegin(x),rend(x)};x=r;}v a(v L,v R){r(L);r(R);L.resize(std::max(L.size(),R.size()));for(int&r:R)L[&r-R.data()]+=r;while(1){L.resize(L.size()+3);auto it=find(rbegin(L),rend(L),2);if(it==rend(L))break;I i=-1+it.base()-begin(L);i&&L[i+1]&&L[i-1]/2?L[i+1]=L[i]=L[i-1]=0:(++L[i+2],++L[i+3],L[i]=0);}L.erase( std::find(rbegin(L),rend(L),1).base(),end(L));r(L);return L;}

oder mit mehr Leerzeichen:

using I=int;
using v=std::vector<I>;

void r(v&x){v r{rbegin(x),rend(x)};x=r;}
v a(v L,v R) {
  r(L);r(R);
  L.resize(std::max(L.size(),R.size()));
  for(int&r:R)
    L[&r-R.data()]+=r;
  while(1) {
    L.resize(L.size()+3);
    auto it=find(rbegin(L), rend(L), 2);
    if(it==rend(L)) break;
    I i=-1+it.base()-begin(L);
    i&&L[i+1]&&L[i-1]/2?
      L[i+1]=L[i]=L[i-1]=0
    :
      (++L[i+2],++L[i+3],L[i]=0);
  }
  L.erase( std::find(rbegin(L),rend(L),1).base(), end(L));
  r(L);
  return L;
}

Kaum Golf gespielt. Es nimmt Eingaben als Vektor von Ints entgegen und gibt einen Vektor von Ints zurück.

Live-Beispiel .

Yakk
quelle