Penambahan di basis -1 + i


64

Bilangan bulat gaussian adalah bilangan kompleks dari bentuk di a+bimana adan bkeduanya bilangan bulat. Dalam basis -1 + i, semua bilangan bulat Gaussian dapat diwakili secara unik menggunakan digit 0dan 1, tanpa perlu simbol untuk menunjukkan tanda.

Misalnya, 1100dalam basis -1 + i mewakili angka desimal 2, karena

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

Input akan berupa dua bilangan bulat Gaussian di basis -1 + i yang diwakili menggunakan digit 01. Ini dapat mengambil salah satu bentuk berikut:

  • Dua string angka yang terpisah,
  • Dua bilangan bulat desimal yang terdiri dari 01mewakili basa -1 + i angka (misalnya 1100untuk 2 di basis -1 + i),
  • Dua bilangan bulat biner yang mewakili angka dasar -1 + i (mis. Desimal 12atau 0b1100untuk 2 pada basis -1 + i)
  • Sebuah string tunggal yang memisahkan dua digit string / integer biner oleh pemisah non-alfanumerik tunggal (misalnya 1100 1100atau 12,12untuk 2 + 2)

Keluarkan jumlah dari dua bilangan bulat Gaussian, juga dalam basis -1 + i dan diwakili menggunakan digit 01(dalam salah satu format yang diizinkan sebagai input, tidak harus pilihan yang sama). Outputnya diizinkan mengandung angka nol terdepan yang terbatas.

Fungsi atau program Anda harus berakhir dalam 2 detik untuk input paling banyak masing-masing 30 digit.

Klarifikasi tambahan

  • Anda dapat berasumsi bahwa input tidak mengandung nol terkemuka di luar. Untuk kasus khusus 0, Anda dapat memilih salah satu 0atau string kosong sebagai representasi.

Uji kasus

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)

Kasus uji yang lebih panjang:

11011011010110101110010001001, 111100010100101001001010010101 => 0
111111111111111111111111111111, 111111111111111111111111111111 => 100100100100100100100100100100
101101110111011101110111011101, 101101110111011101110111011101 => 11101001010001000100010001000100011100
100100010101001101010110101010, 100010011101001011111110101000 => 110000110010101100001100111100010

Tidak ada daftar digit?
CalculatorFeline

@CatsAreFluffy Tidak ada daftar angka, maaf.
Sp3000

96
Anda dapat menyimpan satu byte dengan mengubah -1+ike i-1dalam judul.
mbomb007

1
Sekarang kita perlu konversi sebaliknya. : P
R

3
Ada 1.100 tipe orang di dunia. Mereka yang mengerti biner, mereka yang tidak, mereka yang mengacaukannya dengan ternary, mereka yang mengacaukannya dengan basis 4, mereka yang mengacaukannya dengan basis 5, mereka yang bingung dengan basis -1 + i, mereka yang bingung dengan base 6, mereka yang bingung dengan base 7, mereka yang bingung dengan base 8, mereka yang bingung dengan base 9 ...
wizzwizz4

Jawaban:


42

Python 2, 98 97 91 84 byte

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

Ini saya / O dalam desimal. Bilangan bulat harus dipisahkan oleh karakter non-alfanumerik +.

Terima kasih kepada @xnor karena bermain golf 2 byte!

Cobalah di Ideone .

Bagaimana itu bekerja

Dalam Aritmatika dalam Basa Kompleks , penulis menunjukkan cara menambahkan dan mengalikan bilangan kompleks dalam basis -n + i .

Untuk basis -1 + i , penambahan dilakukan mirip dengan penambahan biner biasa dengan carry, dengan dua perbedaan:

  • Alih-alih membawa 1 ke posisi lebih tinggi berikutnya, kami membawa 110 ke tiga berikutnya.

  • Membawa angka dapat diperbanyak tanpa batas. Namun, tanpa angka nol di depan, jumlah a + b memiliki paling banyak delapan digit lebih dari maksimum a dan b .

Kami melanjutkan sebagai berikut.

  1. Pertama, kita menambahkan a dan b seolah-olah digit mereka adalah angka desimal.

    Untuk a = 10101 dan b = 11011 , ini memberikan 21112 .

  2. Selanjutnya, kami membentuk angka baru dengan mengganti angka yang lebih besar dari 1 dengan 1 , yang lain dengan 0 . 1

    Untuk jumlah 21112 , ini memberi 10001 .

  3. Untuk setiap digit yang lebih besar dari 1 , kita harus mengurangi 2 dari angka itu dan membawa 110 ke tiga posisi berikutnya yang lebih tinggi. Karena 1098 = 10 * 110 - 2 , kita dapat mencapai ini dengan mengalikan hasil dari langkah 2 dengan 1098 , lalu menambahkan produk tersebut ke jumlah. 2

    Untuk jumlah 21112 , ini memberi 21112 + 1098 * 10001 = 21112 + 10981098 = 11002210 .

  4. Kami mengulangi langkah 2 dan 3 total d * 8 kali, di mana d adalah jumlah digit a + b . 3

    Untuk jumlah awal 21112 , hasilnya adalah

                          11002210
                          12210010
                        1220010010
                      122000010010
                    12200000010010
                  1220000000010010
                122000000000010010
              12200000000000010010
            1220000000000000010010
          122000000000000000010010
        12200000000000000000010010
      1220000000000000000000010010
    122000000000000000000000010010
                                 .
                                 .
                                 .
    
  5. Kami mengambil jumlah akhir modulo 10 d + 8 , membuang semua kecuali d + 8 digit terakhir.

    Untuk jumlah awal 21112 , hasil akhirnya adalah 10010 .


