Ajout en base -1 + i

64

Les entiers gaussiens sont des nombres complexes de la forme a+biaet bsont les deux entiers. En base -1 + i, tous les nombres entiers gaussiens peuvent être représentés de manière unique à l'aide des chiffres 0et 1, sans qu'un symbole ne soit nécessaire pour indiquer le signe.

Par exemple, 1100en base -1 + i représente le nombre décimal 2, puisque

1*(-1+i)^3 + 1*(-1+i)^2 + 0*(-1+i)^1 + 0*(-1+i)^0
= (2+2i) + (-2i) + 0 + 0
= 2

L'entrée consistera en deux entiers gaussiens en base -1 + i représentés à l'aide des chiffres 01. Cela peut prendre l’une des formes suivantes:

  • Deux chaînes de chiffres distinctes,
  • Deux entiers décimaux consistant à 01représenter les nombres base -1 + i (par exemple 1100pour 2 en base -1 + i),
  • Deux entiers binaires représentant les nombres base -1 + i (par exemple, décimal 12ou 0b1100pour 2 en base -1 + i)
  • Une seule chaîne séparant deux chaînes de chiffres / entiers binaires par un seul séparateur non alphanumérique (par exemple 1100 1100ou 12,12pour 2 + 2)

Affiche la somme des deux nombres entiers de Gauss, également en base -1 + i et représentée à l'aide des chiffres 01(dans l'un des formats autorisés en entrée, pas nécessairement le même choix). La sortie est autorisée à contenir un nombre fini de zéros non significatifs.

Votre fonction ou votre programme doit se terminer dans les 2 secondes pour des entrées de 30 chiffres maximum chacune.

Clarifications supplémentaires

  • Vous pouvez supposer que l'entrée ne contient pas de zéros non significatifs. Dans le cas particulier de 0, vous pouvez choisir soit 0la chaîne vide, soit la représentation.

Cas de test

0, 0 => 0                                      # 0 + 0 = 0
0, 1 => 1                                      # 0 + 1 = 1
1, 1 => 1100                                   # 1 + 1 = 2
1100, 1100 => 111010000                        # 2 + 2 = 4
1101, 1101 => 111011100                        # 3 + 3 = 6
110111001100, 1110011011100 => 0               # 42 + (-42) = 0
11, 111 => 0                                   # i + (-i) = 0
11, 110 => 11101                               # i + (-1-i) = -1
10101, 11011 => 10010                          # (-3-2i) + (-2+3i) = (-5+i)
1010100101, 111101 => 1110100000100            # (-19+2i) + (3-4i) = (-16-2i)

Cas de test plus longs:

11011011010110101110010001001, 111100010100101001001010010101 => 0
111111111111111111111111111111, 111111111111111111111111111111 => 100100100100100100100100100100
101101110111011101110111011101, 101101110111011101110111011101 => 11101001010001000100010001000100011100
100100010101001101010110101010, 100010011101001011111110101000 => 110000110010101100001100111100010
Sp3000
la source
Aucune liste de chiffres?
CalculatriceFeline
@CatsAreFluffy Pas de liste de chiffres, désolé.
Sp3000
96
Vous pouvez enregistrer un octet en changeant -1+ià i-1dans le titre.
mbomb007
1
Maintenant, nous avons besoin d'une conversion dans l'autre sens. : P
Rɪᴋᴇʀ
3
Il y a 1100 types de personnes dans le monde. Ceux qui comprennent le binaire, ceux qui ne le comprennent pas, ceux qui le confondent avec ternaire, ceux qui le confondent avec la base 4, ceux qui le confondent avec la base 5, ceux qui le confondent avec la base -1 + i, ceux qui le confondent avec base 6, ceux qui la confondent avec la base 7, ceux qui la confondent avec la base 8, ceux qui la confondent avec la base 9 ...
wizzwizz4

Réponses:

42

Python 2, 98 97 91 84 octets

s=input();L=1
for _ in`s`*8:s+=1098*int(str(s).translate('0011'*64));L*=10
print s%L

