Смешанное базовое преобразование

12

Фон

Большинство людей здесь должны быть знакомы с несколькими базовыми системами: десятичной, двоичной, шестнадцатеричной, восьмеричной. Например, в шестнадцатеричной системе число 12345 16 будет представлять

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

Обратите внимание, что мы обычно не ожидаем, что база (здесь 16) изменится с цифры на цифру.

Обобщение этих обычных позиционных систем позволяет использовать различную числовую базу для каждой цифры. Например, если бы мы чередовали десятичную и двоичную системы (начиная с основания 10 в наименее значащей цифре), число 190315 [2,10] будет представлять

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

Обозначим эту базу как [2,10]. Самая правая основа соответствует наименее значащей цифре. Затем вы проходите через базы (слева) и цифры (слева), оборачиваясь, если цифр больше, чем баз.

Для дальнейшего чтения см. Википедию .

Соревнование

Напишите программу или функцию, которая, учитывая список цифр Dвходной базы Iи выходной базы O, преобразует целое число, представленное как Dиз базы Iв базу O. Вы можете получить ввод через STDIN, ARGV или аргумент функции и либо вернуть результат, либо распечатать его в STDOUT.

Вы можете предположить:

  • что числа в Iи Oвсе больше чем 1.
  • Iи Oне пусты.
  • что входной номер действителен в данной базе (т. е. ни одна цифра не превышает его базу).

Dможет быть пустым (представляющим 0) или может иметь начальные нули. Ваш вывод не должен содержать лидирующие нули. В частности, представление результата 0должно быть возвращено как пустой список.

Вы не должны использовать какие-либо встроенные или сторонние функции преобразования базы.

Это код гольф, самый короткий ответ (в байтах) выигрывает.

Примеры

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]     []
Мартин Эндер
источник
Могу ли я потребовать бесконечный список в качестве базового описания, или я должен сам сделать его бесконечным?
Джон Дворак
@JanDvorak Вы имеете в виду, если вы можете ожидать, что базовые списки уже будут иметь достаточное количество повторений, чтобы охватить все цифры? Нет, вам придётся делать обтекание или повторяться.
Мартин Эндер
Я предполагаю, что получение пустого списка в качестве базы - это UB, но можем ли мы предположить, что список цифр не пустой? Кроме того, какова политика в отношении конечных нулей?
Джон Дворжак
А именно, я не против пустого списка на входе, но я хотел бы произвести, []если вход[0]
Джон Дворжак
Могу ли я запросить и составить список цифр в обратном порядке (сначала LSD)?
Джон Дворак

Ответы:

6

CJam, 45

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

Наконец я нашел хорошее применение j.

Как это устроено

Long ArrayList Block jвыполняет блок, который принимает целое число в качестве параметра, и Long jбудет рекурсивно вызывать этот блок в блоке. Он также будет хранить значения, возвращаемые блоком, во внутреннем массиве, который инициализируется параметром массива. Он не будет выполнять блок, если вход уже находится в массиве, и вместо него возвращается значение в массиве.

Поэтому, если я инициализирую его массивом пустого массива, пустой массив будет возвращен для ввода 0, а блок будет выполнен для любого другого ввода.

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

Вход должен быть O I D.

Примеры:

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

Как это устроено

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
источник
Я должен прекратить использовать вращение массива только потому, что он у CJam ... Этот _{}?трюк действительно хорош.
Деннис
@ Судо {}e|это то же самое.
jimmy23013
Не могли бы вы добавить объяснение использования версии j? :)
Мартин Эндер
@ MartinBüttner Готово.
jimmy23013
3

CJam, 62 61 59 57 байт

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

Читает входные массивы как [O I D]из STDIN. Попробуйте онлайн.

Как это устроено

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

Контрольные примеры

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

Обратите внимание, что пустые строки и пустые массивы неотличимы от CJam, поэтому []pпечатает "".

Деннис
источник
4
OMG Никогда не видел 62-байтовую программу CJam: D
Оптимизатор
@Optimizer Это , наверное, мое самое длинное представление CJam.
Esolanging Fruit
@ Challenger5 codegolf.stackexchange.com/a/51238/12012
Деннис,
@ Денис Это был не код-гольф , не так ли?
Esolanging Fruit
@ Challenger5 Это не так, но я сомневаюсь, что версия для гольфа будет короче, чем 200 байтов.
Деннис
2

Питон 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 [])

Я случайно перепутал порядок рассуждений, поэтому пришлось их поменять. Я буду работать над слайс-фу, чтобы списки работали в другом направлении позже, я уже потратил впустую весь перерыв на обед: p

Исправлена

FryAmTheEggman
источник
Не говори «впустую»;)
Мартин Эндер
Вы должны быть в состоянии сыграть
Zacharý
@ Zacharý Это был мой первый гольф, я думаю, я уверен, что он может быть намного короче этого! Ответ Ферсума демонстрирует, что, я думаю, это хорошо. Если вы хотите, вы можете отредактировать этот ответ, но я боюсь, что у меня нет особой мотивации для его улучшения.
FryAmTheEggman
2

APL, 78

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

Примеры:

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
источник
Только для общего образования - со встроенными модулями: {{⍵↓⍨1⍳⍨×⍵}(99⍴⎕)⊤⍵⊥⍨⎕⍴⍨⍴⍵}принимает D в качестве правильного аргумента, а затем просит меня и О.
Адам
2

Python 2 - 122

Очень просто, не удалось найти каких-либо специальных уловок гольфа в этом.

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

Редактировать: 116-байтовая версия программы благодаря 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

Эта версия принимает ввод через запятую, например [1,9,0,3,1,5], [2,10], [10]

feersum
источник
@FryAmTheEggman Я не уверен, как он может принимать ввод с кавычками, но разделение массивов запятыми работает.
Feersum
1

к2 - 83 74 чар

Функция принимает один аргумент. Это было намного лучше подходит для K, чем для J, поэтому я не использую J. Это было бы просто нагрузкой для упаковки / распаковки мусора, и никто этого не хочет. Это на диалекте k2 (может потребоваться некоторая адаптация для работы в реализации с открытым исходным кодом Kona), но я поменяю это на k4, если смогу там поиграть в гольф.

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

Отмечу, что здесь я отстаиваю придирчивость и говорю, что списки одного предмета должны быть введены как таковые. ,2это список одного элемента, который является скаляром 2. Часто скаляры и списки из 1 элемента взаимозаменяемы, но в этом гольфе есть логика, основанная на предположении о списочных аргументах.

Чтобы объяснить гольф, я разобью его на две части. Fэто гольф, Lэто основной цикл, который рассчитывает выходной. Точный механизм зацикливания заключается в том, что Lон применяется к его аргументам несколько раз, пока второй аргумент не станет равным нулю, а затем этот результат будет возвращен. (Это .[L]/часть.)

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

Взрывом:

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

В бою:

  {:[#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
источник
0

Perl 6 , 67 байт

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

Попытайся

Expanded:

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

Если вы не уверены, что делает уменьшение треугольника:

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

Если бы я мог взять входные данные в обратном порядке и вывести обратные, это было бы 47 байтов.

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

Попытайся

Брэд Гилберт b2gills
источник