การแปลงฐานแบบผสม


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และทุกคนมากกว่าO1
  • 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]     []

ฉันขอรายการที่ไม่มีขีด จำกัด เพื่อเป็นคำอธิบายพื้นฐานได้หรือไม่
John Dvorak

@JanDvorak คุณหมายความว่าถ้าคุณสามารถคาดหวังว่ารายการฐานมีจำนวนซ้ำที่เพียงพอที่จะครอบคลุมตัวเลขทั้งหมดหรือไม่ ไม่คุณจะต้องล้อมรอบหรือทำซ้ำตัวเอง
Martin Ender

ฉันถือว่าการรับรายการว่างเปล่าเนื่องจากฐานคือ UB แต่เราอาจคิดว่ารายการตัวเลขไม่ว่างเปล่า? นอกจากนี้นโยบายเกี่ยวกับศูนย์ต่อท้ายคืออะไร
John Dvorak

คือฉันไม่รังเกียจรายการว่างในอินพุต แต่ฉันต้องการผลิต[]หากอินพุตคือ[0]
John Dvorak

ฉันขอและผลิตรายการตัวเลขในลำดับย้อนกลับ (LSD ก่อน) ได้หรือไม่?
John Dvorak

คำตอบ:


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 มี ... _{}?เคล็ดลับนั่นมันเรียบร้อยดีจริงๆ
Dennis

@sudo {}e|เหมือนกัน
jimmy23013

คุณต้องการเพิ่มคำอธิบายสำหรับเวอร์ชันที่ใช้jหรือไม่ :)
Martin Ender

@ 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 ที่ยาวที่สุดของฉัน
แยกผลไม้


@Dennis นั่นไม่ใช่โค้ดกอล์ฟใช่มั้ย
แยกผลไม้

@ Challenger5 มันไม่ใช่ แต่ฉันสงสัยว่าเวอร์ชัน golfed จะสั้นกว่า 200 ไบต์
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 [])

ฉันทำตามลำดับของการขัดแย้งโดยไม่ตั้งใจดังนั้นฉันต้องย้อนกลับ ฉันจะทำงานกับ slice-fu เพื่อให้รายการทำงานในทิศทางอื่นในภายหลังฉันเสียเวลาพักไปแล้ว: p

แก้ไขแล้ว


อย่าพูดคำว่า "เปลือง";)
Martin Ender

คุณควรจะสามารถเล่นกอล์ฟได้ถึง 286 ไบต์: repl.it/JbIk
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 เป็นอาร์กิวเมนต์ที่ถูกต้องแล้วถามฉันและ O.
16 Adám

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]


@FryAmTheEggman ฉันไม่แน่ใจว่าจะรับอินพุตด้วยเครื่องหมายคำพูดได้อย่างไร แต่แยกอาร์เรย์ด้วยเครื่องหมายจุลภาค
feersum

1

k2 - 83 74 ตัวอักษร

ฟังก์ชั่นรับหนึ่งอาร์กิวเมนต์ นี่เป็นสิ่งที่ดีกว่าสำหรับ K มากกว่า J ซึ่งเป็นเหตุผลที่ฉันไม่ได้ใช้ J มันจะเป็นขยะมวย / กล่องขยะและไม่มีใครต้องการมัน นี่คือภาษา k2 (อาจต้องมีการปรับตัวเพื่อทำงานในโอเพนซอร์สโคนา) แต่ฉันจะเปลี่ยนเป็น 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*}

ลองมัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.