Bổ sung trong cơ sở -1 + i


64

Số nguyên Gaussian là số phức có dạng a+binơi abđều là số nguyên. Trong cơ sở -1 + i, tất cả các số nguyên Gaussian có thể được biểu diễn duy nhất bằng cách sử dụng các chữ số 01, không cần biểu tượng để biểu thị dấu hiệu.

Chẳng hạn, 1100trong cơ sở -1 + i đại diện cho số thập phân 2, vì

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

Đầu vào sẽ là hai số nguyên Gaussian trong cơ sở -1 + i được biểu diễn bằng các chữ số 01. Điều này có thể có một trong các hình thức sau:

  • Hai chuỗi chữ số riêng biệt,
  • Hai số nguyên thập phân bao gồm 01đại diện cho các số -1 + i cơ sở (ví dụ: 11002 cho cơ sở -1 + i),
  • Hai số nguyên nhị phân đại diện cho các số cơ sở -1 + i (ví dụ: số thập phân 12hoặc 0b1100cho 2 trong cơ sở -1 + i)
  • Một chuỗi đơn tách hai chuỗi số / số nguyên nhị phân bằng một dấu tách không chữ và số (ví dụ 1100 1100hoặc 12,12cho 2 + 2)

Xuất tổng của hai số nguyên Gaussian, cũng trong cơ sở -1 + i và được biểu diễn bằng các chữ số 01(theo một trong các định dạng được phép làm đầu vào, không nhất thiết phải là cùng một lựa chọn). Đầu ra được phép chứa một số hữu hạn các số 0 đứng đầu.

Chức năng hoặc chương trình của bạn phải chấm dứt trong vòng 2 giây đối với các đầu vào có tối đa 30 chữ số mỗi chữ số.

Làm rõ thêm

  • Bạn có thể giả định rằng đầu vào không chứa các số 0 đứng đầu bên ngoài. Đối với trường hợp đặc biệt là 0, bạn có thể chọn 0hoặc chuỗi trống làm đại diện.

Các trường hợp thử nghiệm

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)

Các trường hợp thử nghiệm dài hơn:

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

Không có danh sách chữ số?
Máy

@CatsAreFluffy Không có danh sách chữ số, xin lỗi.
Sp3000

96
Bạn có thể tiết kiệm một byte bằng cách thay đổi -1+iđể i-1trong tiêu đề.
mbomb007

1
Bây giờ chúng ta cần một chuyển đổi theo cách khác. : P
Rɪᴋᴇʀ

3
Có 1100 loại người trên thế giới. Những người hiểu nhị phân, những người không, những người nhầm lẫn nó với ternary, những người nhầm lẫn nó với cơ sở 4, những người nhầm lẫn nó với cơ sở 5, những người nhầm lẫn nó với cơ sở -1 + i, những người nhầm lẫn với nó cơ sở 6, những người nhầm lẫn nó với cơ sở 7, những người nhầm lẫn nó với cơ sở 8, những người nhầm lẫn nó với cơ sở 9 ...
wizzwizz4

Câu trả lời:


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

Điều này không I / O trong thập phân. Các số nguyên phải được phân tách bằng ký tự không chữ và số +.

Cảm ơn @xnor vì đã chơi golf 2 byte!

Hãy thử nó trên Ideone .

Làm thế nào nó hoạt động

Trong Số học trong các cơ sở phức tạp , tác giả chỉ ra cách thêm và nhân các số phức trong các cơ sở có dạng -n + i .

Đối với cơ sở -1 + i , phép cộng được thực hiện tương tự như phép cộng nhị phân thông thường với phép mang, với hai điểm khác biệt:

  • Thay vì mang 1 đến vị trí cao hơn tiếp theo, chúng tôi mang 110 đến ba vị trí tiếp theo.

  • Chữ số mang có thể truyền vô thời hạn. Tuy nhiên, không có các số 0 đứng đầu, tổng a + b có nhiều nhất là tám chữ số nhiều hơn tối đa của ab .