1 Ini dicapai dengan terjemahan . Mengulang string 0011 64 kali membuat satu pengulangan berbaris dengan urutan karakter ASCII 0123 , mencapai penggantian yang diinginkan.

2 Perhatikan bahwa angka-angka dari jumlah ini tidak dapat melebihi 3 (nilai awal 1 ditambah dua 1 dari carry).

3 Ini berlaku untuk d = 1 , dan d * 8> d + 8 sebaliknya. Kode dapat mengulangi langkah-langkah (d + 1) * 8 kali, karena s memiliki trailing L jika s adalah bilangan bulat panjang .


7
Ini sihir yang dalam . Format apa yang input()diharapkan? (Saya dapatkan 21112ketika saya input 10101, 11011.)
Tim Pederick

1
Lupakan; yang menjalankan versi yang diterjemahkan (tidak berhasil, tampaknya) ke Python 3. Ini berfungsi dengan baik di bawah Python 2 .
Tim Pederick

9
...Bagaimana. Silahkan. Menjelaskan.
Nic Hartley

@QPaysTaxes Saya sudah mengedit jawaban saya.
Dennis

@ Dennis Sekarang, bisakah Anda menjelaskan mengapa itu berhasil? Misalnya, mengapa d+8dan tidak, katakanlah d+9,? Bagaimana????
Nic Hartley

16

Pyth, 34 byte

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

Cobalah online: Demonstrasi atau Test Suite (membutuhkan waktu cukup lama). Ini harus memenuhi batasan waktu dengan mudah, karena kompiler online cukup lambat dibandingkan dengan kompiler normal (offline).

Penjelasan:

Algoritma saya pada dasarnya adalah implementasi dari penambahan dengan membawa. Tapi alih-alih membawa 1, saya harus membawa 110( 1100di pangkalan -1+isama dengan 2di pangkalan -1+i). Ini berfungsi sebagian besar baik-baik saja, tetapi Anda bisa terjebak dalam nol nol pencetakan lingkaran tak terbatas. Misalnya jika Anda menambahkan 1dengan 11dan saat ini memiliki carry 110. Jadi saya pada dasarnya menambahkan sampai saya terjebak dalam satu lingkaran dan kemudian berhenti. Saya berpikir bahwa loop yang loop akan selalu mencetak nol dan karena itu ini harus baik-baik saja.

_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

13

Python 2, 69 67 byte

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

I / O dilakukan dengan basis 2 integer.

-2 terima kasih @Dennis.


Saya menerimanya a*a+b*b^58==0kapan adan bapakah itu invers? Bagaimana cara kerjanya?
xnor

@xnor Tidak, a*a+b*b==58ketika salah satu dari mereka adalah 3 dan yang lainnya adalah 7.
feersum

1
Tidak jelas bagi saya bahwa (3,7)hanya pasangan yang memberikan siklus dan membutuhkan casing khusus. Jika itu benar, maka Anda hanya perlu memeriksa (a,b)==(3,7)urutan itu, sejak (7,3)berulang hingga (3,7), dan mungkin ada ungkapan yang lebih pendek untuk itu.
xnor

1
Sekarang ini dijamin membingungkan siapa saja yang tidak tahu (atau lupa) bahwa (a) ^adalah XOR, bukan eksponensial, atau (b) XOR memiliki prioritas lebih rendah daripada +.
Tim Pederick

12

Retina , 100 byte

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

Ini mengambil input yang dipisahkan dengan koma. Output selalu dimulai dengan tiga nol terkemuka.

Cobalah online!

Saya benar-benar bertanya-tanya apakah ada solusi yang lebih pendek untuk tahap pertama ...


2
Tidak, tidak, skornya sempurna;)
Conor O'Brien

2
Skor bagus -2i!
Nic Hartley

Wow. Saya tidak melihat solusi ini ketika saya memposting milik saya ... Jauh lebih unggul daripada solusi saya.
Leaky Nun

@ KennyLau, saya baru saja melihatnya dan berpikir "hm, saya kira saya harus menambahkan penjelasan di beberapa titik ..."
Martin Ender

...- 2i? Ini desimal tetapi program menggunakan basis yang tidak.
user75200

12

Jelly, 29 28 26 24 21 20 byte

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

Ini saya / O dalam desimal. Bilangan bulat harus dipisahkan oleh karakter non-alfanumerik +.

Cobalah online! atau verifikasi semua kasus uji .

Latar Belakang

