Conversión de base mixta

12

Antecedentes

La mayoría de las personas aquí deben estar familiarizadas con varios sistemas base: decimal, binario, hexadecimal, octal. Por ejemplo, en el sistema hexadecimal, el número 12345 16 representaría

1*16^4 + 2*16^3 + 3*16^2 + 4*16^1 + 5*16^0

Tenga en cuenta que generalmente no esperamos que la base (aquí 16) cambie de un dígito a otro.

Una generalización de estos sistemas posicionales habituales le permite utilizar una base numérica diferente para cada dígito. Por ejemplo, si estuviéramos alternando entre el sistema decimal y binario (comenzando con la base 10 en el dígito menos significativo), el número 190315 [2,10] representaría

1*10*2*10*2*10 + 9*2*10*2*10 + 0*10*2*10 + 3*2*10 + 1*10 + 5 = 7675

Denotamos esta base como [2,10]. La base más a la derecha corresponde al dígito menos significativo. Luego pasas por las bases (a la izquierda) a medida que avanzas por los dígitos (a la izquierda), envolviéndote si hay más dígitos que bases.

Para leer más, ver Wikipedia .

El reto

Escriba un programa o función que, dada una lista de dígitos, Duna base de entrada Iy una base de salida O, convierta el entero representado por Dde base Ia base O. Puede recibir información a través de STDIN, ARGV o argumento de función y devolver el resultado o imprimirlo en STDOUT.

Puedes asumir:

  • que los números en Iy Oson todos mayores que 1.
  • los Iy Ono están vacíos.
  • que el número de entrada es válido en la base dada (es decir, ningún dígito mayor que su base).

Dpodría estar vacío (que representa 0) o podría tener ceros a la izquierda. Su salida no debe contener ceros a la izquierda. En particular, un resultado que representa 0debe ser devuelto como una lista vacía.

No debe utilizar ninguna función de conversión de base integrada o de terceros.

Este es el código de golf, gana la respuesta más corta (en bytes).

Ejemplos

D               I                  O        Result
[1,0,0]         [10]               [2]      [1,1,0,0,1,0,0]
[1,0,0]         [2]                [10]     [4]
[1,9,0,3,1,5]   [2,10]             [10]     [7,6,7,5]
[1,9,0,3,1,5]   [2,10]             [4,3,2]  [2,0,1,1,0,1,3,0,1]
[52,0,0,0,0]    [100,7,24,60,60]   [10]     [3,1,4,4,9,6,0,0]
[0,2,10]        [2,4,8,16]         [42]     [1,0]
[]              [123,456]          [13]     []
[0,0]           [123,456]          [13]     []
Martin Ender
fuente
¿Puedo requerir una lista infinita como descripción base, o tengo que infinitarla yo mismo?
John Dvorak
@ JanDvorak ¿Quiere decir si puede esperar que las listas base ya tengan un número suficiente de repeticiones para cubrir todos los dígitos? No, tendrás que envolverlo o repetirlo tú mismo.
Martin Ender
Supongo que obtener una lista vacía como base es UB, pero ¿podemos suponer que la lista de dígitos no está vacía? Además, ¿cuál es la política sobre ceros al final?
John Dvorak
Es decir, no me importa una lista vacía en la entrada, pero me gustaría producir []si la entrada es[0]
John Dvorak
¿Puedo solicitar y generar una lista de dígitos en el orden inverso (LSD primero)?
John Dvorak

Respuestas:

6

CJam, 45

q~_,@m>0@{@(:T+@T*@+}/\;La{\)_@+@@md@@j@+}jp;

Finalmente encontré un buen uso de j.

Cómo funciona

Long ArrayList Block jejecuta el bloque que toma un número entero como parámetro y Long jllamará a este bloque de forma recursiva en el bloque. También almacenará los valores devueltos por el bloque en una matriz interna, que se inicializa con el parámetro de matriz. No ejecutará el bloque si la entrada ya está en la matriz, y en su lugar se devuelve el valor en la matriz.

Entonces, si lo inicializo con una matriz de una matriz vacía, la matriz vacía se devolverá para la entrada 0, y el bloque se ejecutará para cualquier otra entrada.

q~_,@m>0@{@(:T+@T*@+}/\;     " See below. Stack: O decoded-D ";
La                           " Initialized the value with input 0 as empty list. ";
{
  \)_@+@@md@@                " See below. Stack: remainder O quotient ";
  j                          " Call this block recursively except when the same quotient has
                               appeared before, which is impossible except the 0.
                               Stack: remainder O returned_list ";
  @+                         " Append the remainder to the list. ";
}j
p;                           " Format and output, and discard O. ";

CJam, 49 48

