Перетворення змішаної бази


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

Я повинен припинити використовувати обертання масиву тільки тому, що у CJam це є ... Цей _{}?трюк справді акуратний.
Денніс

@sudo {}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 Ніколи не бачив програму CJam на 62 байти: D
Оптимізатор

@Optimizer Це , мабуть, моє найдовше подання CJam.
Esolanging Fruit


@Dennis Це був не кодовий гольф , чи не так?
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

Виправлено


Не кажіть "відходи";)
Мартін Ендер

Ви повинні мати можливість пограти
Zacharý

@ Zacharý Це був мій перший гольф, я думаю, я впевнений, що він може бути набагато коротшим за це! Відповідь Feersum демонструє це досить добре, я думаю. Якщо ви хочете, ви можете відредагувати цю відповідь, але я боюся, що я не особливо мотивований її вдосконалити.
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

Просто для загальної освіти - із вбудованими: {{⍵↓⍨1⍳⍨×⍵}(99⍴⎕)⊤⍵⊥⍨⎕⍴⍨⍴⍵}приймає D як правильний аргумент, потім просить я та О.
Адам

2

Пітон 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

Безголівки:

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]


@FryAmTheEggman Я не впевнений, як він може прийняти введення цитатами, але розділення масивів комами працює.
feersum

1

k2 - 83 74 char

Функція, що приймає один аргумент. Це було набагато краще підходить для 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
 ()
 ())

0

Perl 6 , 67 байт

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

Спробуй це

Розширено:

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

Спробуй це

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.