Conversion de base mixte

12

Contexte

La plupart des gens ici devraient être familiers avec plusieurs systèmes de base: décimal, binaire, hexadécimal, octal. Par exemple, dans le système hexadécimal, le nombre 12345 16 représenterait

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

Notez que nous ne nous attendons généralement pas à ce que la base (ici 16) change d'un chiffre à l'autre.

Une généralisation de ces systèmes de position habituels vous permet d'utiliser une base numérique différente pour chaque chiffre. Par exemple, si nous alternions entre le système décimal et binaire (en commençant par la base 10 dans le chiffre le moins significatif), le nombre 190315 [2,10] représenterait

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

Nous désignons cette base comme [2,10]. La base la plus à droite correspond au chiffre le moins significatif. Ensuite, vous passez par les bases (à gauche) en parcourant les chiffres (à gauche), en vous retournant s'il y a plus de chiffres que de bases.

Pour plus de lecture, voir Wikipedia .

Le défi

Écrivez un programme ou une fonction qui, étant donné une liste de chiffres, Dune base d'entrée Iet une base de sortie O, convertit l'entier représenté par Dde base Ien base O. Vous pouvez saisir des données via STDIN, ARGV ou un argument de fonction et renvoyer le résultat ou l'imprimer dans STDOUT.

Vous pouvez supposer:

  • que les nombres Iet Osont tous supérieurs à 1.
  • la Iet Osont non vides.
  • que le numéro d'entrée est valide dans la base donnée (c'est-à-dire, aucun chiffre plus grand que sa base).

Dpourrait être vide (représentant 0) ou pourrait avoir des zéros non significatifs. Votre sortie ne doit pas contenir de zéros non significatifs. En particulier, un résultat représentant 0doit être renvoyé sous forme de liste vide.

Vous ne devez utiliser aucune fonction de conversion de base intégrée ou tierce.

Il s'agit du code golf, la réponse la plus courte (en octets) l'emporte.

Exemples

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
la source
Puis-je exiger une liste infinie comme description de base ou dois-je l'infinir moi-même?
John Dvorak
@JanDvorak Vous voulez dire si vous pouvez vous attendre à ce que les listes de base aient déjà un nombre suffisant de répétitions pour couvrir tous les chiffres? Non, vous devrez faire le tour ou vous répéter.
Martin Ender
Je suppose que l'obtention d'une liste vide en tant que base est UB, mais pouvons-nous supposer que la liste des chiffres n'est pas vide? De plus, quelle est la politique sur les zéros de fin?
John Dvorak
A savoir, cela ne me dérange pas une liste vide en entrée, mais je voudrais produire []si l'entrée est[0]
John Dvorak
Puis-je demander et produire une liste de chiffres dans l'ordre inverse (LSD en premier)?
John Dvorak

Réponses:

6

CJam, 45

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

Enfin, j'ai trouvé une bonne utilisation de j.

Comment ça fonctionne

Long ArrayList Block jexécute le bloc qui prend un entier comme paramètre, et Long jappellera ce bloc récursivement dans le bloc. Il stockera également les valeurs renvoyées par le bloc dans un tableau interne, qui est initialisé par le paramètre tableau. Il n'exécutera pas le bloc si l'entrée est déjà dans le tableau et que la valeur dans le tableau est renvoyée à la place.

Donc, si je l'initialise avec un tableau d'un tableau vide, le tableau vide sera retourné pour l'entrée 0, et le bloc sera exécuté pour toute autre entrée.

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'entrée doit être O I D.

Exemples:

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

Comment ça fonctionne

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
la source
Je dois arrêter d'utiliser la rotation de tableau simplement parce que CJam l'a ... Ce _{}?truc est vraiment bien.
Dennis
@sudo {}e|est le même.
jimmy23013
Pourriez-vous ajouter une explication pour la version utilisant j? :)
Martin Ender
@ MartinBüttner Fait.
jimmy23013
3

