Numeri binari complessi


36

Creiamo una mappatura semplice e suriettiva da numeri interi positivi a numeri interi gaussiani , che sono numeri complessi in cui le parti reali e immaginarie sono numeri interi.

Dato un numero intero positivo, ad esempio 4538, esprimilo in binario senza nessun carattere iniziale 0:

4538 base 10 = 1000110111010 base 2

Rimuovi eventuali tracce 0:

100011011101

Sostituisci tutte le esecuzioni di uno o più 0con una singola +:

1+11+111+1

Sostituisci tutto 1con i:

i+ii+iii+i

Valuta l'espressione complessa risultante e visualizza l'intero intero gaussiano semplificato:

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

L'output può essere espresso in un modo matematico tradizionale o dato come due numeri interi separati per le parti reali e complesse. Per l' 4538esempio, uno di questi andrebbe bene:

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

Per gli ingressi come 29, uscite Mathy formattati come 0, 0io 0+0isono tutti bene.

Usare j(o qualcos'altro) invece di iva bene se è più naturale per la tua lingua.

Vince il codice più breve in byte.


Dal titolo ho pensato che la sfida riguardasse numeri complessi in binario, ad es. 4+2j-> 100+10j...
Erik the Outgolfer

Risposte:


22

MATL , 7 byte

BJ*Y'^s

Provalo online!

Come funziona

Si consideri l'input 4538per esempio.

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 in MATL, e il migliore che posso ottenere è 58 in MATLAB ... Hai fatto un bel linguaggio lì! =)
Stewie Griffin l'

1
@StewieGriffin è semplicemente il migliore in mostra quando si tratta di rappresentare graficamente o tracciare, forse anche per l'aritmetica della matrice dalle fantastiche risposte che l'ho visto pubblicare.
Magic Octopus Urn

13

Gelatina , 8 byte

BŒgaıP€S

Provalo online!

Come funziona

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

Ho provato a giocare a golf e sembra giocabile ma io sono fuori di idee atm ...


1
Ciò (k or 1)non sembra ottimale, ma l'unica altra cosa che viene in mente è (k+0**k)...
ETHproductions

@ETHproductions I miei pensieri esattamente, ma sfortunatamente 0**knon funziona per complessi k...
Sp3000

6

Mathematica, 44 38 byte

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

Spiegazione

#~IntegerDigits~2

Converti l'input in base 2. ( 4538diventa {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0})

I*

Moltiplicare per I( {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0}diventa {I, 0, 0, 0, I, I, 0, I, I, I, 0, I, 0})

Split

Dividi per piste ( {I, 0, 0, 0, I, I, 0, I, I, I, 0, I, 0}diventa {{I}, {0, 0, 0}, {I, I}, {0}, {I, I, I}, {0}, {I}, {0}})

1##&@@@ ...

Trova il prodotto al livello 2. ( {{I}, {0, 0, 0}, {I, I}, {0}, {I, I, I}, {0}, {I}, {0}}diventa {I, 0, -1, 0, -I, 0, I, 0})

Tr

Somma il risultato. ( {I, 0, -1, 0, -I, 0, I, 0}diventa -1 + I)


