Złożone liczby binarne

36

Stwórzmy proste, przejmujące odwzorowanie od liczb całkowitych dodatnich do liczb całkowitych Gaussa , które są liczbami zespolonymi, w których rzeczywistymi i urojonymi częściami są liczby całkowite.

Na przykład 4538, biorąc pod uwagę dodatnią liczbę całkowitą, wyraż ją binarnie, bez wiodących 0:

4538 base 10 = 1000110111010 base 2

Usuń wszystkie końcowe 0:

100011011101

Zamień dowolne przebiegi jednego lub więcej 0na jedno +:

1+11+111+1

Wymień wszystkie 1„sz i” s:

i+ii+iii+i

Oceń wynikowe złożone wyrażenie i wyprowadź uproszczoną liczbę całkowitą Gaussa:

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

Dane wyjściowe można wyrazić w tradycyjny sposób matematyczny lub podać jako dwie oddzielne liczby całkowite dla części rzeczywistej i złożonej. Na 4538przykład dowolne z nich byłoby w porządku:

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

Do surowców jak 29, MATHY sformatowane wyjść, na przykład 0, 0iczy 0+0ito wszystko jest w porządku.

Używanie j(lub czegoś innego) zamiast ijest w porządku, jeśli jest to bardziej naturalne dla twojego języka.

Najkrótszy kod w bajtach wygrywa.

Hobby Calvina
źródło
Z tytułu myślałem, że wyzwanie dotyczy liczb zespolonych w postaci binarnej, np. 4+2j-> 100+10j...
Erik Outgolfer

Odpowiedzi:

22

MATL , 7 bajtów

BJ*Y'^s

Wypróbuj online!

Jak to działa

Rozważmy 4538na przykład dane wejściowe .

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
źródło
2
7 bajtów w MATL, a najlepsze, co mogę dostać, to 58 w MATLAB ... Stworzyłeś tam ładny, mały język! =)
Stewie Griffin
1
@StewieGriffin z łatwością najlepiej pokazuje, jeśli chodzi o grafowanie lub kreślenie, być może także w przypadku arytmetyki macierzowej z niesamowitych odpowiedzi, które widziałem.
Magic Octopus Urn
13

Galareta , 8 bajtów

BŒgaıP€S

Wypróbuj online!

Jak to działa

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
źródło
10

Python 2, 53 bajty

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

Próbowałem grać w golfa i wydaje się, że można grać w golfa, ale nie mam pomysłów ...

Sp3000
źródło
1
Że (k or 1)nie wydaje się optymalna, ale tylko inne rzeczy mogę myśleć to (k+0**k)...
ETHproductions
@ETHproductions Moje myśli dokładnie, ale niestety 0**knie działają na skomplikowane k...
Sp3000
6

Mathematica, 44 38 bajtów

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

Wyjaśnienie

#~IntegerDigits~2

Konwertuj dane wejściowe na bazę 2. ( 4538staje się {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0})

I*

Pomnóż przez I( {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0}staje się {I, 0, 0, 0, I, I, 0, I, I, I, 0, I, 0})

Split

Podziel według przebiegów ( {I, 0, 0, 0, I, I, 0, I, I, I, 0, I, 0}staje się {{I}, {0, 0, 0}, {I, I}, {0}, {I, I, I}, {0}, {I}, {0}})

1##&@@@ ...

Znajdź produkt na poziomie 2. ( {{I}, {0, 0, 0}, {I, I}, {0}, {I, I, I}, {0}, {I}, {0}}staje się {I, 0, -1, 0, -I, 0, I, 0})

Tr

Zsumuj wynik. ( {I, 0, -1, 0, -I, 0, I, 0}staje się -1 + I)

