Números binarios complejos

36

Creemos un mapeo simple y sobreyectivo de enteros positivos a enteros gaussianos , que son números complejos donde las partes real e imaginaria son enteros.

Dado un número entero positivo, por ejemplo 4538, exprésalo en binario sin encabezado 0:

4538 base 10 = 1000110111010 base 2

Elimine cualquier rastro 0:

100011011101

Reemplace cualquier ejecución de uno o más 0con una sola +:

1+11+111+1

Reemplace todos los 1's con i' s:

i+ii+iii+i

Evalúe la expresión compleja resultante y genere el entero gaussiano simplificado:

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

La salida se puede expresar de una manera matemática tradicional, o se puede dar como dos enteros separados para las partes real y compleja. Por 4538ejemplo, cualquiera de estos estaría bien:

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

Para las entradas como 29, salidas Mathy formateado como 0, 0io 0+0ison todos bien.

Usar j(o algo más) en lugar de iestá bien si eso es más natural para su idioma.

El código más corto en bytes gana.

Pasatiempos de Calvin
fuente
Por el título, pensé que el desafío sería sobre números complejos en binario, por ejemplo 4+2j-> 100+10j...
Erik the Outgolfer el

Respuestas:

22

MATL , 7 bytes

BJ*Y'^s

Pruébalo en línea!

Cómo funciona

Considere la entrada 4538por ejemplo.

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
fuente
2
7 bytes en MATL, y lo mejor que puedo obtener es 58 en MATLAB ... ¡Has hecho un pequeño y agradable lenguaje allí! =)
Stewie Griffin
1
@StewieGriffin es fácilmente el mejor en cuanto a gráficos o trazados, tal vez también para la aritmética matricial también a partir de las impresionantes respuestas que le he visto publicar.
Magic Octopus Urn
13

Jalea , 8 bytes

BŒgaıP€S

Pruébalo en línea!

Cómo funciona

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

Python 2, 53 bytes

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

He estado tratando de jugar al golf y parece golfable, pero estoy sin ideas atm ...

Sp3000
fuente
1
Eso (k or 1)no parece óptimo, pero lo único que se me ocurre es (k+0**k)...
ETHproductions
@ETHproductions Mis pensamientos exactamente, pero desafortunadamente 0**kno funcionan para complejos k...
Sp3000
6

Mathematica, 44 38 bytes

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

Explicación

#~IntegerDigits~2

Convierta la entrada en la base 2. (se 4538convierte {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0})

I*

Multiplicar por I(se {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0}convierte {I, 0, 0, 0, I, I, 0, I, I, I, 0, I, 0})

Split

Dividido por carreras (se {I, 0, 0, 0, I, I, 0, I, I, I, 0, I, 0}convierte {{I}, {0, 0, 0}, {I, I}, {0}, {I, I, I}, {0}, {I}, {0}})

1##&@@@ ...

Encuentra el producto en el nivel 2. (se {{I}, {0, 0, 0}, {I, I}, {0}, {I, I, I}, {0}, {I}, {0}}convierte {I, 0, -1, 0, -I, 0, I, 0})

Tr

Suma el resultado. (se {I, 0, -1, 0, -I, 0, I, 0}convierte -1 + I)

