Số nhị phân phức


36

Hãy tạo một đơn giản, surjective ánh xạ từ nguyên dương đến số nguyên Gaussian , đó là số phức nơi các phần thực và phần ảo là các số nguyên.

Ví dụ 4538, đưa ra một số nguyên dương, biểu thị nó dưới dạng nhị phân không có dấu đầu 0:

4538 base 10 = 1000110111010 base 2

Xóa mọi dấu vết 0:

100011011101

Thay thế bất kỳ lần chạy nào của một hoặc nhiều lần 0bằng một +:

1+11+111+1

Thay thế tất cả 1's với i' s:

i+ii+iii+i

Đánh giá biểu thức phức tạp kết quả và xuất ra số nguyên Gaussian đơn giản hóa:

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

Đầu ra có thể được thể hiện theo cách toán học truyền thống, hoặc được đưa ra dưới dạng hai số nguyên riêng biệt cho các phần thực và phần phức tạp. Ví 4538dụ, bất kỳ trong số này sẽ ổn:

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

Đối với nguyên liệu đầu vào như 29, kết quả đầu ra định dạng mathy như 0, 0ihoặc 0+0ilà tất cả tiền phạt.

Sử dụng j(hoặc một cái gì đó khác) thay vì itốt nếu điều đó là tự nhiên hơn cho ngôn ngữ của bạn.

Mã ngắn nhất tính bằng byte thắng.


Từ tiêu đề, tôi nghĩ rằng thách thức sẽ là về các số phức trong nhị phân, ví dụ 4+2j-> 100+10j...
Erik the Outgolfer

Câu trả lời:


22

MATL , 7 byte

BJ*Y'^s

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

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

Xem xét đầu vào 4538chẳng hạn.

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

2
7 byte trong MATL và thứ tốt nhất tôi có thể nhận được là 58 trong MATLAB ... Bạn đã tạo ra một ngôn ngữ nhỏ rất hay đấy! =)
Stewie Griffin

1
@StewieGriffin dễ dàng là người giỏi nhất trong chương trình khi nói đến đồ thị hoặc vẽ đồ thị, có lẽ cũng cho số học ma trận từ những câu trả lời tuyệt vời mà tôi đã thấy anh ấy đăng.
Bạch tuộc ma thuật Urn

13

Thạch , 8 byte

BŒgaıP€S

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

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

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+ı.

10

Python 2, 53 byte

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

Đã cố gắng để chơi golf này và nó có vẻ như có thể chơi được nhưng tôi không biết ...


1
Điều đó (k or 1)có vẻ không tối ưu, nhưng điều khác duy nhất tôi có thể nghĩ đến là (k+0**k)...
Sản phẩm ETH

@ETHproductions Chính xác là suy nghĩ của tôi, nhưng thật không may, 0**knó không hoạt động phức tạp k...
Sp3000

6

Toán học, 44 38 byte

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

Giải trình

#~IntegerDigits~2

Chuyển đổi đầu vào thành cơ sở 2. ( 4538trở thành {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0})

I*

Nhân với I( {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0}trở thành {I, 0, 0, 0, I, I, 0, I, I, I, 0, I, 0})

Split

Phân chia bằng cách chạy ( {I, 0, 0, 0, I, I, 0, I, I, I, 0, I, 0}trở thành {{I}, {0, 0, 0}, {I, I}, {0}, {I, I, I}, {0}, {I}, {0}})

1##&@@@ ...

Tìm sản phẩm ở cấp 2. ( {{I}, {0, 0, 0}, {I, I}, {0}, {I, I, I}, {0}, {I}, {0}}trở thành {I, 0, -1, 0, -I, 0, I, 0})

Tr

Tính tổng kết quả. ( {I, 0, -1, 0, -I, 0, I, 0}trở thành -1 + I)