JungHwan Min
źródło
minus 1 bajt:Tr[Times@@@(I*Split@RealDigits[#,2][[1]])]&
martin
1
@martin Cóż, Inajpierw wykorzystałem twój pomysł na pomnożenie , ale IntegerDigitsostatecznie byłem krótszy.
JungHwan Min
tak - o wiele lepiej :)
martin
5

Python 2 , 77 76 71 bajtów

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

Dzięki @ZacharyT za grę w golfa na 1 bajcie!

Wypróbuj online!

Dennis
źródło
5

JavaScript (ES6), 67 64 bajtów

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>

Dane wyjściowe jako tablica 2-elementowa.

Wyjaśnienie

Ponieważ JavaScript nie ma liczb urojonych, musimy śledzić rzeczywiste i urojone części w osobnych zmiennych. Najłatwiej to zrobić w jednej tablicy, z prawdziwą częścią na początku. i jest reprezentowane jako [0,1] , i 2 (lub -1 ) jako [-1,0] , i 3 (lub -i ) jako [0, -1] oraz i 4 (lub 1 ) jako [1 , 0] .

Po pierwsze, wielokrotnie dzielimy liczbę przez 2, zbierając każdy z nich w ich reprezentacji binarnej. Każde uruchomienie n tych odpowiada i n . Odpowiada to dodaniu 1 - (n i 2) do pozycji o indeksie n i 1 w tablicy dwóch elementów. Więc to robimy.

Powinienem chyba dodać więcej wyjaśnień, ale nie mogę wymyślić, co jeszcze trzeba wyjaśnić. Skomentuj dowolne pytania.

ETHprodukcje
źródło
5

Python, 199 129 124 116 94 90 71 63 61 bajtów

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

Dane wejściowe to sama liczba.
Dane wyjściowe mają format (a+bj), w którym jjest jednostką urojoną. 0jzostanie wypisany zamiast(0+0j)

Najpierw przekonwertuj na binarny. Obetnij '0b'off. Zabij końcowe zera. Podziel za pomocą bloku zer (s) jako ogranicznika. Odwzoruj każdy blok na1j ** len . Następnie weź sumę całej rzeczy.

-70 bajtów , nie zamieniając na plusy. Regex
-5 bajtów jest krótszy.
-8 bajtów poprzez pozbycie się dwóch niepotrzebnych zmiennych, które były wywoływane tylko raz.
-22 bajtów przy użyciu liczb zespolonych zamiast mojej dziwnej rzeczy. Dzięki odpowiedzi @Dennis za poinformowanie mnie o liczbach zespolonych!
-4 bajty , uświadamiając sobie, że mapjest to tylko fantazyjny sposób robienia list, z wyjątkiem dłuższych.
-19 bajtów , przechodząc na nieco tajemniczą metodę unikania błędów j ** 0i unikania wyrażenia regularnego. Zainspirowany komentarzem @ Griffin. Dzięki! :)
-8 bajtów , przesuwając ifczęść do końca.
-2 bajty Dzięki @Griffin za zaoszczędzenie 2 bajtów poprzez usunięcie nawiasów kwadratowych, aby zamiast tego było wyrażeniem generatora!

HyperNeutrino
źródło
Mam coś podobnego, więc nie opublikuję osobnej odpowiedzi, choć nieco krótszejsum(1j**x.count('1')for x in bin(input()).split('0')if x)
Griffin
@Griffin Nice. Myślę, że jest na tyle inny, że możesz napisać osobną odpowiedź, ponieważ używa innej metody liczenia 1bloków i nie używa wyrażenia regularnego, jak moje. Nie chcę też kraść ci kodu, ponieważ jest o wiele lepszy niż moja wersja. :)
HyperNeutrino,
@Griffin Znalazłem inne rozwiązanie, które ma taką samą długość jak twoje rozwiązanie, z tym wyjątkiem, że zamiast liczyć 1s zamiast długości, 0xnajpierw bierze część z przodu. Dzięki za pomysł przeniesienia ifdo końca; Nigdy bym nie wiedział, że to działa inaczej!
HyperNeutrino,
nie potrzebujesz zrozumienia listy. Usuń nawiasy kwadratowe, aby stało się wyrażeniem generatora
Griffin
@Griffin Oh. Ok, dzięki! Zapamiętam to dla przyszłych golfistów
HyperNeutrino,
4

MATLAB, 58 bajtów

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

Użyjmy 285 do zilustrowania procesu:

temp1 = dec2bin(285)
      = 100011101

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

Na szczęście 1+++1zachowuje się tak jak 1+1w MATLAB, więc powyższe ocenia:1+111+1 .

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

Teraz to połączenie strrepjest prawdziwym klejnotem! Wstawiając i*1do 1mamy coś naprawdę miłego. Jeśli jest tylko jeden 1, po prostu rozumiemy, i*1co jest i. Jeśli istnieje więcej niż jeden, a następnie i*1zostanie powtórzony i łączone w kolejności: i*1i*1i*1i*1. Ponieważ i==1iw MATLAB i 1i*1==ijest to po prostu:i*i*i*i .

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

Dołączanie .0wydaje się tutaj niepotrzebne, ale jest potrzebne, jeśli ostatnim znakiem temp3jest +. Nie możemy dodać tylko zera, ponieważ dałoby to i*10w powyższym przypadku, a zatem zły wynik.

I w końcu:

eval(temp4)
0.0000 + 1.0000i

To nie działa w Octave z kilku powodów. strrepnie może przyjmować wartości ASCII jako danych wejściowych, potrzebuje rzeczywistych znaków ( '0'zamiast 48). Również +++nie ocenia się tylko +w Octave, ponieważ spowodowałoby to złamanie skrótów zwiększania / zmniejszania x++i x--.

Stewie Griffin
źródło
1
Zawsze +1 za użycie eval:-P Nie możesz użyć 1izamiast 1*i?
Luis Mendo
1
Och, używasz go inaczej. Bardzo mądry!
Luis Mendo,
Dzięki :-) Muszę przyznać, że byłem całkiem zadowolony z tej i*1części ...
Stewie Griffin
2

Mathematica, 84 bajty

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

Funkcja anonimowa. Pobiera liczbę jako dane wejściowe i zwraca liczbę zespoloną jako dane wyjściowe.

