Conversione base mista


12

sfondo

La maggior parte delle persone qui dovrebbe avere familiarità con diversi sistemi di base: decimale, binario, esadecimale, ottale. Ad esempio nel sistema esadecimale, il numero 12345 16 rappresenterebbe

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

Nota che di solito non ci aspettiamo che la base (qui, 16) cambi da cifra a cifra.

Una generalizzazione di questi soliti sistemi posizionali consente di utilizzare una base numerica diversa per ogni cifra. Ad esempio, se stessimo alternando il sistema decimale e binario (a partire dalla base 10 nella cifra meno significativa), il numero 190315 [2,10] rappresenterebbe

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

Indichiamo questa base come [2,10]. La base più a destra corrisponde alla cifra meno significativa. Quindi attraversi le basi (a sinistra) mentre attraversi le cifre (a sinistra), avvolgendoti se ci sono più cifre delle basi.

Per ulteriori letture, vedi Wikipedia .

La sfida

Scrivi un programma o una funzione che, dato un elenco di cifre, Duna base di input Ie una base di output O, converte l'intero rappresentato da Dbase Ia base O. È possibile accettare input tramite STDIN, ARGV o argomento della funzione e restituire il risultato o stamparlo su STDOUT.

Puoi presumere:

  • che i numeri in Ie Osono tutti maggiori di 1.
  • i Ie Osono non vuoti.
  • che il numero di input sia valido nella base data (ovvero nessuna cifra più grande della sua base).

Dpotrebbe essere vuoto (rappresentante 0) o avere zero iniziali. L'output non deve contenere zero iniziali. In particolare, un risultato che rappresenta 0deve essere restituito come un elenco vuoto.

Non è necessario utilizzare alcuna funzione di conversione di base incorporata o di terze parti.

Questo è il codice golf, vince la risposta più breve (in byte).

Esempi

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

Posso richiedere un elenco infinito come descrizione di base o devo infinitarlo da solo?
John Dvorak,

@JanDvorak Vuoi dire se puoi aspettarti che gli elenchi di base abbiano già un numero sufficiente di ripetizioni per coprire tutte le cifre? No, dovrai fare il giro o ripetere te stesso.
Martin Ender,

Presumo che ottenere un elenco vuoto come base sia UB, ma possiamo supporre che l'elenco di cifre non sia vuoto? Inoltre, qual è la politica sugli zero finali?
John Dvorak,

Vale a dire, non mi dispiace un elenco vuoto sull'input, ma vorrei produrre []se l'input è[0]
John Dvorak,

Posso richiedere e produrre un elenco di cifre nell'ordine inverso (prima LSD)?
John Dvorak,

Risposte:


6

CJam, 45

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

Finalmente ho trovato un buon uso di j.

Come funziona

Long ArrayList Block jesegue il blocco che accetta un numero intero come parametro e Long jchiamerà questo blocco in modo ricorsivo nel blocco. Memorizzerà inoltre i valori restituiti dal blocco in un array interno, che viene inizializzato dal parametro array. Non eseguirà il blocco se l'input è già nella matrice e viene invece restituito il valore nella matrice.

Quindi, se lo inizializzo con un array di un array vuoto, l'array vuoto verrà restituito per l'ingresso 0 e il blocco verrà eseguito per qualsiasi altro input.

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%`

L'input dovrebbe essere O I D.

Esempi:

$ 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]
""
""

Come funziona

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. ";

Devo smettere di usare la rotazione dell'array solo perché ce l'ha CJam ... Questo _{}?trucco è davvero pulito.
Dennis,

@sudo {}e|è lo stesso.
jimmy23013,

Ti dispiacerebbe aggiungere una spiegazione per la versione usando j? :)
Martin Ender,

@ MartinBüttner Fatto.
jimmy23013,

3

CJam, 62 61 59 57 byte

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

Legge le matrici di input come [O I D]da STDIN. Provalo online.

Come funziona

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.                                            ";

Casi test

$ 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]         ]'
""

Nota che stringhe vuote e array vuoti sono indistinguibili da CJam, quindi le []pstampe "".


4
OMG Non ho mai visto un programma CJam di 62 byte: D
Ottimizzatore,

@Optimizer Questa è probabilmente la mia presentazione CJam più lunga.
Esolanging Fruit


@Dennis Quello non era il golf del codice , vero?
Esolanging Fruit

@ Challenger5 Non lo era, ma dubito che una versione giocata a golf sarebbe inferiore a 200 byte.
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 [])

Ho sbagliato per errore l'ordine degli argomenti, quindi ho dovuto invertirli. Lavorerò sullo slice-fu per far funzionare le liste nella direzione successiva, ho già perso tutta la mia pausa pranzo: p

Fisso


Non dire "spreco";)
Martin Ender,

Dovresti essere in grado di golf fino a 286 byte: repl.it/JbIk
Zacharý

@ Zacharý Questo è stato il mio primo golf, credo, sono sicuro che può essere molto più corto di così! La risposta di Feersum lo dimostra abbastanza bene, penso. Se vuoi puoi modificare questa risposta, ma temo di non essere particolarmente motivato a migliorarla.
FryAmTheEggman,

2

APL, 78

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

Esempi:

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

Solo per l'educazione generale - con incorporati: {{⍵↓⍨1⍳⍨×⍵}(99⍴⎕)⊤⍵⊥⍨⎕⍴⍨⍴⍵}prende D come argomento giusto, quindi chiede io e O.
Adám

2

Python 2 - 122

Molto semplice, non sono riuscito a trovare particolari trucchi da golf su questo.

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

Ungolfed:

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

Modifica: versione del programma a 116 byte grazie 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

Questa versione accetta input separati da virgola, ad es [1,9,0,3,1,5], [2,10], [10]


@FryAmTheEggman Non sono sicuro di come accettare input con virgolette ma separare le matrici con virgole funziona.
feersum,

1

k2 - 83 74 caratteri

Funzione che accetta un argomento. Questo era molto più adatto a K di J, motivo per cui non sto usando J. Sarebbe solo un sacco di immondizia boxe / unboxing, e nessuno lo vuole. Questo è nel dialetto k2 (potrebbe richiedere qualche adattamento per funzionare nell'implementazione open source Kona), ma lo cambierò in k4 se posso giocarci più in basso.

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

Noterò che prendo posizione per la delicatezza qui e dico che un elenco di voci deve essere inserito come tale. ,2è un elenco di un elemento, che è lo scalare 2. Spesso gli scalari e gli elenchi di 1 elemento sono intercambiabili, ma in questo golf c'è la logica che si basa sul presupposto degli argomenti dell'elenco.

Per spiegare il golf, lo spezzerò in due parti. Fè il golf, Lè il ciclo principale che calcola l'output. L'esatto meccanismo del looping viene Lapplicato ripetutamente ai suoi argomenti fino a quando il secondo argomento è zero, quindi viene restituito quel risultato. (Questa è la .[L]/parte.)

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

Per esplosione:

{_(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

In azione:

  {:[#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
 ()
 ())

0

Perl 6 , 67 byte

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

Provalo

Allargato:

{  # 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
}

Nel caso in cui non sei sicuro di quale triangolo ridurre fa:

[\*] 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

Se potessi prendere gli input invertiti e invertire il contrario, sarebbe 47 byte.

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

Provalo

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.