Mieszana konwersja bazy

12

tło

Większość ludzi tutaj powinna znać kilka podstawowych systemów: dziesiętny, binarny, szesnastkowy, ósemkowy. Na przykład w systemie szesnastkowym, numer 12345 16 stanowiłoby

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

Zauważ, że zazwyczaj nie oczekujemy, że podstawa (tutaj 16) zmieni się z cyfry na cyfrę.

Uogólnienie tych zwykłych systemów pozycyjnych pozwala na użycie innej podstawy liczbowej dla każdej cyfry. Np. Jeśli zmienilibyśmy system dziesiętny i dwójkowy (zaczynając od podstawy 10 w najmniej znaczącej cyfrze), liczba 190315 [2,10] reprezentowałaby

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

Oznaczamy tę bazę jako [2,10]. Najbardziej wysunięta na prawo podstawa odpowiada najmniej znaczącej cyfrze. Następnie przechodzisz przez bazy (po lewej), przechodząc przez cyfry (po lewej), owijając się, jeśli jest więcej cyfr niż baz.

Więcej informacji można znaleźć na Wikipedii .

Wyzwanie

Napisz program lub funkcję, która na podstawie listy cyfr Dpodstawy wejściowej Ii bazy wyjściowej Oprzekształca liczbę całkowitą reprezentowaną przez Dz bazy Ina bazę O. Możesz pobrać dane wejściowe za pomocą argumentu STDIN, ARGV lub funkcji i albo zwrócić wynik, albo wydrukować go do STDOUT.

Możesz założyć:

  • że numery w Ii Osą większe niż 1.
  • Ii Osą niepuste.
  • czy numer wejściowy jest prawidłowy w danej bazie (tj. żadna cyfra nie jest większa niż jej podstawa).

Dmoże być pusty (reprezentujący 0) lub może mieć zera na początku. Twój wynik nie powinien zawierać wiodących zer. W szczególności wynik reprezentujący 0powinien zostać zwrócony jako pusta lista.

Nie wolno używać żadnych wbudowanych ani zewnętrznych funkcji konwersji bazowej.

To jest kod golfowy, wygrywa najkrótsza odpowiedź (w bajtach).

Przykłady

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
źródło
Czy mogę wymagać nieskończonej listy jako podstawowego opisu, czy też muszę ją nieskończenie infinitify?
John Dvorak
@JanDvorak Masz na myśli, czy możesz oczekiwać, że listy podstawowe mają już wystarczającą liczbę powtórzeń, aby objąć wszystkie cyfry? Nie, będziesz musiał wykonać zawijanie lub powtarzanie się.
Martin Ender
Zakładam, że uzyskanie pustej listy, ponieważ podstawa to UB, ale czy możemy założyć, że lista cyfr nie jest pusta? Jakie są zasady dotyczące zer końcowych?
John Dvorak,
Mianowicie, nie mam nic przeciwko pustej liście na wejściu, ale chciałbym przedstawić, []jeśli wejście jest[0]
John Dvorak
Czy mogę poprosić o listę cyfr w odwrotnej kolejności (najpierw LSD)?
John Dvorak,

Odpowiedzi:

6

CJam, 45 lat

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

W końcu znalazłem dobre zastosowanie j.

Jak to działa

Long ArrayList Block jwykonuje blok, który przyjmuje liczbę całkowitą jako parametr, i Long jwywoła ten blok rekurencyjnie w bloku. Będzie także przechowywać wartości zwrócone przez blok w wewnętrznej tablicy, która jest inicjowana przez parametr array. Blok nie wykona bloku, jeśli dane wejściowe są już w tablicy, a zamiast tego zostanie zwrócona wartość z tablicy.

Więc jeśli zainicjuję go tablicą pustej tablicy, pusta tablica zostanie zwrócona dla wejścia 0, a blok zostanie wykonany dla dowolnego innego wejścia.

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

Dane wejściowe powinny być O I D.

Przykłady:

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

Jak to działa

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
źródło
Muszę przestać używać rotacji tablic tylko dlatego, że ma to CJam ... Ta _{}?sztuczka jest naprawdę fajna .
Dennis
@sudo {}e|jest taki sam.
jimmy23013
Czy mógłbyś dodać wyjaśnienie używanej wersji j? :)
Martin Ender
@ MartinBüttner Gotowe.
jimmy23013
3