Chúng tôi tiến hành như sau.

  1. Đầu tiên, chúng ta thêm ab như thể các chữ số của chúng là các chữ số thập phân.

    Với a = 10101b = 11011 , điều này mang lại 21112 .

  2. Tiếp theo, chúng tôi tạo thành một số mới bằng cách thay thế các chữ số lớn hơn 1 bằng 1 , các số khác bằng 0 . 1

    Đối với số tiền 21112 , số tiền này mang lại 10001 .

  3. Đối với mỗi chữ số lớn hơn 1 , chúng ta phải trừ 2 từ chữ số đó và mang 110 đến ba vị trí cao hơn tiếp theo. Vì 1098 = 10 * 110 - 2 , chúng ta có thể đạt được điều này bằng cách nhân kết quả từ bước 2 với 1098 , sau đó thêm sản phẩm đó vào tổng. 2

    Đối với tổng 21112 , số này mang lại 21112 + 1098 * 10001 = 21112 + 10981098 = 11002210 .

  4. Chúng tôi lặp lại bước 23 tổng cộng d * 8 lần, trong đó d là số chữ số của a + b . 3

    Đối với số tiền ban đầu 21112 , kết quả là

                          11002210
                          12210010
                        1220010010
                      122000010010
                    12200000010010
                  1220000000010010
                122000000000010010
              12200000000000010010
            1220000000000000010010
          122000000000000000010010
        12200000000000000000010010
      1220000000000000000000010010
    122000000000000000000000010010
                                 .
                                 .
                                 .
    
  5. Chúng tôi lấy tổng modulo cuối cùng 10 d + 8 , loại bỏ tất cả trừ các chữ số d + 8 cuối cùng .

    Đối với số tiền ban đầu 21112 , kết quả cuối cùng là 10010 .


1 Điều này đạt được với dịch . Lặp lại chuỗi 0011 64 lần làm cho một lần lặp lại nối tiếp với chuỗi các ký tự ASCII 0123 , đạt được sự thay thế mong muốn.

2 Lưu ý rằng các chữ số của tổng này không thể vượt quá 3 (giá trị ban đầu 1 cộng với hai 1 'từ số mang).

3 Điều này xảy ra để làm việc cho d = 1d * 8> d + 8 nếu không. Mã có thể lặp lại các bước (d + 1) * 8 lần, vì s có dấu L nếu s là số nguyên dài .


7
Đây là ma thuật sâu sắc . Định dạng nào đang input()mong đợi? (Tôi nhận được 21112khi tôi nhập 10101, 11011.)
Tim Pederick

1
Đừng bận tâm; đã chạy một phiên bản được dịch (dường như không thành công) sang Python 3. Nó hoạt động tốt trong Python 2 .
Tim Pederick

9
...Làm sao. Xin vui lòng. Giải thích.
Nic Hartley

@QPaysTaxes Tôi đã chỉnh sửa câu trả lời của mình.
Dennis

@Dennis Bây giờ bạn có thể giải thích tại sao điều đó làm việc? Ví dụ, tại sao d+8và không, nói , d+9? Làm sao????
Nic Hartley

16

Bình thường, 34 byte

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

Dùng thử trực tuyến: Trình diễn hoặc Test Suite (mất khá nhiều thời gian). Nó sẽ đáp ứng hạn chế thời gian mặc dù dễ dàng, vì trình biên dịch trực tuyến khá chậm so với trình biên dịch (ngoại tuyến) thông thường.

Giải trình:

Thuật toán của tôi về cơ bản là một thực hiện bổ sung với mang. Nhưng thay vì mang theo 1, tôi phải mang theo 110( 1100trong căn cứ -1+icũng giống như 2trong căn cứ -1+i). Điều này hoạt động chủ yếu là tốt, nhưng bạn có thể bị mắc kẹt trong một số không in vòng lặp vô hạn. Ví dụ nếu bạn đang thêm 1với 11và hiện đang có mang 110. Vì vậy, về cơ bản tôi thêm cho đến khi tôi bị mắc kẹt trong một vòng lặp và sau đó dừng lại. Tôi nghĩ rằng một vòng lặp mà một vòng lặp sẽ luôn in các số không và do đó điều này sẽ ổn.

_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 được thực hiện với số nguyên cơ sở 2.

-2 cảm ơn @Dennis.


Tôi lấy nó a*a+b*b^58==0khi abđang đảo? Làm thế nào mà làm việc?
xnor

@xnor Không, a*a+b*b==58khi một trong số họ là 3 và người kia là 7.
frageum

1
Tôi không rõ ràng rằng đó (3,7)là cặp duy nhất cho một chu kỳ và cần vỏ đặc biệt. Nếu đó là sự thật, thì bạn thực sự chỉ cần kiểm tra (a,b)==(3,7)theo thứ tự đó, kể từ khi (7,3)đệ quy (3,7)và có thể có một biểu thức ngắn hơn cho điều đó.
xnor

1
Bây giờ điều này được đảm bảo để gây nhầm lẫn cho bất kỳ ai không biết (hoặc quên) rằng (a) ^là XOR, không phải là lũy thừa hoặc (b) XOR có mức độ ưu tiên thấp hơn +.
Tim Pederick

12

Võng mạc , 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

Điều này có đầu vào được phân tách bằng dấu phẩy. Đầu ra luôn bắt đầu với ba số 0 đứng đầu.

Hãy thử trực tuyến!

Tôi thực sự tự hỏi nếu có một giải pháp ngắn hơn cho giai đoạn đầu tiên ...


2
Không, không, điểm số là hoàn hảo như vậy;)
Conor O'Brien

