Conversor de Base de Número Personalizado

30

Os poderes desejados poderão converter rapidamente qualquer número que eles possuírem em sua própria base de números, usando o formato que desejar.

Entrada

Seu programa deve aceitar 3 parâmetros.

  1. Number: o número da string a ser convertida
  2. InputFormat: a string base em que o número está atualmente
  3. OutputFormat: a cadeia de base na qual o número deve ser convertido.

Saída

Seu programa deve converter a Numberbase de números antiga InputFormatpara a nova base de númerosOutputFormat

Exemplos

("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"

Adicional

O novo teste da base 77 não é necessário, se ele funcionar

  1. se você estiver em um idioma no qual você precisa primeiro converter para um número e estiver bloqueado no 32Bit, poderá ignorá-lo.
  2. como é um teste adicional.

Todos os exemplos foram gerados pelo PHP 7.2 com a extensão bcmath usando o código a seguir (vars mins mas código formatado). provavelmente haverá uma maneira mais curta. Foi exatamente dessa maneira que eu criei para o sistema com o qual eu precisava fazer isso. Seria bom ver se alguém poderia ter uma versão mais curta.

PHP 7.2 (bcmath - extensão) 614 bytes

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

Experimente Online

Pontuação

Isso é código de golfe; o código mais curto vence. Aplicam-se brechas padrão.

Martin Barker
fonte
5
@WindmillCookies Por qualquer caractere que esteja nas cadeias de caracteres de formato.
Adám 16/08/19
6
Boa primeira pergunta! :-)
Giuseppe
2
Intimamente relacionado .
AdmBorkBork
2
Pode valer a pena adicionar um caso de teste para uma base "única" - por exemplo ["zX", "tXdsyqzSDRP02", "brFNC02bc"] => "cb". (ou seja lá o que realmente deve ser, se isso é incorreto)
Ação do Fundo Monica
2
Eu sugeriria um caso de teste com mais de 36 caracteres nos formatos, para capturar qualquer pessoa usando built-ins que só vão até a base 36
Jo King

Respostas:

13

MATL , 2 bytes

Za

Experimente online!
Todos os casos de teste.

Para o senhor Za !

sundar - Restabelecer Monica
fonte
....................... você sabe, vi que a Zaconversão base, mas os documentos em matl.suever não estavam claros de que aceitavam os caracteres da base, então eu não tentei. RIP me!
Giuseppe
@ Giuseppe Haha, eu me lembrei apenas porque parecia um comando pronto para (ab) usar em algum truque inteligente ou dois. Irônico que meu primeiro uso seja uma resposta direta. :)
sundar - Restabelece Monica 16/08
1
Meu primeiro pensamento quando vi "Za" foi "senhor, Harry Dresden". +1.
Fund Monica's Lawsuit
8

R , 124 bytes

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

Experimente online!

Ugh, isso foi doozy. Eu uso os truques típicos de conversão de base para R, mas as manipulações de string em R ainda são confusas!

Giuseppe
fonte
Infelizmente isso não funcionará com n = "0" ... você deve adicionar 2 bytes fazendo log(N+1,T) , mas causando um zero à esquerda, por vezes, por exemplo, quando você converter 31 da base 10 a base 2 :(
digEmAll
Para evitar o "problema zero" no logaritmo sem zeros à esquerda, não vejo muitas outras soluções ... é log(N+!N,T)claro que você poderia usar! com o significado original
digEmAll
Todos os comentários do OP ainda são um pouco incertos, mas parece que o zero não precisa ser suportado.
Giuseppe
Oh bem ... tudo bem então :) :)
digEmAll
7

APL (Dyalog Unicode) , 22 bytes

Infix anônimo lambda. Toma InputFormatcomo argumento à esquerda e OutputFormatcomo argumento à direita e solicita a Numberpartir de stdin. Assume ⎕IO( I ndex O rigin) como sendo 0, o padrão em muitos sistemas.

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

