Bilangan Biner Kompleks

36

Mari kita buat pemetaan surjektif yang sederhana dari bilangan bulat positif ke bilangan bulat Gaussian , yang merupakan bilangan kompleks di mana bagian nyata dan imajiner adalah bilangan bulat.

Diberikan bilangan bulat positif, misalnya 4538, ungkapkan dalam biner tanpa pemimpin 0:

4538 base 10 = 1000110111010 base 2

Hapus jejak apa pun 0:

100011011101

Ganti setiap menjalankan satu atau lebih 0dengan satu +:

1+11+111+1

Ganti semua 1dengan i:

i+ii+iii+i

Mengevaluasi ekspresi kompleks yang dihasilkan dan menampilkan bilangan bulat Gaussian yang disederhanakan:

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

Keluaran dapat diekspresikan dalam cara matematika tradisional, atau diberikan sebagai dua bilangan bulat terpisah untuk bagian nyata dan kompleks. Sebagai 4538contoh, semua ini akan baik-baik saja:

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

Untuk input seperti 29, mathy diformat output seperti 0, 0iatau 0+0isemua baik-baik saja.

Menggunakan j(atau sesuatu yang lain) alih-alih ibaik-baik saja jika itu lebih alami untuk bahasa Anda.

Kode terpendek dalam byte menang.

Hobi Calvin
sumber
Dari judulnya saya berpikir bahwa tantangannya adalah tentang bilangan kompleks dalam biner, misalnya 4+2j-> 100+10j...
Erik the Outgolfer

Jawaban:

22

MATL , 7 byte

BJ*Y'^s

Cobalah online!

Bagaimana itu bekerja

Pertimbangkan input 4538misalnya.

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
sumber
2
7 byte di MATL, dan yang terbaik yang bisa saya dapatkan adalah 58 di MATLAB ... Anda telah membuat bahasa kecil yang menyenangkan di sana! =)
Stewie Griffin
1
@StewieGriffin dengan mudah menunjukkan yang terbaik ketika datang ke grafik atau merencanakan, mungkin juga untuk matriks aritmatika juga dari jawaban mengagumkan yang saya lihat dia posting.
Magic Gurita Guci
13

Jelly , 8 byte

BŒgaıP€S

Cobalah online!

Bagaimana itu bekerja

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
sumber
10

Python 2, 53 byte

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

Sudah mencoba bermain golf ini dan sepertinya bisa golf tetapi saya kehabisan ide ...

Sp3000
sumber
1
Itu (k or 1)sepertinya tidak optimal, tetapi satu-satunya hal lain yang dapat saya pikirkan adalah (k+0**k)...
ETHproduksi
@ ETHproductions Pikiranku persis, tapi sayangnya 0**ktidak bekerja untuk kompleks k...
Sp3000
6

Mathematica, 44 38 byte

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

Penjelasan

#~IntegerDigits~2

Ubah input menjadi basis 2. ( 4538menjadi {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0})

I*

Kalikan dengan I( {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0}menjadi {I, 0, 0, 0, I, I, 0, I, I, I, 0, I, 0})

Split

Dibagi dengan berjalan ( {I, 0, 0, 0, I, I, 0, I, I, I, 0, I, 0}menjadi {{I}, {0, 0, 0}, {I, I}, {0}, {I, I, I}, {0}, {I}, {0}})

1##&@@@ ...

Temukan produk di level 2. ( {{I}, {0, 0, 0}, {I, I}, {0}, {I, I, I}, {0}, {I}, {0}}menjadi {I, 0, -1, 0, -I, 0, I, 0})

Tr

Jumlahkan hasilnya. ( {I, 0, -1, 0, -I, 0, I, 0}menjadi -1 + I)