JungHwan Min
fuente
menos 1 byte:Tr[Times@@@(I*Split@RealDigits[#,2][[1]])]&
martin
1
@martin Bueno, usé tu idea de multiplicar Iprimero, pero IntegerDigitsterminé siendo más corto.
JungHwan Min
sí, mucho mejor :)
martin
5

Python 2 , 77 76 71 bytes

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

¡Gracias a @ZacharyT por jugar golf en 1 byte!

Pruébalo en línea!

Dennis
fuente
5

JavaScript (ES6), 67 64 bytes

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>

Salidas como una matriz de 2 elementos.

Explicación

Como JavaScript no tiene números imaginarios, tenemos que hacer un seguimiento de las partes reales e imaginarias en variables separadas. La forma más fácil de hacerlo es en una sola matriz, con la parte real primero. i se representa como [0,1] , i 2 (o -1 ) como [-1,0] , i 3 (o -i ) como [0, -1] e i 4 (o 1 ) como [1 , 0] .

Primero, dividimos repetidamente el número por 2, recolectando cada serie de unidades en su representación binaria. Cada serie de n unos corresponde a i n . Esto corresponde a agregar 1 - (n & 2) al elemento en el índice n & 1 en la matriz de dos elementos. Entonces eso es lo que hacemos.

Probablemente debería agregar más explicaciones, pero no puedo pensar en qué más hay que explicar. Siéntase libre de comentar con cualquier pregunta que pueda tener.

ETHproducciones
fuente
5

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

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

La entrada es solo el número mismo.
La salida está en el formato (a+bj), donde jestá la unidad imaginaria. 0jsaldrá en lugar de(0+0j)

Primero convierta a binario. Truncar el '0b'apagado. Mata a los ceros finales. Dividir usando un bloque de cero (s) como delimitador. Asigna cada bloque a 1j ** len. Luego, toma la suma de todo.

-70 bytes al no convertir a más.
-5 bytes regex es más corto.
-8 bytes al deshacerse de las dos variables innecesarias que solo se llamaban una vez.
-22 bytes usando números complejos en lugar de mi cosa extraña. ¡Gracias a la respuesta de @Dennis por informarme de números complejos!
-4 bytes al darse cuenta de que mapes solo una forma elegante de hacer comprensiones de listas, excepto por más tiempo.
-19 bytes cambiando a un método ligeramente arcano para evitar errores j ** 0y evitar expresiones regulares. Inspirado por el comentario de @ Griffin. ¡Gracias! :)
-8 bytes moviendo la ifparte al final.
-2 bytes ¡Gracias a @Griffin por guardar 2 bytes eliminando los corchetes para convertirlo en una expresión generadora!

Hiperneutrino
fuente
Obtuve algo bastante similar, así que no publicaré una respuesta por separado, aunque un poco más cortasum(1j**x.count('1')for x in bin(input()).split('0')if x)
Griffin
@Griffin Nice. Creo que es lo suficientemente diferente como para que puedas publicar una respuesta por separado, ya que usa un método diferente para contar los 1bloques y no usa expresiones regulares como la mía. Además, no quiero robarte el código, ya que es mucho mejor que mi versión. :)
HyperNeutrino
@Griffin Encontré otra solución que tiene la misma longitud que su solución, excepto que en lugar de contar 1s en lugar de la longitud, 0xprimero quita la parte del frente. Gracias por la idea de mover ifal final; ¡Nunca hubiera sabido que eso funciona de otra manera!
HyperNeutrino
No necesitas la comprensión de la lista. Quite los corchetes para convertirlo en una expresión generadora
Griffin
@Griffin Oh. ¡Bien gracias! Lo recordaré para el futuro golf
HyperNeutrino
4

MATLAB, 58 bytes

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

Usemos 285para ilustrar el proceso:

temp1 = dec2bin(285)
      = 100011101

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

Por suerte 1+++1se comporta igual que 1+1en MATLAB, por lo que los evalúa anteriores a: 1+111+1.

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

¡Ahora esta strrepllamada es la verdadera joya! Al insertar i*1para 1obtener algo realmente agradable. Si solo hay uno 1, simplemente obtenemos i*1cuál es i. Si hay más de uno, entonces i*1se repite y se concatenan en una secuencia: i*1i*1i*1i*1. Dado que i==1ien MATLAB y 1i*1==iesto simplemente es: i*i*i*i.

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

Anexar .0parece innecesario aquí, pero es necesario si el último carácter de temp3es a +. No podemos agregar solo un cero, ya que eso daría i*10en el caso anterior y, por lo tanto, el resultado incorrecto.

Y finalmente:

eval(temp4)
0.0000 + 1.0000i

Esto no funciona en Octave por varias razones. strrepno puede tomar valores ASCII como entrada, necesita los caracteres reales (en '0'lugar de 48). Además, +++no se evalúa sólo +en Octave, ya que ello romper los atajos de aumento / disminución x++y x--.

Stewie Griffin
fuente
1
Siempre +1 por usar eval:-P ¿No puedes usar en 1ilugar de 1*i?
Luis Mendo
1
Oh, lo estás usando de manera diferente. ¡Muy inteligente!
Luis Mendo
Gracias :-) Debo admitir que estaba bastante satisfecho con la i*1parte ...
Stewie Griffin
3

Pyth - 15 bytes

Frustrantemente largo.