Experimente online!

{... } "dfn"; é argumento à esquerda, é argumento à direita
(mnemônico: extremidades esquerda e direita do alfabeto grego)

⍵[...]  Indexe o formato de saída com o seguinte:

   solicitação de entrada

  ⍺⍳ɩ índices desses caracteres no formato de entrada

  (...)⊥  Avalie como estando na seguinte base:

   ≢⍺ o comprimento do formato de entrada

   rendimento que (separa ¯1de (≢⍺))

  ()⊥⍣¯1 Converta para a seguinte base:

  ≢⍺ o comprimento do formato de saída

Adão
fonte
7

Japt, 5 bytes

Regressando ao golfe após um intervalo de 2 semanas

nV sW

Tente


Explicação

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

C (gcc), 79 + 46 = 125 bytes

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

Isso deve ser compilado com o

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

bandeira. (Sim, isso é incrivelmente superficial, e é por isso que estou mantendo minha resposta antiga abaixo.) Isso define uma macro fque gera a resposta para STDOUT.

Experimente online!

C (gcc), 133 131 bytes

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

Experimente online!

Isso define uma função fque envia a resposta para 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
}
Maçaneta da porta
fonte
Você pode economizar 2 bytes usando em putcharvez de writee alterando um pouco o loop de decodificação: Experimente online!
ErikF 17/08/19
Esta indexfunção salva-me um byte, bem como com a minha abordagem, não sabia sobre isso;)
Felix Palmen
6

05AB1E , 5 bytes

ÅβIÅв

Experimente online!

Isso não funciona na versão herdada do 05AB1E. Funciona apenas na nova versão, reescrita do Elixir.

Como funciona

ÅβIÅв - Programa completo.
Åβ - Converte da base personalizada para decimal.
  I - Pressione a terceira entrada.
   Åв - Converte de decimal para base personalizada. 
Mr. Xcoder
fonte
Você afirma que só funciona no 05AB1E v2 (não tem certeza se esse é o número da versão correto ..), mas ainda forneceu um link TIO. A versão do Elixir já está no TIO ?! : S Ou funciona para a maioria dos casos de teste, mas há alguns casos extremos em que funciona apenas na nova versão?
Kevin Cruijssen 17/08/1918
2
05AB1E v2 já está disponível no TIO. 05AB1E (legado) (procure na barra de tio) é o nome do antigo 05AB1E e 05AB1E é o nome do novo. Eu sei que você já viu isso na sala de bate-papo, no entanto, mas vou deixar aqui como uma referência para outros usuários.
Xcoder
5

MATL , 5 bytes