JungHwan Min
sumber
minus 1 byte:Tr[Times@@@(I*Split@RealDigits[#,2][[1]])]&
martin
1
@ Smart Nah, saya menggunakan ide Anda untuk mengalikan Idulu, tetapi IntegerDigitsakhirnya menjadi lebih pendek.
JungHwan Min
ya - jauh lebih baik :)
martin
5

Python 2 , 77 76 71 byte

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

Berkat @ ZacharyT untuk bermain golf 1 byte!

Cobalah online!

Dennis
sumber
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>

Output sebagai array 2-elemen.

Penjelasan

Karena JavaScript tidak memiliki angka imajiner, kami harus melacak bagian nyata dan imajiner dalam variabel terpisah. Cara termudah untuk melakukan ini adalah dalam satu array, dengan bagian yang sebenarnya terlebih dahulu. i direpresentasikan sebagai [0,1] , i 2 (atau -1 ) sebagai [-1,0] , i 3 (atau -i ) sebagai [0, -1] , dan i 4 (atau 1 ) sebagai [1 , 0] .

Pertama, kami berulang kali membagi angka dengan 2, mengumpulkan setiap run yang ada dalam representasi binernya. Setiap run n yang sesuai dengan i n . Ini sesuai dengan menambahkan 1 - (n & 2) ke item di indeks n & 1 di array dua item. Jadi itu yang kita lakukan.

Saya mungkin harus menambahkan lebih banyak penjelasan, tetapi saya tidak bisa memikirkan apa lagi yang perlu dijelaskan. Jangan ragu untuk berkomentar dengan pertanyaan yang mungkin Anda miliki.

Produksi ETH
sumber
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)

Input hanyalah nomor itu sendiri.
Output dalam format (a+bj), di mana junit imajiner. 0jakan menjadi output, bukan(0+0j)

Konversi pertama ke biner. Pangkas '0b'off. Bunuh nol yang tertinggal. Berpisah menggunakan blok nol sebagai pembatas. Petakan setiap blok1j ** len . Lalu, ambil jumlah keseluruhannya.

-70 byte dengan tidak mengonversi ke plus. Regex
-5 byte lebih pendek.
-8 byte dengan menyingkirkan dua variabel yang tidak perlu yang hanya dipanggil sekali.
-22 byte dengan menggunakan bilangan kompleks, bukan hal aneh saya. Terima kasih atas jawaban @Dennis karena memberi tahu saya tentang angka-angka kompleks!
-4 byte dengan menyadari bahwa mapitu hanya cara mewah untuk melakukan pemahaman daftar, kecuali lebih lama.
-19 byte dengan beralih ke metode yang sedikit misterius untuk menghindari kesalahan dengan j ** 0dan menghindari regex. Terinspirasi oleh komentar @ Griffin. Terima kasih! :)
-8 byte dengan memindahkan ifbagian ke ujung.
-2 byte Terima kasih kepada @Griffin karena telah menghemat 2 byte dengan menghapus tanda kurung siku untuk menjadikannya ekspresi generator!

HyperNeutrino
sumber
Saya mendapat sesuatu yang sangat mirip sehingga tidak akan memposting jawaban yang terpisah, meskipun sedikit lebih pendeksum(1j**x.count('1')for x in bin(input()).split('0')if x)
Griffin
@ Griffin Bagus. Saya pikir itu cukup berbeda sehingga Anda dapat memposting jawaban terpisah, karena menggunakan metode penghitungan 1blok yang berbeda dan tidak menggunakan regex seperti yang saya lakukan. Juga, saya tidak ingin mencuri kode dari Anda karena jauh lebih baik daripada versi saya. :)
HyperNeutrino
@ Griffin Saya menemukan solusi lain yang sama panjangnya dengan solusi Anda kecuali alih-alih menghitung 1s alih-alih panjang, ia mengambil 0xbagian dari depan terlebih dahulu. Terima kasih atas gagasan untuk memindahkan ifsampai akhir; Saya tidak akan pernah tahu itu bekerja sebaliknya!
HyperNeutrino
Anda tidak perlu pemahaman daftar. Hapus tanda kurung siku untuk menjadikannya ekspresi generator
Griffin
@ Griffin Oh. Oke terima kasih! Saya akan ingat itu untuk bermain golf di masa depan
HyperNeutrino
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.   

Mari kita gunakan 285untuk menggambarkan proses:

temp1 = dec2bin(285)
      = 100011101

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

Untungnya 1+++1berperilaku seperti 1+1di MATLAB, sehingga mengevaluasi atas untuk: 1+111+1.

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

Sekarang ini strrep-call adalah permata yang sebenarnya! Dengan memasukkan i*1untuk 1kita mendapatkan sesuatu yang sangat bagus. Jika hanya ada satu 1, kami hanya mendapatkan i*1yang i. Jika ada lebih dari satu maka i*1akan diulang dan rubah menjadi berurutan: i*1i*1i*1i*1. Karena i==1idi MATLAB dan 1i*1==iini adalah sederhana: i*i*i*i.

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

Menambahkan .0tampaknya tidak perlu di sini, tetapi diperlukan jika karakter terakhir temp3adalah a +. Kami tidak dapat menambahkan hanya nol, karena itu akan memberii*10 dalam kasus di atas dan karenanya hasil yang salah.

Dan akhirnya:

eval(temp4)
0.0000 + 1.0000i

Ini tidak berfungsi di Octave karena beberapa alasan. strreptidak dapat mengambil nilai ASCII sebagai input, ini membutuhkan karakter yang sebenarnya ( '0'bukan 48). Juga, +++tidak mengevaluasi hanya +dalam Oktaf, karena itu akan merusak pintasan kenaikan / pengurangan x++dan x--.

Stewie Griffin
sumber
1
Selalu memberi +1 untuk menggunakan eval:-P Tidak bisakah Anda menggunakan 1ibukan 1*i?
Luis Mendo
1
Oh Anda menggunakannya secara berbeda. Sangat pintar!
Luis Mendo
Terima kasih :-) Harus saya akui, saya cukup puas dengan i*1perannya ...
Stewie Griffin
2