LegionMammal978
źródło
6
Wow, jestem zaskoczony, że Mathematica nie ma do tego wbudowanego!
HyperNeutrino,
2

Mathematica, 75 bajtów

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

Niezależnie wymyślił prawie to samo rozwiązanie, które LegionMammal978 opublikował 23 minuty temu! Zastąpienie 1przez I (który jest wewnętrznym symbolem Mathematica pierwiastka kwadratowego z -1) działa, ponieważ spacje są traktowane jako zwielokrotnienie sąsiednich wyrażeń. Miejsce, które zapisałem na innym rozwiązaniu, a mianowicie przez unikanie potrzeby StringTrim, polega zawsze na dołączaniu -0: jeśli liczba binarna kończy się 1, to to wyrażenie kończy się, ...I-0co nie wpływa na jego wartość; podczas gdy jeśli liczba binarna kończy się na „0”, to to wyrażenie kończy ...+-0się parsowaniem jako „dodaj ujemne 0” i w ten sposób pozbywa się końcowego znaku plus.

Greg Martin
źródło
2

Matlab, 99 bajtów

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

Przypadki testowe:

z(656) = 3i
z(172) = -1 + 2i
z(707) = -2 + i
z(32)  = i
z(277) = 4i
Owen Morgan
źródło
2

Haskell, 102 91 89 87 bajtów

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)

Wielokrotnie dzieli przez dwa i sprawdza bit. Utrzymuje akumulator, i^(number of odds)gdzie a+b*ijest zakodowany jako [a,b]i *ijest [a,b]↦[-b,a](obrót o 90 stopni). Inicjał(*2) jest uniknięcie wyszukiwania pierwszego bitu.

Zastosowanie (podziękowania dla przykładów @OwenMorgan):

(%[0,0]).(*2)<$>[656,172,707,32,277]
[[0,3],[-1,2],[-2,1],[0,1],[0,4]]
Angs
źródło
1

Java, 172 bajty

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
źródło
1

Clojure, 183 bajtów

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

Czy mogę to zrobić?

Użyj funkcji w następujący sposób:

(#(...) {num}) -> (Wrap the # function in brackets first!)
clismique
źródło
1

Właściwie 35 bajtów

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

Wypróbuj online!

Wyjaśnienie:

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

Z grubsza równoważny kod Python 3:

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

Wypróbuj online!

Mego
źródło
Dzielenie „0” za pomocą '0@si ``░przycinanie dowolnych ciągów pustych ciągów powinno zaoszczędzić cztery bajty.
Sherlock9,
1

Galaretka , 10 bajtów

To nie jest lepsze niż odpowiedź Jelnisa ​​na Dennisa, ale i tak chciałem spróbować swoich sił w odpowiedzi na Jelly. Zapraszamy do gry w golfa! Wypróbuj online!

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.
Sherlock9
źródło
W powyższym linku Wejście 1 zwraca 1j Wejście 2 zwraca 1j .... Czy to prawda?
RosLuP,
@RosLuP Tak, zgadza się? Ponieważ usuwamy końcowe zera, 1 => 1 => 1jjest to równoważne z 2 => 10 => 1 => 1j.
Sherlock9,
1

Tak właściwie 15 bajtów

Zapraszamy do gry w golfa! Wypróbuj online!

├'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.
Sherlock9
źródło
0

Axiom, 140, 131, 118 108 bajtów

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 jest wyimaginowanym kosztownym

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

wyniki

(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
źródło
0

Perl 6 ,  40  46 bajtów

Dość szybko to wymyśliłem

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

Niestety jest to obecnie niedokładne w implementacji Rakudo na MoarVM .
say i ** 3; # -1.83697019872103e-16-1i

Musiałem więc zrobić następną najlepszą rzecz:

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

Rozszerzony:

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

Test:

.say for (4538, 29).map:

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

# -1+1i
# 0+0i
Brad Gilbert b2gills
źródło
Zgłoszony
0

PHP, 87 bajtów

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

Prawie to samo co rozwiązanie ETHproductions; tylko iteracyjne zamiast rekurencyjne.
Pobiera dane z wiersza poleceń, ustawia zmienne ${0}i ${1}.

Tytus
źródło
0

TI-Basic (TI-84 Plus CE), 70 bajtów

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

Nie ma wbudowanego programu do konwersji na ciąg binarny (ani też nie ma go na parsowanie), więc ten program ręcznie dzieli przez 2, zwiększając N za każdym razem, gdy zobaczy 1 i dodając i ^ N do S (N> 0) i resetując N, jeśli widzi zero.

pizzapanty184
źródło
0

Java , 100 bajtów

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

Wypróbuj online!

Leaky Nun
źródło
0

R , 54 bajty

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

Wypróbuj online!

n%/%2^(0:log2(n))%%2oblicza wektor cyfr binarnych. Używając kodowania długości przebiegu, używamy typu R, complexaby obliczyć odpowiednią sumę, mnożąc przezx$values aby usunąć zera.

Zwraca complexwektor jednego elementu.

Giuseppe
źródło