meno 1 byte:Tr[Times@@@(I*Split@RealDigits[#,2][[1]])]&
martin

1
@martin Beh, ho usato la tua idea di moltiplicare Iprima, ma alla IntegerDigitsfine sono stata più breve.
JungHwan Min

si - molto meglio :)
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

Grazie a @ZacharyT per giocare a golf a 1 byte!

Provalo online!


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 come un array a 2 elementi.

Spiegazione

Poiché JavaScript non ha numeri immaginari, dobbiamo tenere traccia delle parti reali e immaginarie in variabili separate. Il modo più semplice per farlo è in un singolo array, con prima la parte reale. i è rappresentato come [0,1] , i 2 (o -1 ) come [-1,0] , i 3 (o -i ) come [0, -1] e i 4 (o 1 ) come [1 , 0] .

Innanzitutto, dividiamo ripetutamente il numero per 2, raccogliendo ciascuna serie di quelli nella sua rappresentazione binaria. Ogni serie di n corrisponde a i n . Ciò corrisponde all'aggiunta di 1 - (n & 2) all'elemento nell'indice n & 1 nell'array a due elementi. Quindi è così.

Probabilmente dovrei aggiungere ulteriori spiegazioni, ma non riesco a pensare a cos'altro debba essere spiegato. Sentiti libero di commentare con qualsiasi domanda tu possa avere.


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)

L'input è solo il numero stesso.
L'output è nel formato (a+bj), dove si jtrova l'unità immaginaria. 0jverrà emesso invece di(0+0j)

Prima converti in binario. Tronca lo '0b'spento. Uccidi gli zeri finali. Dividi usando un blocco di zero (s) come delimitatore. Mappa ogni blocco a 1j ** len. Quindi, prendi la somma dell'intera cosa.

-70 byte non convertendoli in più.
-5 byte regex è più breve.
-8 byte eliminando le due variabili non necessarie che venivano chiamate una sola volta.
-22 byte usando numeri complessi invece della mia strana cosa. Grazie alla risposta di @Dennis per avermi informato di numeri complessi!
-4 byte rendendosi conto che mapè solo un modo elaborato per fare la comprensione della lista, se non più a lungo.
-19 byte passando a un metodo leggermente arcano per evitare errori j ** 0ed evitare regex. Ispirato dal commento di @ Griffin. Grazie! :)
-8 byte spostando la ifparte alla fine.
-2 byte Grazie a @Griffin per aver salvato 2 byte rimuovendo le parentesi quadre per renderlo invece un'espressione del generatore!


Ho qualcosa di abbastanza simile, quindi non pubblicherò una risposta separata, un po 'più brevesum(1j**x.count('1')for x in bin(input()).split('0')if x)
Griffin,

@Griffin Nice. Penso che sia abbastanza diverso che tu possa pubblicare una risposta separata, dal momento che utilizza un metodo diverso di contare i 1blocchi e non usa regex come il mio. Inoltre, non voglio rubarti il ​​codice poiché è molto meglio della mia versione. :)
HyperNeutrino il

@Griffin Ho trovato un'altra soluzione della stessa lunghezza della tua soluzione tranne che invece di contare 1s piuttosto che lunghezza, toglie prima la 0xparte dalla parte anteriore. Grazie per l'idea di spostare il iffino alla fine; Non avrei mai saputo che funzionasse diversamente!
HyperNeutrino,

non hai bisogno della comprensione dell'elenco. Rimuovi le parentesi quadre per renderlo un'espressione del generatore
Griffin

@Griffin Oh. Va bene, grazie! Lo ricorderò per il futuro golf
HyperNeutrino il

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.   

Usiamo 285per illustrare il processo:

temp1 = dec2bin(285)
      = 100011101

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

Per fortuna 1+++1si comporta proprio come 1+1in MATLAB, quindi i Esamina sopra per: 1+111+1.

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

Ora questa strrepchiamata è la vera gemma! Inserendo i*1per 1otteniamo qualcosa di veramente bello. Se ce n'è solo uno 1, capiamo semplicemente i*1quale è i. Se ci sono più di una, allora i*1ottiene ripetuto e concatenati in una sequenza: i*1i*1i*1i*1. Dal momento che i==1iin MATLAB e 1i*1==iquesto semplicemente è: i*i*i*i.

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

L'aggiunta .0sembra non necessaria qui, ma è necessaria se l'ultimo carattere di temp3è a +. Non possiamo aggiungere solo uno zero, poiché ciò darebbe i*10nel caso sopra e quindi il risultato sbagliato.

E infine:

eval(temp4)
0.0000 + 1.0000i

Questo non funziona in Octave per diversi motivi. strrepnon può accettare valori ASCII come input, necessita dei caratteri effettivi ( '0'anziché 48). Inoltre, +++non valuta solo +in Octave, poiché ciò spezzerebbe le scorciatoie di incremento / decremento x++e x--.