Dalam Aritmatika dalam Basa Kompleks , penulis menunjukkan cara menambahkan dan mengalikan bilangan kompleks dalam basis -n + i .

Untuk basis -1 + i , penambahan dilakukan mirip dengan penambahan biner biasa dengan carry, dengan dua perbedaan:

  • Alih-alih membawa 1 ke posisi lebih tinggi berikutnya, kami membawa 110 ke tiga berikutnya.

  • Membawa angka dapat diperbanyak tanpa batas. Namun, tanpa angka nol di depan, jumlah a + b memiliki paling banyak delapan digit lebih dari maksimum a dan b .

Kami melanjutkan sebagai berikut.

  1. Pertama, kita menambahkan a dan b seolah-olah digit mereka adalah angka desimal.

    Untuk a = 10101 dan b = 11011 , ini memberikan 21112 .

  2. Untuk setiap digit yang lebih besar dari 1 , kita harus mengurangi 2 dari angka itu dan membawa 110 ke tiga posisi berikutnya yang lebih tinggi. Kita dapat mencapai ini dengan mengkonversi masing-masing digit desimal ke biner, sehingga array biner dari dasar 1100 ke integer, dan menafsirkan daftar yang dihasilkan dari 0 's, 1 ' s, 1100 's dan 1101 ' s sebagai dasar non-kanonik 10 jumlah. 1

    Untuk jumlah 21112 , ini memberi 21112 + 1098 * 10001 = 21112 + 10981098 = 11002210 .

  3. Kami mengulangi langkah 2 total d + 8 kali, di mana d adalah jumlah digit a + b .

    Untuk jumlah awal 21112 , hasilnya adalah

                          11002210
                          12210010
                        1220010010
                      122000010010
                    12200000010010
                  1220000000010010
                122000000000010010
              12200000000000010010
            1220000000000000010010
          122000000000000000010010
        12200000000000000000010010
      1220000000000000000000010010
    122000000000000000000000010010
    
  4. Kami membuang semua kecuali digit d + 8 terakhir dari hasil akhir. Ini dicapai dengan membuang semuanya setelah 2 terakhir . 2

    Untuk jumlah awal 21112 , hasil akhirnya adalah 10010 .

Bagaimana itu bekerja

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 Perhatikan bahwa angka-angka dari jumlah ini tidak dapat melebihi 3 (nilai awal 1 ditambah dua 1 dari carry).

2 Ini berfungsi karena digit terakhir yang akan dibatalkan tidak boleh 3 .


6

Python 3, 289 byte

Ini melakukan penambahan digit dari paling sedikit ke paling signifikan (dengan kata lain, algoritma yang sama persis dengan yang Anda pelajari di sekolah dasar). Perbedaannya adalah bahwa (a) itu dalam biner, bukan desimal, jadi Anda membawa setiap kali angka 2 atau lebih, dan (b) 1 + 1 = 1100, tidak 10.

Sebenarnya, perlu juga dicatat bahwa 11 + 111 = 0, jika jumlah yang menjadi nol tidak akan pernah berakhir.

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]

Lebih banyak golf tentu saja mungkin.


Seberapa yakin Anda bahwa "detektor nol" Anda sudah cukup?
Yakk

4
@Yakk: Pada skala satu untuk peer-review-journal, mungkin memberikan no-counterexamples-yet?
Tim Pederick

2

Retina, 157 151 134 133 124 123 byte

1 byte off berkat Martin Büttner.

(.+),(.+)
$.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

Cobalah online!

Konversi ke unary, lalu ulangi penggantian berikut (ditampilkan di sini dalam desimal):

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

Pada dasarnya, ketika lebih besar dari dua: ambil dua, tambahkan tidak ada di digit sebelumnya, tambahkan satu ke digit sebelumnya, lalu tambahkan satu ke digit sebelumnya.

Dalam pseudocode:

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

Implementasi unary:

Setiap digit (misalnya 3) ditampilkan sebagai jumlah xs (misalnya xxx) dan kemudian diawali dengan 0.

Sebagai contoh, 1234akan dinyatakan sebagai 0x0xx0xxx0xxxx.

Ini 0tidak berubah, seperti yang 101akan diungkapkan oleh 0x00x.

Sejak awal dan akhirnya, hanya ada 0dan 1, konversi dapat dengan mudah dilakukan oleh 1->0xdan 0x->1.

Klik di sini untuk melihat setiap langkah .


1

JavaScript (ES6), 146 126 byte

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

gmengubah integer Gaussian (bagian nyata dan imajiner) menjadi basis i-1, sementara rdan imengubah i-1integer basis menjadi integer Gaussian (masing-masing bagian nyata dan imajiner). Setelah konversi di tempat, saya hanya perlu melakukan aritmatika.

Sunting: Disimpan 20 byte dengan menghitung bagian nyata dan imajiner secara terpisah.


1

C ++ 416 byte, plus #include <vector>\n#include <algorithm>\n(40 lainnya)

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

atau, dengan lebih banyak ruang putih:

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

Nyaris tidak bermain golf. Dibutuhkan input sebagai vektor int, dan mengembalikan vektor int.

Contoh langsung .

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.