Nombres binaires complexes

36

Créons un mappage simple et surjectif des entiers positifs aux entiers gaussiens , qui sont des nombres complexes dans lesquels les parties réelle et imaginaire sont des entiers.

Par exemple, pour un entier positif 4538, exprimez-le en binaire sans interligne 0:

4538 base 10 = 1000110111010 base 2

Supprimez tous les éléments suivants 0:

100011011101

Remplacez les exécutions d'un ou plusieurs 0par un seul +:

1+11+111+1

Remplacez tout 1par ides:

i+ii+iii+i

Evaluez l'expression complexe résultante et générez le nombre entier gaussien simplifié:

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

La sortie peut être exprimée de manière mathématique traditionnelle ou sous forme de deux entiers distincts pour les parties réelle et complexe. Pour l' 4538exemple, n'importe lequel d'entre eux serait bien:

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

Pour les entrées 29telles que 0, les sorties au format mathématique telles que,, 0iou 0+0isont correctes .

Utiliser j(ou autre chose) à la place de iest acceptable si cela est plus naturel pour votre langue.

Le code le plus court en octets gagne.

Les passe-temps de Calvin
la source
D'après le titre, je pensais que le défi concernerait les nombres complexes en binaire, par exemple 4+2j-> 100+10j...
Erik the Outgolfer

Réponses:

22

MATL , 7 octets

BJ*Y'^s

Essayez-le en ligne!

Comment ça marche

Considérons l'entrée 4538par exemple.

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
la source
2
7 octets en MATL, et le meilleur que je puisse obtenir est de 58 en MATLAB ... Vous avez fait un joli petit langage! =)
Stewie Griffin
1
@StewieGriffin représente facilement le meilleur de la série lorsqu'il s'agit de représenter graphiquement ou de dessiner, peut-être aussi pour l'arithmétique matricielle d'après les réponses impressionnantes que je l'ai vu publier.
Urne Magique Octopus 12/12
13

Gelée , 8 octets

BŒgaıP€S

Essayez-le en ligne!

Comment ça marche

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
la source
10

Python 2, 53 octets

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

J'essaie de jouer au golf et cela semble golfable, mais je suis à court d'idées ...

Sp3000
la source
1
Cela (k or 1)ne semble pas optimal, mais la seule autre chose à laquelle je peux penser est (k+0**k)...
ETHproductions
@ETHproductions Mes pensées exactement, mais 0**kne fonctionnent malheureusement pas pour les complexes k...
Sp3000
6

Mathematica, 44 38 octets

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

Explication

#~IntegerDigits~2

Convertir l'entrée en base 2. ( 4538devient {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0})

I*

Multiplier par I( {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0}devient {I, 0, 0, 0, I, I, 0, I, I, I, 0, I, 0})

Split

Divisé en pistes ( {I, 0, 0, 0, I, I, 0, I, I, I, 0, I, 0}devient {{I}, {0, 0, 0}, {I, I}, {0}, {I, I, I}, {0}, {I}, {0}})

1##&@@@ ...

Trouvez le produit au niveau 2. ( {{I}, {0, 0, 0}, {I, I}, {0}, {I, I, I}, {0}, {I}, {0}}devient {I, 0, -1, 0, -I, 0, I, 0})

Tr

Somme le résultat. ( {I, 0, -1, 0, -I, 0, I, 0}devient -1 + I)