s^L.j)hMe#r8jQ2

Test Suite .

Maltysen
fuente
2

Mathematica, 84 bytes

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

Función anónima. Toma un número como entrada y devuelve un número complejo como salida.

LegionMammal978
fuente
66
¡Vaya, me sorprende que Mathematica no tenga una función integrada para esto!
HyperNeutrino
2

Mathematica, 75 bytes

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

Independientemente se le ocurrió casi la misma solución que LegionMammal978 publicó hace 23 minutos. Reemplazar 1con I (que es el símbolo interno de Mathematica para la raíz cuadrada de -1) funciona porque los espacios se tratan como una multiplicación de expresiones vecinas. El lugar que guardé en la otra solución, es decir, evitando la necesidad de hacerlo StringTrim, es agregando siempre -0: si el número binario termina 1, entonces esta expresión termina en ...I-0lo que no afecta su valor; mientras que si el número binario termina en '0', entonces esta expresión termina en la ...+-0que se analiza como "agregar 0 negativo" y, por lo tanto, elimina el signo más final.

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

Casos de prueba:

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

Haskell, 102 91 89 87 bytes

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)

Se divide repetidamente por dos y comprueba el bit. Mantiene un acumulador de i^(number of odds)donde a+b*iestá codificado como [a,b]y *ies [a,b]↦[-b,a](rotación de 90 grados). La inicial (*2)es evitar una búsqueda para el primer bit.

Uso (gracias a @OwenMorgan por los ejemplos):

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

Java, 172 bytes

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
fuente
1

Clojure, 183 bytes

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

¿Se me permite hacer esto?

Use la función así:

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

En realidad , 35 bytes

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

Pruébalo en línea!

Explicación:

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

Código de Python 3 aproximadamente 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))

Pruébalo en línea!

Mego
fuente
Dividir en '0' con '0@sy usar ``░para recortar cualquier cadena vacía final debería ahorrarle cuatro bytes.
Sherlock9
1

Jalea , 10 bytes

Esto no es mejor que la respuesta Jelly de Dennis, pero de todos modos quería probar suerte con una respuesta Jelly. Sugerencias de golf bienvenidas! Pruébalo en línea!

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
fuente
En el enlace de arriba La entrada 1 devuelve 1j la entrada 2 devuelve 1j ... ¿Es correcto?
RosLuP
@RosLuP Sí, ¿verdad? Como eliminamos los ceros finales, 1 => 1 => 1jes equivalente a 2 => 10 => 1 => 1j.
Sherlock9
1

Actualmente , 15 bytes

Sugerencias de golf bienvenidas! Pruébalo en línea!

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

No golfista:

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

Axioma, 140, 131, 118108 bytes

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 es el costante imaginario.

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

resultados

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

Perl 6 ,  40  46 bytes

Se me ocurrió esto bastante rápido

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

Desafortunadamente, actualmente es inexacto en la implementación de Rakudo en MoarVM .
say i ** 3; # -1.83697019872103e-16-1i

Así que tuve que hacer lo siguiente mejor:

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

Expandido:

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

Prueba:

.say for (4538, 29).map:

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

# -1+1i
# 0+0i
Brad Gilbert b2gills
fuente
Informe de error archivado
Brad Gilbert b2gills
0

PHP, 87 bytes

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

Casi lo mismo que la solución de ETHproductions; solo iterativo en lugar de recursivo.
Toma datos de la línea de comandos, establece variables ${0}y ${1}.

Titus
fuente
0

TI-Basic (TI-84 Plus CE), 70 bytes

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

No hay una función integrada para convertir en una cadena binaria (ni tampoco para analizar una cadena), por lo que este programa se divide manualmente por 2, incrementa N cada vez que ve un 1 y agrega i ^ N a S (N> 0) y reinicia N si ve un cero.

pizzapants184
fuente
0

Java , 100 bytes

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

Pruébalo en línea!

Monja permeable
fuente
0

R , 54 bytes

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

Pruébalo en línea!

n%/%2^(0:log2(n))%%2calcula un vector de los dígitos binarios. Usando la codificación de longitud de ejecución, usamos Rcomplex tipo para calcular la suma apropiada, multiplicando por elx$values para eliminar los ceros.

Devuelve un complexvector de un elemento.

Giuseppe
fuente