Mathematica, 84 byte

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

Fungsi anonim. Mengambil nomor sebagai input dan mengembalikan nomor kompleks sebagai output.

LegionMammal978
sumber
6
Wow, saya terkejut bahwa Mathematica tidak memiliki bawaan untuk ini!
HyperNeutrino
2

Mathematica, 75 byte

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

Independen datang dengan solusi yang hampir sama yang diposting LegionMammal978 23 menit yang lalu! Mengganti 1dengan I (yang merupakan simbol internal Mathematica untuk akar kuadrat dari -1) berfungsi karena spasi diperlakukan sebagai perkalian dari ekspresi tetangga. Tempat saya menghemat solusi lain, yaitu dengan menghindari kebutuhan StringTrim, adalah dengan selalu menambahkan -0: jika angka biner berakhir 1, maka ungkapan ini berakhir ...I-0yang tidak mempengaruhi nilainya; sementara jika angka biner berakhir dengan '0', maka ekspresi ini berakhir dengan ...+-0yang diuraikan sebagai "tambahkan negatif 0" dan dengan demikian menghilangkan tanda tambah yang mengekor.

Greg Martin
sumber
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

Kasus uji:

z(656) = 3i
z(172) = -1 + 2i
z(707) = -2 + i
z(32)  = i
z(277) = 4i
Owen Morgan
sumber
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)

Membagi dua kali dan memeriksa bit. Terus akumulator dari i^(number of odds)mana a+b*idikodekan sebagai [a,b]dan *imerupakan [a,b]↦[-b,a](rotasi 90 derajat). Inisial(*2) adalah untuk menghindari pencarian untuk bit pertama.

Penggunaan (terima kasih kepada @OwenMorgan untuk contohnya):

(%[0,0]).(*2)<$>[656,172,707,32,277]
[[0,3],[-1,2],[-2,1],[0,1],[0,4]]
Angs
sumber
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";}
Roman Gräf
sumber
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))))

Apakah saya diizinkan melakukan ini?

Gunakan fungsi seperti ini:

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

Sebenarnya , 35 byte

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

Cobalah online!

Penjelasan:

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

Kode Python 3 yang hampir sama:

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

Cobalah online!

Mego
sumber
Memisahkan pada '0's dengan '0@sdan menggunakan ``░untuk memangkas setiap string kosong trailing akan menghemat empat byte.
Sherlock9
1

Jeli , 10 byte

Ini tidak lebih baik daripada jawaban Jelly Dennis, tetapi saya ingin tetap mencoba jawaban Jelly. Selamat datang saran bermain golf! Cobalah online!

BŒrm2Ṫ€ı*S

Tidak melakukanolf

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
sumber
Pada tautan di atas Input 1 mengembalikan 1j input 2 mengembalikan 1j .... Apakah itu benar?
RosLuP
@ RosLuP Ya, benar? Karena kami menghapus trailing 0's, 1 => 1 => 1jsama dengan 2 => 10 => 1 => 1j.
Sherlock9
1

Sebenarnya , 15 byte

Selamat datang saran bermain golf! Cobalah online!

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

Tidak melakukan pelanggaran:

         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
sumber
0

Aksioma, 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 adalah costant imajiner. Tidak tahu

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

hasil

(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
sumber
0

Perl 6 ,  40  46 byte

Saya datang dengan ini cukup cepat

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

Sayangnya saat ini tidak akurat dalam implementasi Rakudo di MoarVM .
say i ** 3; # -1.83697019872103e-16-1i

Jadi saya harus melakukan hal terbaik berikutnya:

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

Diperluas:

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

Uji:

.say for (4538, 29).map:

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

# -1+1i
# 0+0i
Brad Gilbert b2gills
sumber
Laporan bug diajukan
Brad Gilbert b2gills
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})";

Hampir sama dengan solusi ETHproductions; hanya iteratif dan bukan rekursif.
Mengambil input dari baris perintah, menetapkan variabel ${0}dan ${1}.

Titus
sumber
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

Tidak ada builtin untuk mengkonversi ke string biner, (juga tidak ada untuk mengurai string), jadi program ini secara manual membaginya dengan 2, menambah N setiap kali melihat 1 dan menambahkan i ^ N ke S (N> 0) dan mengatur ulang N jika melihat nol.

pizzapants184
sumber
0

Java , 100 byte

int[]f(int n){int c=2,r[]=new int[2];for(;n>0;r[c&1]+=n%4==1?(c&2)-1:0,n/=2)c=n%2<1?2:c+1;return r;}

Cobalah online!

Biarawati Bocor
sumber
0

R , 54 byte

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

Cobalah online!

n%/%2^(0:log2(n))%%2menghitung vektor dari angka biner. Menggunakan pengkodean run-length, kami menggunakan complextipe R untuk menghitung jumlah yang sesuai, dikalikan denganx$values untuk menghapus nol.

Mengembalikan complexvektor satu elemen.

Giuseppe
sumber