sundar encontrou o real embutido para fazer isso! Voto acima dessa resposta em vez da minha idiota :-(

ZAwYA

Experimente online!

          % implicit input N, the number, and S, the digits of the Source base
ZA        % base2dec, convert string N using S as digits into a base 10 integer
w         % swap stack elements, with implicit input T, the digits of the Target base
YA        % dec2base, reverse the ZA operation with digits coming from T instead.
Giuseppe
fonte
4

Carvão , 5 bytes

⍘⍘SSS

Experimente online! Link é a versão detalhada do código. Explicação:

  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

A BaseStringfunção converte automaticamente entre número e string, dependendo do tipo do primeiro parâmetro.

Neil
fonte
3

Python 2 , 132 129 122 121 bytes

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

Experimente online!

Uma função anônima (obrigado, Erik o Outgolfer !), Que converte o número original em um número inteiro de base 10, depois passa o número inteiro e a nova string de base para a função g (), que converte recursivamente para a nova base. Agora passa o comprimento do OutputFormat como um parâmetro para g ().

Atualizado g () para um número de bytes mais baixo. (obrigado, Dennis !)

Índice substituído () por find (). (obrigado, Sr. Xcoder !)

Explicação Ungolfed:

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
Triggernometria
fonte
1
Você não precisa f=, funções anônimas são permitidas por padrão.
Erik the Outgolfer
@Erik the Outgolfer Isso é permitido quando a função anônima chama outra função, tho?
Triggernometry
Desde que você inclua os outros itens no seu número de bytes, sim, você poderá definir variáveis ​​e importar módulos.
Erik the Outgolfer
1
A função auxiliar pode se tornar g=lambda n,c:c[n:n+1]or g(n/len(c),c)+c[n%len(c)].
Dennis
1
E o principal pode se tornar lambda n,a,b:g(sum(len(a)**i*a.find(j)for i,j in enumerate(n[::-1])),b,len(b)).
Mr. Xcoder
2

Gelatina , 11 bytes

iⱮ’ḅL{ṃ⁵ṙ1¤

Experimente online!

Ordem dos argumentos: InputFormat, Number, OutputFormat. Certifique-se de citar os argumentos com escape apropriado!

Erik, o Outgolfer
fonte
Hrm não sei se dizia explicitamente a ordem dos parâmetros ...
Martin Barker
@MartinBarker Os parâmetros são obtidos na ordem 2, 1, 3 aqui. Não vejo um requisito para uma ordem específica no desafio, e isso seria desencorajado.
Erik the Outgolfer
3
@MartinBarker Pro Dica: Seja flexível com essas coisas. Acho que a ordem das entradas para ser completamente irrelevante quando resolver uma tarefa, então eu sugiro que você permitir que qualquer ordenação escolhido arbitrariamente dos parâmetros
Mr. Xcoder
eu ia deixar assim mesmo, tentando testá-lo agora.
Martin Barker
2

Pitão, 21 bytes

s@LeQjimx@Q1dhQl@Q1le

Suíte de teste

Explicação:
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
fonte
2

Haskell , 119 bytes

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

Experimente online!

ბიმო
fonte
2

Perl 6 , 100 97 bytes

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

Experimente online!

Bloco de código anônimo que utiliza três cadeias de caracteres em ordem, entrada, formato de entrada e formato de saída e retorna uma string

Explicação:

{  # 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
}
Brincadeira
fonte
2

VBA, 182 bytes

Uma sub-rotina declarada que recebe entrada,, nno idioma ye os projeta no idioma 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
fonte
2

JavaScript (ES6), 90 86 bytes

Toma entrada como (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

Experimente online!

Arnauld
fonte
Desculpe, isso não é válido, pois você altera o formato de entrada da sequência para uma matriz que não é algo que pode ser feito por meio de uma entrada da CLI. e precisa ser programado, você precisa dividir a string na matriz para que o primeiro parâmetro seja válido.
Martin Barker
@MartinBarker A qual regra você está se referindo? Atualizado para levar três seqüências de qualquer maneira.
Arnauld
Todos os três parâmetros de entrada dizem que "string", como C ++, uma string pode ser lida diretamente e usada como uma matriz com javascript.
Martin Barker
1

C (gcc) , 130 129 bytes

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

Experimente online!

-1 byte usando em indexvez de strchr.

Essa é uma abordagem iterativa simples, reutilizando algumas variáveis ​​(e, dessa forma, abusando sizeof(int) == sizeof(char *) do TIO) para salvar bytes.

Entrada:

  • i número de entrada
  • s caracteres base de origem
  • t caracteres base de destino

Saída:

  • r número do resultado (ponteiro para um buffer)

Explicação:

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
fonte
Sugerir em bcopy(r,r+1,++i)vez dememmove(r+1,r,++i)
tetocat 21/08
1

Python 2 , 97 95 bytes

Agradecimentos a Chas Brown por -2 bytes.

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

Experimente online!

ovs
fonte
1

Java 10, 131 bytes

Um lambda pegando os parâmetros em ordem como strings e retornando uma string.

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

Experimente Online

Ungolfed

(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
fonte