JungHwan Min
la source
moins 1 octet:Tr[Times@@@(I*Split@RealDigits[#,2][[1]])]&
martin
1
@martin Eh bien, j'ai utilisé votre idée de multiplier en Ipremier, mais j'ai IntegerDigitsfini par être plus court.
JungHwan Min
oui - bien mieux :)
martin
5

JavaScript (ES6), 67 64 octets

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>

Sort en tant que tableau à 2 éléments.

Explication

Puisque JavaScript n'a pas de nombres imaginaires, nous devons suivre les parties réelle et imaginaire dans des variables séparées. La façon la plus simple de procéder consiste à utiliser un seul tableau, avec la partie réelle en premier. i est représenté par [0,1] , i 2 (ou -1 ) par [-1,0] , i 3 (ou -i ) par [0, -1] et i 4 (ou 1 ) par [1 , 0] .

Premièrement, nous divisons le nombre par 2 à plusieurs reprises, en rassemblant chaque série de uns dans sa représentation binaire. Chaque série de n unités correspond à i n . Cela correspond à l'ajout de 1 - (n & 2) à l'item d'index n & 1 dans le tableau à deux items. Donc c'est ce que nous faisons.

Je devrais probablement ajouter plus d'explications, mais je ne peux pas penser à quoi d'autre a besoin d'expliquer. Ne hésitez pas à commenter avec toutes les questions que vous pourriez avoir.

ETHproductions
la source
5

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

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

L'entrée est juste le nombre lui-même.
La sortie est au format (a+bj), où jest l'unité imaginaire. 0jsera sorti au lieu de(0+0j)

Tout d'abord convertir en binaire. Tronquer le '0b'off. Tuez les zéros à la fin. Fractionner en utilisant un bloc de zéro (s) en tant que délimiteur. Mappez chaque bloc sur 1j ** len. Ensuite, prenez la somme de la chose entière.

-70 octets en ne convertissant pas en plus.
-5 octets regex est plus court.
-8 octets en éliminant les deux variables inutiles appelées une seule fois.
-22 octets en utilisant des nombres complexes au lieu de mon étrange chose. Merci à la réponse de @Dennis de m'avoir informé des nombres complexes!
-4 octets en réalisant que mapc'est juste une façon élégante de faire des compréhensions de liste, sauf plus longtemps.
-19 octets en passant à une méthode légèrement mystérieuse pour éviter les erreurs j ** 0et éviter les expressions rationnelles. Inspiré par le commentaire de @ Griffin. Merci! :)
-8 octets en déplaçant la ifpièce à la fin.
-2 octets Merci à @Griffin d'avoir économisé 2 octets en supprimant les crochets pour en faire une expression génératrice!

HyperNeutrino
la source
J'ai quelque chose d'assez similaire alors ne posterai pas de réponse séparée, mais un peu plus courtesum(1j**x.count('1')for x in bin(input()).split('0')if x)
Griffin
@ Griffin Nice. Je pense que c'est assez différent pour que vous puissiez poster une réponse séparée, car elle utilise une méthode différente pour compter les 1blocs et n'utilise pas de regex comme le mien. De plus, je ne veux pas vous voler le code car il est bien meilleur que ma version. :)
HyperNeutrino
@Griffin J'ai trouvé une autre solution de la même longueur que votre solution, mais au lieu de compter le nombre de 1s plutôt que la longueur, la 0xpièce est d'abord placée au premier plan. Merci pour l'idée de déplacer le ifà la fin; Je n'aurais jamais su que ça marche autrement!
HyperNeutrino
vous n'avez pas besoin de la compréhension de la liste. Supprimez les crochets pour en faire une expression génératrice
Griffin
@Griffin Oh. D'accord merci! Je me souviendrai de cela pour le futur golf
HyperNeutrino
4

MATLAB, 58 octets

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

Utilisons 285pour illustrer le processus:

temp1 = dec2bin(285)
      = 100011101

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

Heureusement , 1+++1se comporte comme 1+1dans Matlab, de sorte que les evalue ci - dessus à: 1+111+1.

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

Maintenant, cet strrepappel est le vrai bijou! En insérant i*1pour 1quelque chose de vraiment sympa. S'il n'y en a qu'un 1, nous obtenons simplement i*1ce qui est i. S'il y a plus d'un alors i*1se répète et concaténées en une séquence: i*1i*1i*1i*1. Depuis i==1idans Matlab et 1i*1==icela est tout simplement: i*i*i*i.

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

Ajouter .0semble inutile ici, mais il est nécessaire si le dernier caractère temp3est un +. Nous ne pouvons pas ajouter un zéro, car cela donnerait i*10le cas précédent et donnerait donc un résultat erroné.

Et enfin:

eval(temp4)
0.0000 + 1.0000i

Cela ne fonctionne pas dans Octave pour plusieurs raisons. strrepne peut pas prendre les valeurs ASCII en entrée, il faut les caractères réels ( '0'au lieu de 48). De plus, +++n'évalue pas uniquement +Octave, cela casserait les raccourcis d'incrémentation / décrémentation x++et x--.

Stewie Griffin
la source
1
Toujours +1 pour utiliser eval:-P Ne pouvez-vous pas utiliser 1iau lieu de 1*i?
Luis Mendo
1
Oh, vous l'utilisez différemment. Très intelligent!
Luis Mendo
Merci :-) Je dois admettre que j'étais assez satisfait de la i*1partie ...
Stewie Griffin
2