CJam, 62 61 59 57 bajtów

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

Odczytuje tablice wejściowe [O I D]od STDIN. Wypróbuj online.

Jak to działa

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

Przypadki testowe

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

Zauważ, że puste łańcuchy i puste tablice są nierozróżnialne dla CJam, więc []pdrukuje "".

Dennis
źródło
4
OMG Nigdy nie widziałem 62-bajtowego programu CJam: D
Optimizer
@Optimizer To prawdopodobnie moje najdłuższe zgłoszenie do CJam.
Esolanging Fruit
@Dennis To nie był kod-golf , prawda?
Esolanging Fruit
@ Challenger5 Nie było, ale wątpię, że wersja w golfa byłaby krótsza niż 200 bajtów.
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 [])

Przypadkowo pomieszałem kolejność argumentów, więc musiałem je odwrócić. Popracuję nad plastrem-fu, aby później listy działały w innym kierunku, zmarnowałem już całą przerwę na lunch: p

Naprawiony

FryAmTheEggman
źródło
Nie mów „marnuj”;)
Martin Ender
Powinieneś być w stanie zagrać w
Zacharý
@ Zacharý To był mój pierwszy golf. Myślę, że może być znacznie krótszy! Odpowiedź Feersum pokazuje, że myślę, że całkiem dobrze. Jeśli chcesz, możesz edytować tę odpowiedź, ale obawiam się, że nie mam szczególnej motywacji, aby ją poprawić.
FryAmTheEggman
2

APL, 78

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

Przykłady:

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
źródło
Tylko dla edukacji ogólnej - z wbudowanymi funkcjami: {{⍵↓⍨1⍳⍨×⍵}(99⍴⎕)⊤⍵⊥⍨⎕⍴⍨⍴⍵}bierze D jako właściwy argument, a następnie prosi o I i O.
Adám
2

Python 2 - 122

Bardzo proste, nie udało mi się znaleźć żadnych specjalnych sztuczek golfowych na tym.

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

Nie golfowany:

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

Edycja: 116-bajtowa wersja programu dzięki 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

Ta wersja akceptuje dane oddzielone przecinkami, np [1,9,0,3,1,5], [2,10], [10]

feersum
źródło
@FryAmTheEggman Nie jestem pewien, jak mógłby zaakceptować dane wejściowe z cudzysłowami, ale działa rozdzielanie tablic przecinkami.
feersum
1

k2 - 83 74 znak

Funkcja przyjmująca jeden argument. To było po prostu znacznie lepiej dostosowane do K niż J, dlatego nie używam J. To byłby po prostu mnóstwo śmieci do boksowania / rozpakowywania i nikt tego nie chce. Jest to w dialekcie k2 (może wymagać pewnej adaptacji do pracy w implementacji Kona typu open source), ale zmienię to na k4, jeśli będę mógł tam grać w golfa krócej.

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

Zauważę, że stoję tutaj za wybrednością i mówię, że jedną listę pozycji należy wprowadzić jako taką. ,2to lista jednego elementu, którym jest skalar 2. Często skalary i listy 1-elementowe są wymienne, ale w tym golfie istnieje logika polegająca na przyjmowaniu argumentów listy.

Aby wyjaśnić golfa, podzielę go na dwie części. Fjest golfem, Ljest główną pętlą obliczającą wynik. Dokładny mechanizm zapętlania jest Lstosowany wielokrotnie do argumentów, aż drugi argument wyniesie zero, a następnie ten wynik jest zwracany. (To jest .[L]/część.)

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

Przez wybuch:

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

W akcji:

  {:[#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
 ()
 ())
algorytmshark
źródło
0

Perl 6 , 67 bajtów

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

Spróbuj

Rozszerzony:

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

Jeśli nie masz pewności, co zmniejsza trójkąt:

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

Gdybym mógł cofnąć dane wejściowe i odwrócić dane wyjściowe, byłoby 47 bajtów.

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

Spróbuj

Brad Gilbert b2gills
źródło