Cela ne I / O en décimal. Les nombres entiers doivent être séparés par un caractère non alphanumérique +.

Merci à @xnor d'avoir joué 2 octets!

Essayez-le sur Ideone .

Comment ça fonctionne

Dans Arithmetic in Complex Bases , l'auteur montre comment ajouter et multiplier des nombres complexes dans des bases de la forme -n + i .

Pour la base -1 + i , l’addition est similaire à l’addition régulière, binaire avec retenue, avec deux différences:

  • Au lieu de porter 1 à la position immédiatement supérieure, nous en porterons 110 aux trois prochaines.

  • Les chiffres porteurs peuvent se propager indéfiniment. Cependant, sans les zéros de tête, la somme a + b a au plus huit chiffres plus que le maximum de a et b .

Nous procédons comme suit.

  1. Tout d'abord, nous ajoutons a et b comme si leurs chiffres étaient des chiffres décimaux.

    Pour a = 10101 et b = 11011 , cela donne 21112 .

  2. Ensuite, nous formons un nouveau numéro en remplaçant les chiffres plus grands que 1 par un 1 , les autres par un 0 . 1

    Pour la somme 21112 , cela donne 10001 .

  3. Pour chaque chiffre supérieur à 1 , nous devons soustraire 2 de ce chiffre et en porter 110 aux trois positions les plus élevées. Puisque 1098 = 10 * 110 - 2 , nous pouvons y parvenir en multipliant le résultat de l’étape 2 par 1098 , puis en ajoutant ce produit à la somme. 2

    Pour la somme 21112 , cela donne 21112 + 1098 * 10001 = 21112 + 10981098 = 11002210 .

  4. Nous répétons les étapes 2 et 3 un total de d * 8 fois, où d est le nombre de chiffres de a + b . 3

    Pour la somme initiale 21112 , les résultats sont

                          11002210
                          12210010
                        1220010010
                      122000010010
                    12200000010010
                  1220000000010010
                122000000000010010
              12200000000000010010
            1220000000000000010010
          122000000000000000010010
        12200000000000000000010010
      1220000000000000000000010010
    122000000000000000000000010010
                                 .
                                 .
                                 .
    
  5. Nous prenons la somme finale modulo 10 j + 8 , en éliminant tous les d, sauf les derniers d + 8 chiffres.

    Pour la somme initiale 21112 , le résultat final est 10010 .


1 Ceci est réalisé avec translate . La répétition de la chaîne 0011 64 fois permet à une répétition de s'aligner sur la séquence de caractères ASCII 0123 , permettant ainsi d' obtenir le remplacement souhaité.

2 Notez que les chiffres de cette somme ne peuvent pas excéder 3 (valeur initiale 1 plus deux 1 de reports).

3 Cela fonctionne pour d = 1 et d * 8> d + 8 sinon. Le code peut répéter les étapes (d + 1) * 8 fois, car s est suivi d'un L final si s est un entier long .

Dennis
la source
7
C'est de la magie profonde . Quel format input()attend? (Je reçois 21112quand je saisis 10101, 11011.)
Tim Pederick
1
Ça ne fait rien; qui exécutait une version traduite (sans succès, semble-t-il) en Python 3. Cela fonctionne très bien sous Python 2 .
Tim Pederick
9
...Comment. S'il vous plaît. Explique.
Nic Hartley
@QPaysTaxes J'ai modifié ma réponse.
Dennis
@ Dennis Maintenant, pourriez-vous expliquer pourquoi cela fonctionne? Par exemple, pourquoi d+8et pas, disons d+9? Comment????
Nic Hartley
16

Pyth, 34 octets

_shM.u,%J/eMeN\12-+PMeNm.B6/J2k,kQ

Essayez-le en ligne: Démonstration ou Suite de tests (prend un certain temps). Cela devrait facilement satisfaire à la limitation de temps, car le compilateur en ligne est assez lent par rapport au compilateur normal (hors ligne).

Explication:

Mon algorithme est fondamentalement une implémentation d’addition à porter. Mais au lieu de porter 1, je dois porter 110( 1100dans la base -1+iest la même que 2dans la base -1+i). Cela fonctionne généralement très bien, mais vous pouvez rester bloqué dans une boucle infinie d’impressions de zéros. Par exemple, si vous ajoutez 1avec 11et avez actuellement le report 110. Donc, en gros, j'ajoute jusqu'à ce que je reste bloqué dans une boucle, puis je m'arrête. Je pense qu’une boucle imprimera toujours des zéros et que cela devrait donc aller.

_shM.u,%J/eMeN\12-+PMeNm.B6/J2k,kQ   implicit: Q = input list of strings
                               ,kQ   create the pair ["", Q]
    .u                               modify the pair N (^) until loop:
      ,                                replace N with a new pair containing:
            eN                           N[1] (the remaining summand)
          eM                             take the last digits of each summand
         /    \1                         count the ones
        J                                store the count in J
       %J       2                        J % 2 (this is the first element of the new pair)
                   PMeN                  remove the last digit of each summand
                  +    m   /J2           and add J / 2 new summand:
                        .B6                 with the value "110" (binary of 6)
                 -            k          remove empty summand
    .u                               returns all intermediate results
  hM                                 extract the digits
 s                                   sum them up to a long string
_                                    reverse
Jakube
la source
13

Python 2, 69 67 octets

f=lambda a,b:a*a+b*b^58and 2*f(a*b%2*6,f(a/2,b/2))|a+b&1if a else b

I / O est fait avec des entiers base 2.

-2 merci à Dennis.

feersum
la source
Je le prends a*a+b*b^58==0quand aet bsont inverses? Comment ça marche?
xnor
@xnor Non, a*a+b*b==58quand l'un d'eux a 3 ans et l'autre 7 ans.
feersum
1
Ce n'est pas évident que ce (3,7)soit la seule paire qui donne un cycle et qui a besoin d'un boîtier spécial. Si cela est vrai, il vous suffira de vérifier (a,b)==(3,7)dans cet ordre, puisque (7,3)récursivement (3,7), et peut-être une expression plus courte pour cela.
Xnor
1
Maintenant , c'est garanti à confondre tous ceux qui ne sait pas (ou oublie) qui (a) est XOR, non Exponentiation, ou (b) XOR a priorité inférieur . ^+
Tim Pederick
12

Retina , 100 octets

r+`(.*)(\d|(?!\4))( .*)(.?)
$2$4:$1$3
T` 0
+`1:11(1*:1*)11
:$1
^:*
:::
}`:(1*:1*:)11
1:1$1
(1)*:
$#1

Cela prend l’entrée séparée par une virgule. La sortie commence toujours par trois zéros au début.

Essayez-le en ligne!

Je me demande vraiment s'il existe une solution plus courte pour la première étape ...

Martin Ender
la source
2
Non, non, le score est parfait tel qu'il est;)
Conor O'Brien
2
Beau score de -2i!
Nic Hartley
Sensationnel. Je n'ai pas vu cette solution lorsque j'ai posté le mien ... Bien plus que ma solution.
Leaky Nun
@KennyLau J'étais juste en train de regarder et de penser "hm, j'imagine que j'aurais dû ajouter une explication à un moment donné ..."
Martin Ender
...- 2i? C'est décimal, mais le programme utilise une base qui non.
user75200
12

Jelly, 29 28 26 24 21 20 octets

DBḅ1100ḌµDL+8µ¡Dṣ2ṪḌ

Cela ne I / O en décimal. Les nombres entiers doivent être séparés par un caractère non alphanumérique +.

Essayez-le en ligne! ou vérifier tous les cas de test .

Contexte

Dans Arithmetic in Complex Bases , l'auteur montre comment ajouter et multiplier des nombres complexes dans des bases de la forme -n + i .

Pour la base -1 + i , l’addition est similaire à l’addition régulière, binaire avec retenue, avec deux différences:

  • Au lieu de porter 1 à la position immédiatement supérieure, nous en porterons 110 aux trois prochaines.

  • Les chiffres porteurs peuvent se propager indéfiniment. Cependant, sans les zéros de tête, la somme a + b a au plus huit chiffres plus que le maximum de a et b .