1
Sempre +1 per l'utilizzo eval:-P Non puoi usare 1iinvece di 1*i?
Luis Mendo,

1
Oh, lo stai usando in modo diverso. Molto intelligente!
Luis Mendo,

Grazie :-) Devo ammettere che ero abbastanza soddisfatto del i*1 parte ...
Stewie Griffin


2

Mathematica, 84 byte

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

Funzione anonima. Prende un numero come input e restituisce un numero complesso come output.


6
Wow, sono sorpreso che Mathematica non abbia un built-in per questo!
HyperNeutrino

2

Mathematica, 75 byte

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

Indipendentemente è arrivata la stessa soluzione che LegionMammal978 ha pubblicato 23 minuti fa! La sostituzione 1con I (che è il simbolo interno di Mathematica per la radice quadrata di -1) funziona perché gli spazi sono trattati come una moltiplicazione di espressioni vicine. Il posto che ho salvato sull'altra soluzione, vale a dire evitandone la necessità StringTrim, è sempre l'aggiunta -0: se il numero binario finisce 1, allora questa espressione termina in ...I-0cui non influisce sul suo valore; mentre se il numero binario termina in '0', allora questa espressione termina in ...+-0cui viene analizzata come "aggiungi 0 negativo" e quindi elimina il segno più finale.


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

Casi test:

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)

Si divide ripetutamente per due e controlla il bit. Mantiene un accumulatore di i^(number of odds)dove a+b*iviene codificato com'è [a,b]e lo *iè [a,b]↦[-b,a](rotazione di 90 gradi). L'iniziale (*2)è evitare una ricerca per il primo bit.

Utilizzo (grazie a @OwenMorgan per gli esempi):

(%[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))))

Mi è permesso farlo?

Utilizzare la funzione in questo modo:

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

1

In realtà , 35 byte

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

Provalo online!

Spiegazione:

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

Codice Python 3 approssimativamente equivalente:

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

Provalo online!


Dividere su '0' con '0@se usare ``░per tagliare qualsiasi stringa vuota finale dovrebbe farti risparmiare quattro byte.
Sherlock9,

1

Gelatina , 10 byte

Non è meglio della risposta di Jelly di Dennis, ma volevo comunque provare la mia risposta a una Jelly. Suggerimenti di golf benvenuti! Provalo 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.

Nel link sopra L'ingresso 1 restituisce 1j l'ingresso 2 restituisce 1j .... Esatto?
RosLuP il

@RosLuP Sì, esatto? Poiché rimuoviamo gli 0 finali, 1 => 1 => 1jequivale a 2 => 10 => 1 => 1j.
Sherlock9,

1

In realtà , 15 byte

Suggerimenti di golf benvenuti! Provalo 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.

0

Axiom, 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 è il costante immaginario

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

risultati

(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

L'ho pensato abbastanza rapidamente

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

Purtroppo al momento non è accurato nell'implementazione di Rakudo su MoarVM .
say i ** 3; # -1.83697019872103e-16-1i

Quindi ho dovuto fare la prossima cosa migliore:

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

Allargato:

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


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

Quasi uguale alla soluzione di ETHproductions; solo iterativo invece che ricorsivo.
Prende input dalla riga di comando, imposta variabili ${0}e ${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

Non c'è un builtin da convertire in una stringa binaria, (né c'è per analizzare una stringa), quindi questo programma si divide manualmente per 2, incrementando N ogni volta che vede un 1 e aggiungendo i ^ N a S (N> 0) e ripristinando N se vede uno zero.



0

R , 54 byte

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

Provalo online!

n%/%2^(0:log2(n))%%2calcola un vettore delle cifre binarie. Usando la codifica run-length, usiamo il complextipo di R per calcolare la somma appropriata, moltiplicando per il x$valuesper rimuovere gli zeri.

Restituisce un complexvettore di un elemento.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.