Mathematica, 84 octets

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

Fonction anonyme. Prend un nombre en entrée et renvoie un nombre complexe en sortie.

LegionMammal978
la source
6
Wow, je suis surpris que Mathematica n'ait pas de fonction intégrée pour cela!
HyperNeutrino
2

Mathematica, 75 octets

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

Indépendamment est venu avec presque la même solution que LegionMammal978 a posté il y a 23 minutes! Remplacer 1par I (qui est le symbole interne de Mathematica pour la racine carrée de -1) fonctionne car les espaces sont traités comme une multiplication d'expressions voisines. La place que j'ai sauvegardée sur l'autre solution, à savoir en évitant de recourir à StringTrim, est toujours ajoutée -0: si le nombre binaire se termine par 1, alors cette expression se termine ...I-0sans affecter sa valeur; tandis que si le nombre binaire se termine par '0', alors cette expression se termine par ...+-0ce qui est analysé comme "ajoute un négatif" et supprime ainsi le signe plus final.

Greg Martin
la source
2

Matlab, 99 octets

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

Cas de test:

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

Haskell, 102 91 89 87 octets

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)

Divise à plusieurs reprises par deux et vérifie le bit. Conserve un accumulateur de i^(number of odds)a+b*iest codé comme [a,b]et *iest [a,b]↦[-b,a](rotation de 90 degrés). La première (*2)est d'éviter une recherche pour le premier bit.

Utilisation (merci à @OwenMorgan pour les exemples):

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

Java, 172 octets

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
la source
1

Clojure, 183 octets

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

Ai-je le droit de faire ça?

Utilisez la fonction comme suit:

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

En fait , 35 octets

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

Essayez-le en ligne!

Explication:

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

Code Python 3 à peu près équivalent:

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

Essayez-le en ligne!

Mego
la source
Fractionner les 0 avec '0@set utiliser ``░pour couper les dernières chaînes vides devrait vous faire économiser quatre octets.
Sherlock9
1

Gelée , 10 octets

Ce n'est pas mieux que la réponse de Dennis, mais je voulais quand même tenter ma chance. Suggestions de golf bienvenues! Essayez-le en ligne!

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
la source
Dans le lien ci-dessus, l'entrée 1 retourne 1j l'entrée 2 retourne 1j .... Est-ce vrai?
RosLuP
@RosLuP Oui, c'est bien ça? Puisque nous supprimons les 0 qui suivent, cela 1 => 1 => 1jéquivaut à 2 => 10 => 1 => 1j.
Sherlock9
1

En fait , 15 octets

Suggestions de golf bienvenues! Essayez-le en ligne!

├'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
la source
0

Axiom, 140, 131, 118 108 octets

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 est le client imaginaire.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

résultats

(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
la source
0

Perl 6 ,  40  46 octets

Je suis venu avec cela assez rapidement

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

Malheureusement, il est actuellement inexact dans l' implémentation de Rakudo sur MoarVM .
say i ** 3; # -1.83697019872103e-16-1i

Je devais donc faire la meilleure chose suivante:

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

Étendu:

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

Tester:

.say for (4538, 29).map:

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

# -1+1i
# 0+0i
Brad Gilbert b2gills
la source
Rapport de bug déposé
Brad Gilbert b2gills
0

PHP, 87 octets

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

Presque identique à la solution ETHproductions´; seulement itératif au lieu de récursif.
Prend les entrées en ligne de commande, définit les variables ${0}et ${1}.

Titus
la source
0

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

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

Il n’existe aucune possibilité de convertir une chaîne en binaire (ni d’analyser une chaîne), ce programme est donc divisé en 2 manuellement, incrémentant N chaque fois qu’il voit un 1, ajoutant i ^ N à S (N> 0) et réinitialisant. N s'il voit un zéro.

pizzapants184
la source
0

R , 54 octets

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

Essayez-le en ligne!

n%/%2^(0:log2(n))%%2calcule un vecteur des chiffres binaires. En utilisant le codage de longueur d'exécution, nous utilisons le complextype de R pour calculer la somme appropriée, en multipliant par le x$valuespour supprimer les zéros.

Retourne un complexvecteur d'un élément.

Giuseppe
la source