2
Điểm số đẹp của -2i!
Nic Hartley

Ồ Tôi đã không thấy giải pháp này khi tôi đăng bài của tôi ... Cao hơn nhiều so với giải pháp của tôi.
Leaky Nun

@KennyLau Tôi chỉ nhìn vào nó và nghĩ "hm, tôi đoán tôi nên thêm một lời giải thích vào một lúc nào đó ..."
Martin Ender

...- 2i? Đây là số thập phân nhưng chương trình sử dụng một cơ sở mà không.
dùng75200

12

Thạch, 29 28 26 24 21 20 byte

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

Điều này không I / O trong thập phân. Các số nguyên phải được phân tách bằng ký tự không chữ và số +.

Hãy thử trực tuyến! hoặc xác minh tất cả các trường hợp thử nghiệm .

Lý lịch

Trong Số học trong các cơ sở phức tạp , tác giả chỉ ra cách thêm và nhân các số phức trong các cơ sở có dạng -n + i .

Đối với cơ sở -1 + i , phép cộng được thực hiện tương tự như phép cộng nhị phân thông thường với phép mang, với hai điểm khác biệt:

  • Thay vì mang 1 đến vị trí cao hơn tiếp theo, chúng tôi mang 110 đến ba vị trí tiếp theo.

  • Chữ số mang có thể truyền vô thời hạn. Tuy nhiên, không có các số 0 đứng đầu, tổng a + b có nhiều nhất là tám chữ số nhiều hơn tối đa của ab .