Nous procédons comme suit.

  1. Tout d'abord, nous ajoutons a et b comme si leurs chiffres étaient des chiffres décimaux.

    Pour a = 10101 et b = 11011 , cela donne 21112 .

  2. Pour chaque chiffre supérieur à 1 , nous devons soustraire 2 de ce chiffre et en porter 110 aux trois positions les plus élevées. On peut y parvenir en convertissant chaque chiffre décimal en binaire, les matrices binaires résultantes de la base 1100 à un nombre entier, et interpréter la liste résultante de 0 « s, 1 » s, 1100 « s et 1101 » s en tant que base non-canonique 10 nombre. 1

    Pour la somme 21112 , cela donne 21112 + 1098 * 10001 = 21112 + 10981098 = 11002210 .

  3. Nous répétons les étapes 2 un total de d + 8 fois, où d est le nombre de chiffres de a + b .

    Pour la somme initiale 21112 , les résultats sont

                          11002210
                          12210010
                        1220010010
                      122000010010
                    12200000010010
                  1220000000010010
                122000000000010010
              12200000000000010010
            1220000000000000010010
          122000000000000000010010
        12200000000000000000010010
      1220000000000000000000010010
    122000000000000000000000010010
    
  4. Nous éliminons tous les d + 8 derniers chiffres du résultat final, sauf les derniers . Ceci est réalisé en éliminant tout après les 2 derniers . 2

    Pour la somme initiale 21112 , le résultat final est 10010 .

Comment ça fonctionne

DBḅ1100ḌµDL+8µ¡Dṣ2ṪḌ  Main link. Argument: a + b (implicit sum)

        µ    µ¡       Execute the chain before the first µ n times, where n is
                      the result of executing the chain before the second µ.
         D            Convert a + b to base 10.
          L           Length; count the decimal digits.
           +8         Add 8 to the number of digits.
D                     Convert the initial/previous sum to base 10.
 B                    Convert each digit (0 - 3) to binary.
  ḅ1100               Convert each binary array from base 1100 to integer.
       Ḍ              Interpret the resulting list as a base 10 number.
               D      Convert the final sum to base 10.
                ṣ2    Split at occurrences of 2.
                  Ṫ   Select the last chunk.
                   Ḍ  Convert from base 10 to integer.

1 Notez que les chiffres de cette somme ne peuvent pas excéder 3 (valeur initiale 1 plus deux 1 de reports).

2 Ceci fonctionne car le dernier chiffre qui sera annulé ne peut pas être un 3 .

Dennis
la source
6

Python 3, 289 octets

Ceci effectue une addition digitale du chiffre le moins significatif au chiffre le plus significatif (en d'autres termes, le même algorithme que celui enseigné à l'école primaire). Les différences sont que (a) c'est en binaire, pas décimal, donc vous portez chaque fois qu'un chiffre est égal à 2 ou plus, et (b) 1 + 1 = 1100, pas 10.

En fait, il faut aussi noter que 11 + 111 = 0sinon les sommes qui devraient devenir zéro ne se termineront jamais.

from collections import*
def a(*s,p=0):
 r=defaultdict(int,{0:0})
 for S in s:
  n=0
  for d in S[::-1]:r[n]+=d=='1';n+=1
 while p<=max(r):
  while r[p]>1:
   r[p]-=2
   if r[p+1]>1<=r[p+2]:r[p+1]-=2;r[p+2]-=1
   else:r[p+2]+=1;r[p+3]+=1
  p+=1
 return str([*map(r.get,sorted(r))])[-2::-3]

Plus de golf est sûrement possible.

Tim Pederick
la source
Dans quelle mesure êtes-vous certain que votre "détecteur de zéro" est suffisant?
Yakk
4
@Yakk: Sur une échelle allant d'un journal à un autre, donnez-lui peut-être un sans-contre-exemple?
Tim Pederick
2

