Convertisseur de base numérique personnalisé

30

Les pouvoirs en place veulent pouvoir convertir rapidement n'importe quel nombre qu'ils ont en leur propre base numérique en utilisant le format qu'ils souhaitent.

Contribution

Votre programme doit accepter 3 paramètres.

  1. Number: numéro de chaîne à convertir
  2. InputFormat: la chaîne de base dans laquelle le numéro est actuellement
  3. OutputFormat: la chaîne de base dans laquelle le nombre doit être converti.

Sortie

Votre programme doit convertir la base Numberde l'ancien numéro InputFormaten la nouvelle base de numéroOutputFormat

Exemples

("1","0123456789","9876543210") = "8"
("985724","9876543210","0123456789ABCDEF") = "37C3"
("FF","0123456789ABCDEF","0123456789") = "255"
("FF","0123456789ABCDEF","01234567") = "377"
("18457184548971248772157", "0123456789","Aa0Bb1Cc2Dd3Ee4Ff5Gg6Hh7Ii8Jj9Kk,Ll.Mm[Nn]Oo@Pp#Qq}Rr{Ss-Tt+Uu=Vv_Ww!Xx%Yy*Zz") = ",sekYFg_fdXb"

Additionnel

Le nouveau test de base 77 n'est pas un accessoire nécessaire s'il fonctionne bien

  1. si vous êtes dans une langue où vous devez d'abord convertir en nombre et êtes verrouillé dans 32 bits, vous pouvez l'ignorer.
  2. car c'est un test supplémentaire.

Tous les exemples ont été générés par PHP 7.2 avec l'extension bcmath en utilisant le code suivant (vars mins mais formaté en code). il y aura probablement un moyen plus court, c'est juste la façon dont j'ai trouvé le système avec lequel je devais le faire serait bien de voir si quelqu'un pourrait proposer une version plus courte.

PHP 7.2 (bcmath - extension) 614 octets

<?php
function f($a, $b, $c)
{
    $d= str_split($b,1);
    $e= str_split($c,1);
    $f= str_split($a,1);
    $g=strlen($b);
    $h=strlen($c);
    $k=strlen($a);
    $r='';
    if ($c== '0123456789')
    {
        $r=0;
        for ($i = 1;$i <= $k; $i++)
            $retval = bcadd($retval, bcmul(array_search($f[$i-1], $d),bcpow($g,$k-$i)));
        return $r;
    }
    if ($b!= '0123456789')
        $l=f($a, $b, '0123456789');
    else
        $l= $a;
    if ($l<strlen($c))
        return $e[$l];
    while($l!= '0')
    {
        $r= $e[bcmod($l,$h)].$r;
        $l= bcdiv($l,$h,0);
    }
    return $r;
}

Essayez-le en ligne

Notation

C'est le golf de code; le code le plus court gagne. Des échappatoires standard s'appliquent.

Martin Barker
la source
5
@WindmillCookies Par tous les caractères dans les chaînes de format.
Adám
6
Belle première question! :-)
Giuseppe
2
Étroitement liés .
AdmBorkBork
2
Il peut être utile d'ajouter un cas de test pour une base "unique" - par exemple ["zX", "tXdsyqzSDRP02", "brFNC02bc"] => "cb". (ou quoi que ce soit en fait, si c'est incorrect)
Fund Monica's Lawsuit
2
Je suggérerais un cas de test avec plus de 36 caractères dans les formats, pour attraper n'importe qui utilisant des modules intégrés qui ne montent qu'à la base 36
Jo King

Réponses:

13

MATL , 2 octets

Za

Essayez-le en ligne!
Tous les cas de test.

Pour le seigneur Za !

Sundar - Rétablir Monica
la source
....................... vous savez, j'ai vu que la Zaconversion de base a été effectuée, mais les documents sur matl.suever ne savaient pas clairement qu'elle acceptait les caractères de la base, donc je ne l'ai pas essayé. Déchirez-moi!
Giuseppe
@Giuseppe Haha, je m'en suis souvenu uniquement parce que cela semblait être une commande mûre pour (ab) une utilisation dans un ou deux hack intelligent. Ironique que ma première utilisation est une réponse intégrée directe. :)
sundar
1
Ma première pensée quand j'ai vu "Za" était "seigneur, Harry Dresden". +1.
Fund Monica's Lawsuit
8