trừ đi 1 byte:Tr[Times@@@(I*Split@RealDigits[#,2][[1]])]&
martin

1
@martin Chà, tôi đã sử dụng ý tưởng nhân lên Itrước, nhưng IntegerDigitscuối cùng lại ngắn hơn.
JungHwan tối

có - tốt hơn nhiều :)
martin


5

JavaScript (ES6), 67 64 byte

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>

Đầu ra là một mảng 2 phần tử.

Giải trình

Vì JavaScript không có số ảo, chúng tôi phải theo dõi các phần thực và phần ảo trong các biến riêng biệt. Cách dễ nhất để làm điều này là trong một mảng duy nhất, với phần thực trước tiên. i được biểu diễn dưới dạng [0,1] , i 2 (hoặc -1 ) là [-1,0] , i 3 (hoặc -i ) là [0, -1]i 4 (hoặc 1 ) là [1 , 0] .

Đầu tiên, chúng tôi liên tục chia số cho 2, thu thập từng lần chạy trong biểu diễn nhị phân của nó. Mỗi lần chạy của n tương ứng với i n . Điều này tương ứng với việc thêm 1 - (n & 2) vào mục tại chỉ mục n & 1 trong mảng hai mục. Vì vậy, đó là chúng tôi làm.

Tôi có lẽ nên thêm lời giải thích, nhưng tôi không thể nghĩ ra điều gì khác cần giải thích. Hãy bình luận với bất kỳ câu hỏi mà bạn có thể có.


5

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

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

Đầu vào chỉ là số chính nó.
Đầu ra ở định dạng (a+bj), jđơn vị tưởng tượng ở đâu. 0jsẽ là đầu ra thay vì(0+0j)

Đầu tiên chuyển đổi thành nhị phân. Cắt ngắn '0b'tắt. Giết con số không. Tách bằng cách sử dụng một khối 0 (s) làm dấu phân cách. Ánh xạ từng khối tới 1j ** len. Sau đó, lấy tổng của toàn bộ.

-70 byte bằng cách không chuyển đổi thành dấu cộng. Regex
-5 byte ngắn hơn.
-8 byte bằng cách loại bỏ hai biến không cần thiết chỉ được gọi một lần.
-22 byte bằng cách sử dụng số phức thay vì điều kỳ lạ của tôi. Cảm ơn câu trả lời của @Dennis đã thông báo cho tôi về các số phức!
-4 byte bằng cách nhận ra rằng đó mapchỉ là một cách thú vị để thực hiện việc hiểu danh sách, ngoại trừ dài hơn.
-19 byte bằng cách chuyển sang một phương pháp hơi phức tạp để tránh lỗi j ** 0và tránh regex. Lấy cảm hứng từ bình luận của @ Griffin. Cảm ơn! :)
-8 byte bằng cách di chuyển ifphần đến cuối.
-2 byte Cảm ơn @Griffin đã lưu 2 byte bằng cách xóa dấu ngoặc vuông để biến nó thành biểu thức trình tạo thay thế!


Tôi đã nhận được một cái gì đó khá giống nhau vì vậy sẽ không đăng câu trả lời riêng biệt, mặc dù ngắn hơn một chútsum(1j**x.count('1')for x in bin(input()).split('0')if x)
Griffin

@Griffin Đẹp. Tôi nghĩ nó đủ khác để bạn có thể đăng một câu trả lời riêng biệt, vì nó sử dụng một phương pháp khác để đếm các 1khối và nó không sử dụng regex như của tôi. Ngoài ra, tôi không muốn đánh cắp mã từ bạn vì nó tốt hơn phiên bản của tôi rất nhiều. :)
HyperNeutrino

@Griffin Tôi đã tìm thấy một giải pháp khác có cùng độ dài với giải pháp của bạn ngoại trừ thay vì đếm 1s thay vì chiều dài, nó sẽ đưa 0xphần đó ra trước. Cảm ơn ý tưởng di chuyển ifđến cùng; Tôi chưa bao giờ biết rằng nó hoạt động khác!
HyperNeutrino

bạn không cần hiểu danh sách. Xóa dấu ngoặc vuông để biến nó thành biểu thức trình tạo
Griffin

@Griffin ơi. Được rồi, cảm ơn! Tôi sẽ nhớ rằng để chơi gôn trong tương lai
HyperNeutrino 6/12/2016

4

MATLAB, 58 byte

@(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.   

Hãy sử dụng 285để minh họa quá trình:

temp1 = dec2bin(285)
      = 100011101

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

May mắn 1+++1hành xử giống như 1+1trong MATLAB, vì vậy, đánh giá ở trên : 1+111+1.

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

Bây giờ strrep-call này là đá quý thực sự! Bằng cách chèn i*1cho 1chúng tôi nhận được một cái gì đó thực sự tốt đẹp. Nếu chỉ có một 1, chúng ta chỉ đơn giản là có i*1được i. Nếu có nhiều hơn một thì i*1được lặp lại và nối thành một chuỗi : i*1i*1i*1i*1. Vì i==1itrong MATLAB và 1i*1==iđiều này chỉ đơn giản là : i*i*i*i.

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

Việc thêm vào .0có vẻ không cần thiết ở đây, nhưng nó cần thiết nếu ký tự cuối cùng temp3là a +. Chúng tôi không thể chỉ thêm một số không, vì điều đó sẽ đưa ra i*10trong trường hợp trên và do đó kết quả sai.

Và cuối cùng:

eval(temp4)
0.0000 + 1.0000i

Điều này không hoạt động trong Octave vì một số lý do. strrepkhông thể lấy giá trị ASCII làm đầu vào, nó cần các ký tự thực tế ( '0'thay vì 48). Ngoài ra, +++không đánh giá chỉ +trong Octave, vì điều đó sẽ phá vỡ các phím tắt tăng / giảm x++x--.


1
Luôn luôn +1 để sử dụng eval:-P Bạn không thể sử dụng 1ithay vì 1*i?
Luis Mendo

1
Oh bạn đang sử dụng nó khác nhau. Rất thông minh!
Luis Mendo

Cảm ơn :-) Tôi phải thừa nhận, tôi khá hài lòng với i*1phần ...
Stewie Griffin