q~_,@m>0@{@(:T+@T*@+}/\;{\)_@+@@md@@}h;;_{}?]W%`

La entrada debe ser O I D.

Ejemplos:

$ while read; do <<<$REPLY ./cjam-0.6.2.jar <(echo 'q~_,@m>0@{@(:T+@T*@+}/\;{\)_@+@@md@@}h;;_{}?]W%`');echo; done
[2] [10] [1 0 0]
[10] [2] [1 0 0]
[10] [2 10] [1 9 0 3 1 5]
[4 3 2] [2 10] [1 9 0 3 1 5]
[10] [100 7 24 60 60] [52 0 0 0 0]
[42] [2 4 8 16] [0 2 10]
[13] [123 456] []
[13] [123 456] [0 0]
[1 1 0 0 1 0 0]
[4]
[7 6 7 5]
[2 0 1 1 0 1 3 0 1]
[3 1 4 4 9 6 0 0]
[1 0]
""
""

Cómo funciona

q~           “ Read the input and evaluate. ";
_,@m>        " Rotate I to the right by the length of D. ";
0@{          " For each item in D, with the result initialized to 0: ";
  @(:T+      " Rotate I to the left, and set the original first item to T. ";
  @T*@+      " Calculate result * T + current. ";
}/
\;           " Discard I. ";
{            " Do: ";
  \)_@+      " Rotate O to the right, and get a copy of the original last item. ";
  @@md       " Calculate divmod. ";
  @@         " Move O and the quotient to the top of the stack. ";
}h           " ...while the quotient is not 0. ";
;;           " Discard O and the last 0. ";
_{}?         " If the last item is still 0, discard it. ";
]W%          " Collect into an array and reverse. ";
`            " Turn the array into its string representation. ";
jimmy23013
fuente
Tengo que dejar de usar la rotación de matriz solo porque CJam lo tiene ... Ese _{}?truco es realmente bueno.
Dennis
@sudo {}e|es lo mismo.
jimmy23013
¿Te importaría agregar una explicación para la versión usando j? :)
Martin Ender
@ MartinBüttner Hecho.
jimmy23013
3

CJam, 62 61 59 57 bytes

q~Wf%~UX@{1$*@+\@(+_W=@*@\}/;\;{\(+_W=@\md@@}h;;]W%_0=!>p

Lee las matrices de entrada a partir [O I D]de STDIN. Pruébalo en línea.

Cómo funciona

q~         " Read from STDIN and evaluate the input. Result: [O I D]                      ";
Wf%~       " Reverse each of the three arrays and dump them on the stack.                 ";
UX@        " Push U (0) and X (1); rotate D on top of both.                               ";
{          " For each N in D:                                                             ";
  1$*      "   N *= X                                                                     ";
  @+       "   U += N                                                                     ";
  \@(+     "   I := I[1:] + I[:1]                                                         ";
  _W=@*    "   X *= I[-1]                                                                 ";
  @\       "   ( U I X ) ↦ ( I U X )                                                      ";
}/         "                                                                              ";
;\;        " Discard I and X.                                                             ";
{          " R := []; Do:                                                                 ";
  \(+      "   O := O[1:] + O[:1]                                                         ";
  _W=@\md  "   R += [U / O[-1]], U %= O[-1]                                               ";
  @@       "   ( O U R[-1] ) ↦ ( R[-1] O U )                                              ";
}/         " While U                                                                      ";
;;]        " Discard U and O.                                                             ";
W%         " Reverse R.                                                                   ";
_0=!>      " Execute R := R[!R[0]:] to remove a potential leading zero.                   ";
p          " Print a string presentation of R.                                            ";

Casos de prueba

$ cjam mixed-base.cjam <<< '[ [2]     [10]             [1 0 0]       ]'
[1 1 0 0 1 0 0]
$ cjam mixed-base.cjam <<< '[ [10]    [2]              [1 0 0]       ]'
[4]
$ cjam mixed-base.cjam <<< '[ [10]    [2 10]           [1 9 0 3 1 5] ]'
[7 6 7 5]
$ cjam mixed-base.cjam <<< '[ [4 3 2] [2 10]           [1 9 0 3 1 5] ]'
[2 0 1 1 0 1 3 0 1]
$ cjam mixed-base.cjam <<< '[ [10]    [100 7 24 60 60] [52 0 0 0 0]  ]'
[3 1 4 4 9 6 0 0]
$ cjam mixed-base.cjam <<< '[ [42]    [2 4 8 16]       [0 2 10]      ]'
[1 0]
$ cjam mixed-base.cjam <<< '[ [13]    [123 456]        []            ]'
""
$ cjam mixed-base.cjam <<< '[ [13]    [123 456]        [0 0]         ]'
""

Tenga en cuenta que las cadenas vacías y las matrices vacías son indistinguibles para CJam, por lo que []pimprime "".

Dennis
fuente
44
OMG nunca ha visto un programa CJam de 62 bytes: D
Optimizer
@Optimizer Esta es probablemente mi presentación más larga de CJam.
Esolanging Fruit
@ Dennis Eso no fue código golf , ¿verdad?
Esolanging Fruit
@ Challenger5 No lo fue, pero dudo que una versión de golf sea más corta que 200 bytes.
Dennis
2

Python 2 - 318

from operator import *
d,i,o=input()
c=len
def p(l):return reduce(mul,l,1)
n=sum(x[1]*p((i[-x[0]%c(i)-1:]+x[0]/c(i)*i)[1:]) for x in enumerate(d[::-1]))
r=[]
j=1
t=[]
k=c(o)
while p(t)*max(o)<=n:t=(o[-j%k-1:]+j/k*o)[1:];j+=1
while j:j-=1;t=(o[-j%k-1:]+j/k*o)[1:];r+=[n/p(t)];n%=p(t)
print (r if r[0] else [])

Cambié el orden de los argumentos por accidente, así que tuve que revertirlos. Trabajaré en el slice-fu para que las listas funcionen en la otra dirección más tarde, ya desperdicié toda mi pausa para el almuerzo: p

Fijo

FryAmTheEggman
fuente
No digas "desperdicio";)
Martin Ender
Debería poder jugar golf hasta 286 bytes: repl.it/JbIk
Zacharý
@ Zacharý Creo que este fue mi primer golf, ¡estoy seguro de que puede ser mucho más corto que eso! La respuesta de Feersum lo demuestra bastante bien, creo. Si lo desea, puede editar esta respuesta, pero me temo que no estoy particularmente motivado para mejorarla.
FryAmTheEggman
2

APL, 78

{1↓(⊃1⌷⍺)({t←⍺[(⍴⍺)|⍴⍵]
(⌊0⌷⍵÷t)(t|0⌷⍵),1↓⍵}⍣{0=0⌷⍵}),+/(0,⍵)×⌽×\1,(⍴⍵)⍴⌽⊃0⌷⍺}

Ejemplos:

f←{1↓(⊃1⌷⍺)({t←⍺[(⍴⍺)|⍴⍵]
  (⌊0⌷⍵÷t)(t|0⌷⍵),1↓⍵}⍣{0=0⌷⍵}),+/(0,⍵)×⌽×\1,(⍴⍵)⍴⌽⊃0⌷⍺}
(,10)(,2) f 1 0 0
1 1 0 0 1 0 0
(,2)(,10) f 1 0 0
4
(2 10)(,10) f 1 9 0 3 1 5
7 6 7 5
(2 10)(4 3 2) f 1 9 0 3 1 5
2 0 1 1 0 1 3 0 1
(100 7 24 60 60)(,10) f 52 0 0 0 0
3 1 4 4 9 6 0 0
(2 4 8 16)(,42) f 0 2 10
1 0
(123 456)(,13) f ⍬

⍴(123 456)(,13) f ⍬
0
(123 456)(,13) f 0 0

⍴(123 456)(,13) f 0 0
0
jimmy23013
fuente
Solo para educación general, con elementos integrados: {{⍵↓⍨1⍳⍨×⍵}(99⍴⎕)⊤⍵⊥⍨⎕⍴⍨⍴⍵}toma D como argumento correcto, luego pregunta por I y O.
Adám
2

Python 2 - 122

Muy sencillo, no logró encontrar ningún truco especial de golf en este caso.

def f(D,I,O):
 n,i,l=0,-len(D),[]
 for d in D:n=n*I[i%len(I)]+d;i+=1
 while n:i-=1;b=O[i%len(O)];l=[n%b]+l;n/=b
 return l

Sin golf:

def f(D,I,O):
    n = 0
    for i in range(len(D)):
        dn = len(D) - i
        n = n * I[-dn % len(I)] + D[i]
    l = []
    i = 0
    while n:
        i -= 1
        b = O[i%len(O)]
        l = [n%b] + l
        n /= b
    return l

Editar: versión del programa de 116 bytes gracias a FryAmTheEggman

D,I,O=input()
n,i,l=0,-len(D),[]
for d in D:n=n*I[i%len(I)]+d;i+=1
while n:i-=1;b=O[i%len(O)];l=[n%b]+l;n/=b
print l

Esta versión acepta entradas separadas por comas, p. Ej. [1,9,0,3,1,5], [2,10], [10]

Feersum
fuente
@FryAmTheEggman No estoy seguro de cómo podría aceptar entradas con comillas, pero separar las matrices con comas funciona.
feersum
1

k2 - 83 74 char

Función tomando un argumento. Esto era mucho más adecuado para K que para J, por eso no estoy usando J. Simplemente sería una carga de basura de boxeo / unboxing, y nadie quiere eso. Esto está en el dialecto k2 (puede requerir alguna adaptación para trabajar en la implementación de código abierto Kona), pero cambiaré esto a k4 si puedo jugar golf más corto allí.

{:[#x@:|&~&\~x;|*{x 1}.[{_(x,y!*z;y%*z;1!z)}]/(();+/x*1*\(1-#x)#y;|z);()]}

Notaré que tomo una posición de selectividad aquí y digo que las listas de un elemento deben ingresarse como tales. ,2es una lista de un elemento, ese elemento es el escalar 2. A menudo, los escalares y las listas de 1 ítem son intercambiables, pero hay una lógica en este golf que se basa en la suposición de argumentos de lista.

Para explicar el golf, lo dividiré en dos partes. Fes el golf, Les el bucle principal que calcula la salida. El mecanismo exacto del bucle es que Lse aplica a sus argumentos repetidamente hasta que el segundo argumento sea cero, luego se devuelve ese resultado. (Esta es la .[L]/parte)

L: {_(x,y!*z;y%*z;1!z)}
F: {:[#x@:|&~&\~x;|*{x 1}.[L]/(();+/x*1*\(1-#x)#y;|z);()]}

Por explosión:

{_(x,y!*z;y%*z;1!z)}  /function, args x y z
  (      ;    ;   )   / update each arg as follows:
               1!z    /  new z: rotate z left
            *z        /  head of z (current base digit)
          y%          /  y divided by that
 _                    /  new y: floor of that
     y!*z             /  y modulo head of z
   x,                 /  new x: append that to old x

{:[#x@:|&~&\~x;|*{x 1}.[L]/(();+/x*1*\(1-#x)#y;|z);()]}  /function, args x y z
            ~x                                           /find the 0s in x
          &\                                             /find leading zeros
        &~                                               /indices of digits that aren't
    x@ |                                                 /those items from x, reverse order
    x :                                                  /assign to x
 :[#          ;                                      ]   /if length is 0:
                                                   ()    / return empty list
                                                  ;      /else:
                      .[L]/                              / loop L repeatedly
                 {x 1}                                   / until y = 0
                           (  ;               ;  )       / starting with args:
                            ()                           /  Lx: empty list
                                       1-#x              /  number of input digits, minus 1
                                      (    )#y           /  cyclically extend base leftward
                                   1*\                   /  running product, start at 1
                                 x*                      /  multiply digits by these
                               +/                        /  Ly: sum of the above
                                               |z        /  Lz: out base, reverse order
               |*                                        / first elem of result, reversed

En acción:

  {:[#x@:|&~&\~x;|*{x 1}.[{_(x,y!*z;y%*z;1!z)}]/(();+/x*1*\(1-#x)#y;|z);()]}[1 0 0; ,10; ,2]
1 1 0 0 1 0 0
  f:{:[#x@:|&~&\~x;|*{x 1}.[{_(x,y!*z;y%*z;1!z)}]/(();+/x*1*\(1-#x)#y;|z);()]}
  f[1 0 0; ,2; ,10]
,4
  f .' ((1 9 0 3 1 5; 2 10;           ,10)  /f apply each
>       (1 9 0 3 1 5; 2 10;           4 3 2)
>       (52 0 0 0 0;  100 7 24 60 60; ,10)
>       (0 2 10;      2 4 8 16;       ,42)
>       (();          123 456;        ,13)
>       (0 0;         123 456;        ,13))
(7 6 7 5
 2 0 1 1 0 1 3 0 1
 3 1 4 4 9 6 0 0
 1 0
 ()
 ())
Algoritmo de tiburón
fuente
0

Perl 6 , 67 bytes

{[R,] [+]([R,](@^a)Z*1,|[\*] |[R,](@^b)xx*).polymod: |[R,](@^c)xx*}

Intentalo

Expandido:

{  # bare block lambda with placeholder parameters @a,@b,@c

  [R,]    # reduce the following using reverse meta op 「R」 combined with 「,」 op
          # (shorter than 「reverse」)

    [+](  # sum

        [R,](@^a) # reverse of first argument

      Z[*]        # zipped using &infix:<*> with the following

        1,
        |                    # slip the following in (flattens)
          [\*]               # triangle reduce

            |[R,](@^b) xx*   # reverse of second argument repeated infinitely
    )

    .polymod: |[R,](@^c) xx* # moduli the reverse of third argument repeated
}

En caso de que no esté seguro de lo que hace la reducción de triángulo:

[\*] 1,2,3,4,5
# 1, 1*2, 1*2*3, 1*2*3*4, 1*2*3*4*5
# 1,   2,     6,      24,       120

Si pudiera tomar las entradas invertidas, y dar salida a la inversa, serían 47 bytes.

{[+](@^a Z*1,|[\*] |@^b xx*).polymod: |@^c xx*}

Intentalo

Brad Gilbert b2gills
fuente