Retina, 157 151 134 133 124 123 octets

1 byte off grâce à Martin Büttner.

(.+),(.+)
$.1$*0$2,$.2$*0$1,
1
0x
+`(0x*)(,.*)0(x*),
$2,$1$3
{`,

(^|0x0xx0xx)
000
(0x*)(0x*)(0x*0)xx
$1x$2x$3
)`^0+
0
0x
1

Essayez-le en ligne!

Convertit en unaire, puis répète les remplacements suivants (indiqués ici en décimal):

122 -> 000
0002 -> 1100 (this can also be 0012 -> 1110 and 1112 -> 2210 or even 2222 -> 3320 or even 3333 -> 4431)

En gros, quand plus grand que deux: enlevez deux, n'ajoutez rien dans le chiffre précédent, ajoutez un au chiffre précédent, puis ajoutez un au chiffre précédent.

En pseudocode:

if(a[n]>2):
    a[n] -= 2;
    a[n-2] += 1;
    a[n-3] += 1;

Mise en œuvre unaire:

Chaque chiffre (par exemple 3) est indiqué par le nombre de xs (par exemple xxx) et est ensuite précédé de 0.

Par exemple, 1234serait exprimé comme 0x0xx0xxx0xxxx.

Cela reste 0inchangé, comme le 101dirait 0x00x.

Depuis le début et enfin, il n'y a que 0et 1, la conversion pourrait être facilement faite par 1->0xet 0x->1.

Cliquez ici pour voir chaque étape .

Fuite Nun
la source
1

JavaScript (ES6), 146 126 octets

r=n=>n&&n%2-r(n>>=1)-i(n)
i=n=>n&&r(n>>=1)-i(n)
g=(x,y,b=(x^y)&1)=>x|y&&b+2*g(b-x+y>>1,b-x-y>>1)
(x,y)=>g(r(x)+r(y),i(x)+i(y))

gconvertit un entier gaussien (parties réelles et imaginaires) en base i-1, tandis rque iconvertit un i-1entier de base en un entier gaussien (parties réelle et imaginaire, respectivement). Une fois que les conversions sont en place, il me suffit de faire l’arithmétique.

Edit: Sauvegardé 20 octets en calculant les parties réelle et imaginaire séparément.

Neil
la source
1

C ++ 416 octets, plus #include <vector>\n#include <algorithm>\n(40 autres)

using I=int;using v=std::vector<I>;void r(v&x){v r{rbegin(x),rend(x)};x=r;}v a(v L,v R){r(L);r(R);L.resize(std::max(L.size(),R.size()));for(int&r:R)L[&r-R.data()]+=r;while(1){L.resize(L.size()+3);auto it=find(rbegin(L),rend(L),2);if(it==rend(L))break;I i=-1+it.base()-begin(L);i&&L[i+1]&&L[i-1]/2?L[i+1]=L[i]=L[i-1]=0:(++L[i+2],++L[i+3],L[i]=0);}L.erase( std::find(rbegin(L),rend(L),1).base(),end(L));r(L);return L;}

ou, avec plus d'espaces:

using I=int;
using v=std::vector<I>;

void r(v&x){v r{rbegin(x),rend(x)};x=r;}
v a(v L,v R) {
  r(L);r(R);
  L.resize(std::max(L.size(),R.size()));
  for(int&r:R)
    L[&r-R.data()]+=r;
  while(1) {
    L.resize(L.size()+3);
    auto it=find(rbegin(L), rend(L), 2);
    if(it==rend(L)) break;
    I i=-1+it.base()-begin(L);
    i&&L[i+1]&&L[i-1]/2?
      L[i+1]=L[i]=L[i-1]=0
    :
      (++L[i+2],++L[i+3],L[i]=0);
  }
  L.erase( std::find(rbegin(L),rend(L),1).base(), end(L));
  r(L);
  return L;
}

À peine golfé. Il prend en entrée un vecteur d'ints et renvoie un vecteur d'ints.

Exemple en direct .

Yakk
la source