Chúng tôi tiến hành như sau.

  1. Đầu tiên, chúng ta thêm ab như thể các chữ số của chúng là các chữ số thập phân.

    Với a = 10101b = 11011 , điều này mang lại 21112 .

  2. Đối với mỗi chữ số lớn hơn 1 , chúng ta phải trừ 2 từ chữ số đó và mang 110 đến ba vị trí cao hơn tiếp theo. Chúng ta có thể đạt được điều này bằng cách chuyển đổi từng chữ số thập phân thành nhị phân, các mảng nhị phân kết quả từ cơ sở 1100 thành số nguyên và giải thích danh sách kết quả của 0 , s, 1 , 11001101 như là một cơ sở không chính tắc 10 con số. 1

    Đối với tổng 21112 , số này mang lại 21112 + 1098 * 10001 = 21112 + 10981098 = 11002210 .

  3. Chúng tôi lặp lại các bước 2 tổng cộng d + 8 lần, trong đó d là số chữ số của a + b .

    Đối với số tiền ban đầu 21112 , kết quả là

                          11002210
                          12210010
                        1220010010
                      122000010010
                    12200000010010
                  1220000000010010
                122000000000010010
              12200000000000010010
            1220000000000000010010
          122000000000000000010010
        12200000000000000000010010
      1220000000000000000000010010
    122000000000000000000000010010
    
  4. Chúng tôi loại bỏ tất cả trừ 8 chữ số cuối cùng từ kết quả cuối cùng. Điều này đạt được bằng cách loại bỏ mọi thứ sau 2 lần cuối . 2

    Đối với số tiền ban đầu 21112 , kết quả cuối cùng là 10010 .

Làm thế nào nó hoạt động

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 Lưu ý rằng các chữ số của tổng này không thể vượt quá 3 (giá trị ban đầu 1 cộng với hai 1 'từ số mang).

2 Điều này hoạt động vì chữ số cuối cùng sẽ hủy không thể là 3 .


6

Python 3, 289 byte

Điều này thực hiện bổ sung kỹ thuật số từ ít nhất đến chữ số có nghĩa nhất (nói cách khác, chính xác thuật toán bạn đã được dạy ở trường tiểu học). Sự khác biệt là (a) nó ở dạng nhị phân, không phải là số thập phân, do đó bạn mang theo bất cứ khi nào một chữ số là 2 hoặc nhiều hơn và (b) 1 + 1 = 1100, không phải 10.

Trên thực tế, cũng cần lưu ý rằng 11 + 111 = 0, nếu không, số tiền sẽ trở thành số 0 sẽ không bao giờ chấm dứt.

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]

Chơi golf nhiều hơn là chắc chắn có thể.


Làm thế nào chắc chắn là bạn rằng "máy dò không" của bạn là đủ?
Yakk

4
@Yakk: Trên thang điểm từ một đến tạp chí được đánh giá ngang hàng, có thể cung cấp cho nó một mẫu không có phản hồi-chưa?
Tim Pederick

2

Võng mạc, 157 151 134 133 124 123 byte

Giảm 1 byte nhờ 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

Hãy thử trực tuyến!

Chuyển đổi thành unary, và sau đó lặp lại các thay thế sau (hiển thị ở đây dưới dạng thập phân):

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

Về cơ bản, khi lớn hơn hai: lấy đi hai, không thêm gì vào chữ số trước, thêm một vào chữ số trước, sau đó thêm một vào chữ số trước.

Trong mã giả:

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

Thực hiện đơn phương:

Mỗi chữ số (ví dụ 3) được hiển thị dưới dạng số xs (ví dụ xxx) và sau đó được thêm tiền tố 0.

Ví dụ, 1234sẽ được thể hiện như 0x0xx0xxx0xxxx.

Điều này 0không thay đổi, như 101sẽ được thể hiện bởi 0x00x.

Vì ban đầu và cuối cùng, chỉ có 01, việc chuyển đổi có thể được thực hiện dễ dàng bởi 1->0x0x->1.

Nhấn vào đây để xem từng bước .


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

gchuyển đổi một số nguyên Gaussian (phần thực và phần ảo) thành cơ sở i-1, trong khi richuyển đổi một i-1số nguyên cơ bản thành số nguyên Gaussian (phần thực và phần ảo tương ứng). Khi các chuyển đổi được thực hiện, tôi chỉ phải thực hiện số học.

Chỉnh sửa: Đã lưu 20 byte bằng cách tính riêng phần thực và phần ảo.


1

C ++ 416 byte, cộng #include <vector>\n#include <algorithm>\n (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;}

hoặc, với nhiều khoảng trắng hơn:

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

Chơi golf đơn giản. Nó nhận đầu vào là một vectơ của int và trả về một vectơ int.

Ví dụ sống .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.