CJam, 62 61 59 57 octets

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

Lit les tableaux d'entrée à [O I D]partir de STDIN. Essayez-le en ligne.

Comment ça fonctionne

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

Cas de 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]         ]'
""

Notez que les chaînes vides et les tableaux vides ne peuvent pas être distingués de CJam, donc []pimprime "".

Dennis
la source
4
OMG Jamais vu un programme CJam de 62 octets: D
Optimizer
@Optimizer C'est probablement ma plus longue soumission CJam.
Esolanging Fruit
@Dennis Ce n'était pas du golf de code , n'est-ce pas?
Esolanging Fruit
@ Challenger5 Ce n'était pas le cas, mais je doute qu'une version golfée soit plus courte que 200 octets.
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 [])

J'ai foiré l'ordre des arguments par accident, j'ai donc dû les inverser. Je vais travailler sur la tranche-fu pour faire fonctionner les listes dans l'autre sens plus tard, j'ai déjà perdu toute ma pause déjeuner: p

Fixé

FryAmTheEggman
la source
Ne dites pas "gaspillage";)
Martin Ender
Vous devriez pouvoir le jouer à 286 octets: repl.it/JbIk
Zacharý
@ Zacharý C'était mon premier golf je pense, je suis sûr que ça peut être beaucoup plus court que ça! La réponse de Feersum le démontre assez bien, je pense. Si vous le souhaitez, vous pouvez modifier cette réponse, mais je crains de ne pas être particulièrement motivé pour l'améliorer.
FryAmTheEggman
2

APL, 78

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

Exemples:

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
la source
Juste pour l'enseignement général - avec intégré: {{⍵↓⍨1⍳⍨×⍵}(99⍴⎕)⊤⍵⊥⍨⎕⍴⍨⍴⍵}prend D comme bon argument, puis demande I et O.
Adám
2

Python 2 - 122

Très simple, je n'ai pas réussi à trouver d'astuces de golf spéciales sur celui-ci.

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

Non 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

Edit: version du programme de 116 octets grâce à 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

Cette version accepte les entrées séparées par des virgules, par exemple [1,9,0,3,1,5], [2,10], [10]

feersum
la source
@FryAmTheEggman Je ne sais pas comment il pourrait accepter l'entrée avec des guillemets, mais séparer les tableaux avec des virgules fonctionne.
feersum
1

k2 - 83 74 car

Fonction prenant un argument. C'était bien mieux adapté à K qu'à J, c'est pourquoi je n'utilise pas J. Ce serait juste une charge de déchets de boxe / déballage, et personne ne veut ça. C'est dans le dialecte k2 (peut nécessiter une adaptation pour fonctionner dans l'implémentation open source Kona), mais je changerai cela en k4 si je peux y jouer plus court.

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

Je noterai que je prends position pour la ponctualité ici et que je dis qu'une liste d'articles doit être saisie en tant que telle. ,2est une liste d'un élément, cet élément étant le scalaire 2. Souvent, les scalaires et les listes à 1 élément sont interchangeables, mais il y a une logique dans ce golf qui repose sur l'hypothèse d'arguments de liste.

Pour expliquer le golf, je vais le diviser en deux parties. Fest le golf, Lest la boucle principale qui calcule la sortie. Le mécanisme exact du bouclage est celui qui Lest appliqué à ses arguments à plusieurs reprises jusqu'à ce que le deuxième argument soit nul, puis ce résultat est renvoyé. (C'est la .[L]/partie.)

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

Par explosion:

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

  {:[#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
 ()
 ())
algorithmshark
la source
0

Perl 6 , 67 octets

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

Essayez-le

Étendu:

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

Dans le cas où vous n'êtes pas sûr de ce que le triangle réduit:

[\*] 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 je pouvais prendre les entrées inversées et produire l'inverse, ce serait 47 octets.

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

Essayez-le

Brad Gilbert b2gills
la source