2

Toán học, 84 byte

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

Chức năng ẩn danh. Lấy một số làm đầu vào và trả về một số phức làm đầu ra.


6
Ồ, tôi ngạc nhiên khi Mathicala không tích hợp sẵn cho việc này!
HyperNeutrino

2

Toán học, 75 byte

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

Độc lập đưa ra gần như cùng một giải pháp mà LegionMammal978 đã đăng 23 phút trước! Việc thay thế 1bằng I (là biểu tượng bên trong của Mathicala cho căn bậc hai của -1) hoạt động vì các khoảng trắng được coi là phép nhân của các biểu thức lân cận. Vị trí tôi đã lưu trên giải pháp khác, cụ thể là bằng cách tránh sự cần thiết StringTrim, là luôn luôn nối thêm -0: nếu số nhị phân kết thúc 1, thì biểu thức này kết thúc trong ...I-0đó không ảnh hưởng đến giá trị của nó; trong khi nếu số nhị phân kết thúc bằng '0', thì biểu thức này kết thúc trong ...+-0đó được phân tích cú pháp là "thêm âm 0" và do đó thoát khỏi dấu cộng.


2

Matlab, 99 byte

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

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

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

2

Haskell, 102 91 89 87 byte

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)

Liên tục chia cho hai và kiểm tra bit. Giữ một bộ tích lũy ở i^(number of odds)nơi a+b*iđược mã hóa theo [a,b]*iđược [a,b]↦[-b,a](xoay 90 độ). Ban đầu (*2)là để tránh tra cứu cho bit đầu tiên.

Cách sử dụng (cảm ơn @OwenMorgan cho các ví dụ):

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

1

Java, 172 byte

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

1

Clojure, 183 byte

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

Tôi có được phép làm điều này không?

Sử dụng chức năng như vậy:

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

1

Trên thực tế , 35 byte

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

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

Giải trình:

├'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

Mã Python 3 tương đương:

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

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


Việc tách trên '0 với '0@svà sử dụng ``░để cắt bất kỳ chuỗi trống nào ở cuối sẽ giúp bạn tiết kiệm bốn byte.
Sherlock9

1

Thạch , 10 byte

Điều này không tốt hơn câu trả lời Jelly của Dennis, nhưng dù sao tôi cũng muốn thử trả lời Jelly. Gợi ý chơi golf chào mừng! Hãy thử trực tuyến!

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.

Trong liên kết ở trên Đầu vào 1 trả về 1j đầu vào 2 trả về 1j .... Có đúng không?
RosLuP

@RosLuP Vâng, đúng không? Vì chúng tôi xóa dấu 0, 1 => 1 => 1jtương đương với 2 => 10 => 1 => 1j.
Sherlock9

1

Trên thực tế , 15 byte

Gợi ý chơi golf chào mừng! Hãy thử trực tuyến!

├'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.

0

Tiên đề, 140, 131, 118 108 byte

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 là chi phí tưởng tượng.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

các kết quả

(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

0

Perl 6 ,  40  46 byte

Tôi nghĩ ra cái này khá nhanh

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

Thật không may, hiện tại nó không chính xác trong triển khai Rakudo trên MoarVM .
say i ** 3; # -1.83697019872103e-16-1i

Vì vậy, tôi đã phải làm điều tốt nhất tiếp theo:

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

Mở rộng:

*\             # 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

Kiểm tra:

.say for (4538, 29).map:

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

# -1+1i
# 0+0i


0

PHP, 87 byte

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

Gần giống như giải pháp ETHproductions. chỉ lặp đi lặp lại thay vì đệ quy.
Lấy đầu vào từ dòng lệnh, đặt biến ${0}${1}.


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

Không có nội dung nào để chuyển đổi thành chuỗi nhị phân, (cũng không có phân tích chuỗi), vì vậy chương trình này chia theo cách thủ công cho 2, tăng N mỗi lần nhìn thấy 1 và thêm i ^ N vào S (N> 0) và đặt lại N nếu nó thấy số không.



0

R , 54 byte

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

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

n%/%2^(0:log2(n))%%2tính một vectơ của các chữ số nhị phân. Sử dụng mã hóa độ dài chạy, chúng tôi sử dụng R'scomplex để tính tổng phù hợp, nhân vớix$values với số 0 để loại bỏ các số không.

Trả về một complexvectơ của một phần tử.

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.