R , 124 octets

function(n,s,t,T=L(t),N=(match(!n,!s)-1)%*%L(s)^(L(n):1-1))intToUtf8((!t)[N%/%T^rev(0:log(N,T))%%T+1])
"!"=utf8ToInt
L=nchar

Essayez-le en ligne!

Ugh, c'était un doozy. J'utilise les astuces de conversion de base typiques pour R, mais les manipulations de chaînes dans R sont toujours en désordre!

Giuseppe
la source
Malheureusement, cela ne fonctionnera pas avec n = "0" ... vous devriez ajouter 2 octets en faisant log(N+1,T)mais en provoquant parfois un zéro de tête, par exemple lorsque vous convertissez 31 de la base 10 en base 2 :(
digEmAll
Pour éviter le "problème zéro" sur le logarithme sans zéros non significatifs , je ne vois pas beaucoup d'autres solutions ... vous pourriez bien log(N+!N,T)sûr utiliser !avec le sens original
digEmAll
@digEmAll les commentaires de l'OP sont encore un peu flous, mais il semble que zéro ne soit pas pris en charge.
Giuseppe
Oh bien .. c'est bien alors :)
digEmAll
7

APL (Dyalog Unicode) , 22 octets

Infixe anonyme lambda. Prend InputFormatcomme argument de gauche et OutputFormatcomme argument de droite, et demande à Numberpartir de stdin. Suppose que ⎕IO( I ndex O rigin) est 0, ce qui est le cas par défaut sur de nombreux systèmes.

{⍵[(≢⍵)⊥⍣¯1⊢(≢⍺)⊥⍺⍳⎕]}

Essayez-le en ligne!

{} "Dfn"; est l'argument gauche, est l'argument droit
(mnémonique: extrémités gauche et droite de l'alphabet grec)

⍵[] Indexez le format de sortie comme suit:

   demande de saisie

  ⍺⍳ɩ ndices de ces caractères dans le format d'entrée

  ()⊥ Évaluer comme étant dans la base suivante:

   ≢⍺ la longueur du format d'entrée

   rendement qui (se sépare ¯1de (≢⍺))

  ()⊥⍣¯1 Convertir à la base suivante:

  ≢⍺ la longueur du format de sortie

Adam
la source
7

Japt, 5 octets

Retour au golf après une pause de 2 semaines

nV sW

Essayez-le


Explication

           :Implicit input of U=Number, V=InputFormat & W=OutputFormat
 nV        :Convert U from base V to decimal
    sW     :Convert to base W string
Hirsute
la source
7

C (gcc), 79 + 46 = 125 octets

char*O;l,n;g(n){n/l&&g(n/l);write(1,O+n%l,1);}

Cela doit être compilé avec le

-Df(s,i,o)=for(n=l=0;n=n*strlen(i)+index(i,s[l])-i,s[++l];);l=strlen(O=o);g(n)

drapeau. (Oui, c'est incroyablement sommaire, c'est pourquoi je garde mon ancienne réponse ci-dessous.) Cela définit une macro fqui renvoie la réponse à STDOUT.

Essayez-le en ligne!

C (gcc), 133 131 octets

char*O;l;g(n){n/l&&g(n/l);write(1,O+n%l,1);}f(s,i,o,n)char*s,*i,*o;{for(n=0,l=strlen(O=o);n=n*strlen(i)+index(i,*s)-i,*++s;);g(n);}

Essayez-le en ligne!

Ceci définit une fonction fqui renvoie la réponse à STDOUT.

char*O;           // declare variable to store output charset
l;                // will be set to length of O
g(n){             // helper function to print the result
  n/l&&g(n/l);    // recursively calls itself if there are more digits
  write(1,        // output to stdout...
   O+n%l,1);      // the byte at (n mod output base) in O
}
f(s,i,o,n)        // main function
char*s,*i,*o;{    // declare string inputs
for(n=0,          // initialize n to 0
l=strlen(O=o);    // assign output charset so we don't have to pass it to g
n=n*strlen(i)     // repeatedly multiply n by input base...
+index(i,*s)-i,   // ... add the index of the digit in input charset...
*++s;);           // and move to the next digit until there's none left
g(n);             // call the helper function on the resulting integer
}
Poignée de porte
la source
Vous pouvez enregistrer 2 octets en utilisant au putcharlieu de writeet changer la boucle de décodage légèrement: Essayez en ligne!
ErikF
Cette indexfonction m'a également sauvé un octet avec mon approche, je ne le savais pas;)
Felix Palmen
6

05AB1E , 5 octets

ÅβIÅв

Essayez-le en ligne!

Cela ne fonctionne pas dans la version héritée de 05AB1E. Il ne fonctionne que sur la nouvelle version, la réécriture Elixir.

Comment ça marche

ÅβIÅв - Programme complet.
Åβ - Conversion de la base personnalisée en décimal.
  I - Appuyez sur la troisième entrée.
   Åв - Convertir de la décimale en base personnalisée. 
M. Xcoder
la source
Vous déclarez que cela ne fonctionne que dans 05AB1E v2 (je ne sais pas si c'est le bon numéro de version ..), mais vous avez quand même fourni un lien TIO. La version Elixir est-elle déjà sur TIO?! : S Ou cela fonctionne pour la plupart des cas de test, mais il y a des cas limites où cela ne fonctionne que dans la nouvelle version?
Kevin Cruijssen
2
05AB1E v2 est désormais disponible sur TIO. 05AB1E (hérité) (recherchez-le dans la barre de tio) est le nom de l'ancien 05AB1E et 05AB1E est le nom du nouveau. Je sais que vous l'avez déjà vu dans le salon de discussion, mais je vais le laisser ici comme référence pour les autres utilisateurs.
M. Xcoder
4

Fusain , 5 octets

⍘⍘SSS

Essayez-le en ligne! Le lien est vers la version détaillée du code. Explication:

  S     Input the "number"
   S    Input the input format
 ⍘      Convert to number using that format
    S   Input the output format
⍘       Convert to string using that format
        Implicitly print

La BaseStringfonction convertit automatiquement entre nombre et chaîne selon le type du premier paramètre.

Neil
la source
3

Python 2 , 132 129 122 122 121 octets

lambda n,a,b:g(sum(len(a)**i*a.find(j)for i,j in enumerate(n[::-1])),b)
g=lambda n,c:c[n:n+1]or g(n/len(c),c)+c[n%len(c)]

Essayez-le en ligne!

Une fonction anonyme (merci, Erik the Outgolfer !) Qui convertit le nombre d'origine en un entier de base 10, puis transmet l'entier et la nouvelle chaîne de base à la fonction g (), qui convertit récursivement en la nouvelle base. Transmet maintenant la longueur du OutputFormat en tant que paramètre à g ().

Mise à jour de g () pour un nombre d'octets inférieur. (merci Dennis !)

Index () remplacé par find (). (merci, M. Xcoder !)

Explication non golfée:

def f(n, a, b):
    # reverse the string to that the least significant place is leftmost
    # Ex: 985724 -> 427589
    n = n[::-1]
    # get the value of each place, which is its index in the InputFormat, times the base to the power of the place
    # Ex: 427589, 9876543210 -> 5*10^0, 7*10^1, 2*10^2, 4*10^3, 1*10^4, 0*10^5 -> [5,70,200,4000,10000,0]
    n = [a.find(j)*len(a)**i for i,j in enumerate(n)]
    # add all of the values together to bet the value in base 10
    # Ex: (5 + 70 + 200 + 4000 + 10000 + 0) = 14275
    n = sum(n)

    # call the convert to base function
    return g(n, b)

def g(n, c):
    # string slice, which will return an empty string if n:n+1 is not in range
    # an empty string is falsey
    if c[n:n+1]:
        return c[n:n+1]
    else:
        # get current least significant digit
        rem = c[n%len(c)]
        # get the rest of the integer
        div = n/len(c)

        # get the converted string for the rest of the integer, append the calculated least significant digit
        return g(div,c)+rem
Triggernométrie
la source
1
Vous n'avez pas besoin f=, les fonctions anonymes sont autorisées par défaut.
Erik the Outgolfer
@Erik the Outgolfer Est-ce autorisé lorsque la fonction anonyme appelle une autre fonction, tho?
Triggernométrie
Tant que vous incluez les autres éléments dans votre bytecount, oui, vous êtes autorisé à définir des variables et à importer des modules.
Erik the Outgolfer
1
La fonction d'aide peut devenir g=lambda n,c:c[n:n+1]or g(n/len(c),c)+c[n%len(c)].
Dennis
1
Et le principal peut devenir lambda n,a,b:g(sum(len(a)**i*a.find(j)for i,j in enumerate(n[::-1])),b,len(b)).
M. Xcoder
2

Gelée , 11 octets

iⱮ’ḅL{ṃ⁵ṙ1¤

Essayez-le en ligne!

Ordre des arguments: InputFormat, Number, OutputFormat. Assurez-vous de citer les arguments avec un échappement approprié!

Erik le Outgolfer
la source
Hrm pas sûr que j'ai énoncé explicitement l'ordre des params ...
Martin Barker
@MartinBarker Les paramètres sont pris dans l'ordre 2, 1, 3 ici. Je ne vois pas d'exigence pour une commande spécifique dans le défi, et ce serait découragé.
Erik the Outgolfer
3
@MartinBarker Pro Astuce: Soyez flexible avec de telles choses. Je trouve que l'ordre des entrées est complètement hors de propos lors de la résolution d'une tâche, donc je suggère que vous
autorisiez
j'allais le laisser de toute façon essayer juste de le tester maintenant.
Martin Barker
2

Pyth, 21 octets

s@LeQjimx@Q1dhQl@Q1le

Suite de tests

Explication:
s@LeQjimx@Q1dhQl@Q1le  | Code
s@LeQjimx@Q1dhQl@Q1leQ |  with implicit variables
       m               | Map the function
        x   d          |   index of d in
         @Q1           |    the second string in the input
             hQ        |  over the first string in the input
      i                | Convert the resulting list to int from base
               l@Q1    |  length of the second string in the input
     j                 | Convert the int into a list in base
                   leQ |  length of the last string in the input
 @LeQ                  | Turn each number in the list into the character from the numbers index in the last string in the input
s                      | Concatenate the strings in to one string
                       | Implicit print
hakr14
la source
2

Haskell , 119 octets

n!f=init.((foldl((+).(l f*))0[i|c<-n,(i,d)<-zip[0..]f,d==c],0)#)
(0,d)#b=[b!!d]
(r,d)#b=r`divMod`l b#b++[b!!d]
l=length

Essayez-le en ligne!

ბიმო
la source
2

Perl 6 , 100 97 octets

{$^c.comb[(":"~$^b.chars~[$^a.comb>>.&{index $b,$_}].perl).EVAL.polymod($c.chars xx*)].join.flip}

Essayez-le en ligne!

Bloc de code anonyme qui prend 3 chaînes dans l'ordre, entrée, format d'entrée et format de sortie, puis retourne une chaîne

Explication:

{  # Anonymous code block
  $^c.comb[  # Split the output format into characters
           (":"~$^b.chars~[$^a.comb>>.&{index $b,$_}].perl) # The radix syntax in a string e.g ":3[1,2,3]"
           .EVAL  # Eval'ed to produce the base 10 version
           .polymod($c.chars xx*)  # Converted to a list in the output base (reversed)
          ] # Convert the list into indexes of the output format
           .join  # Join the characters to a string
           .flip  # And unreversed
}
Jo King
la source
2

VBA, 182 octets

Un sous-programme déclaré qui prend des entrées, ndans la langue yet les projette dans la langue z.

Sub f(n,y,z)
l=Len(n)
For i=-l To-1
v=v+(InStr(1,y,Mid(n,-i,1))-1)*Len(y)^(l+i)
Next
l=Len(z)
While v
v=v-1
d=v Mod l+1
v=v\l
If d<0Then v=v+1:d=d-l
o=Mid(z,d+1,1)&o
Wend
n=o
End Sub
Taylor Scott
la source
2

JavaScript (ES6), 90 86 octets

Prend l'entrée comme (input_format)(output_format)(number).

s=>d=>g=([c,...n],k=0)=>c?g(n,k*s.length+s.search(c)):k?g(n,k/(l=d.length)|0)+d[k%l]:n

Essayez-le en ligne!

Arnauld
la source
Désolé, ce n'est pas valide car vous changez le format d'entrée de la chaîne en un tableau qui n'est pas quelque chose qui peut être fait via une entrée CLI. et doit être programmé, vous devez diviser la chaîne en tableau pour que le premier paramètre soit valide.
Martin Barker
@MartinBarker De quelle règle parlez-vous? Mis à jour pour prendre 3 chaînes de toute façon.
Arnauld
Tous les 3 des paramètres d'entrée indiquent "chaîne" en C ++ une chaîne peut être directement lue et utilisée comme un tableau avec javascript, ce ne peut pas être.
Martin Barker
1

C (gcc) , 130 129 octets

v;c(r,i,s,t)char*r,*i,*t;{for(r[1]=v=0;*i;v=v*strlen(s)+index(s,*i++)-s);for(s=strlen(t),i=1;*r=t[v%s],v/=s;memmove(r+1,r,++i));}

Essayez-le en ligne!

-1 octet utilisant indexau lieu de strchr.

Il s'agit d'une approche itérative simple, réutilisant certaines variables (et donc abusant sizeof(int) == sizeof(char *)sur TIO) pour économiser des octets.

Contribution:

  • i numéro d'entrée
  • s caractères de base source
  • t personnages de base cibles

Sortie:

  • r numéro de résultat (pointeur vers un tampon)

Explication:

v;                                        // value of number
c(r,i,s,t)char*r,*i,*t;{
    for(r[1]=v=0;                         // initialize value and second
                                          // character of output to 0
        *i;                               // loop while not at the end of
                                          // input string
         v=v*strlen(s)+index(s,*i++)-s);  // multiply value with source base
                                          // and add the value of the current
                                          // digit (position in the base string)
    for(s=strlen(t),i=1;                  // initialize s to the length of the
                                          // target base string, length of
                                          // result to 1
        *r=t[v%s],v/=s;                   // add character for current digit
                                          // (value modulo target base) and
                                          // divide value by target base until
                                          // 0 is reached
        memmove(r+1,r,++i));              // move result string one place to
                                          // the right
}
Felix Palmen
la source
Suggérer à la bcopy(r,r+1,++i)place dememmove(r+1,r,++i)
plafondcat
1

Python 2 , 97 95 octets

Merci à Chas Brown pour -2 octets.

n,s,t=input()
k=0;w='';x=len(t)
for d in n:k=len(s)*k+s.find(d)
while k:w=t[k%x]+w;k/=x
print w

Essayez-le en ligne!

ovs
la source
1

Java 10, 131 octets

Un lambda prenant les paramètres dans l'ordre sous forme de chaînes et renvoyant une chaîne.

(i,f,o)->{int n=0,b=o.length();var r="";for(var c:i.split(r))n=n*f.length()+f.indexOf(c);for(;n>0;n/=b)r=o.charAt(n%b)+r;return r;}

Essayez-le en ligne

Non golfé

(i, f, o) -> {
    int n = 0, b = o.length();
    var r = "";
    for (var c : i.split(r))
        n = n * f.length() + f.indexOf(c);
    for (; n > 0; n /= b)
        r = o.charAt(n % b) + r;
    return r;
}
Jakob
la source