ฐาน bijective ทั้งหมดของคุณเป็นของเรา


25

พื้นหลัง

bijective ฐานเลขที่เป็นจำนวนเต็มบวกเป็นสัญกรณ์ตำแหน่ง bijective ที่ทำให้การใช้สัญลักษณ์ที่เกี่ยวข้องกับค่านิยมของ1ที่จะข

ซึ่งแตกต่างจากคู่ไม่ใช่ bijective ของสัญลักษณ์ไม่มีมีค่าเป็น0 วิธีนี้แต่ละจำนวนเต็มไม่เป็นลบnมีที่ไม่ซ้ำกันเป็นตัวแทนใน bijective ฐานข

ตัวเลข bijective ที่เป็นที่นิยม ได้แก่ unary, bijective base 2 (ใช้ในการเข้ารหัสแบบ run-length ของ bzip2 ) และ bijective base 26 (เคยเป็นคอลัมน์จำนวนในสเปรดชีต)

คำนิยาม

ในความท้าทายนี้เราได้กำหนดสัญลักษณ์ชุดMเป็น

123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz<=>

และฟังก์ชั่นฉันจากMไปยังหมายเลขธรรมชาติเช่นว่าฉัน ( '1') = 1, ... , I ( '>') = 64

ได้รับฐานระหว่าง1และ64 (ทั้งรวม) เรากำหนดว่าแต่ละจำนวนเต็มไม่เป็นลบnสอดคล้องกับสตริงkที่ ... 0ประกอบด้วยสัญลักษณ์ของMเช่นว่าn = b kฉัน (กk ) + ... + B 0ฉัน (เป็น0 )

จดหมายนี้มีการกำหนดที่ดีและมีความ bijective เนื่องจากผลรวมที่ว่างเปล่าถูกกำหนดเป็น0จำนวนเต็ม0จึงสามารถเข้ารหัสเป็นสตริงที่ว่างเปล่า

งาน

ยอมรับสามสายเป็นอินพุต:

  • อินพุตฐานbระหว่าง1ถึง64เข้ารหัสเป็นสตริงฐาน64 bijective

  • จำนวนเต็มไม่เป็นลบnซึ่งเข้ารหัสเป็นสตริงฐานทางชีวภาพb

  • เอาต์พุตฐานBระหว่าง1ถึง64ซึ่งเข้ารหัสเป็นสตริงฐาน bijective 64

รับอินพุตทั้งสามนี้ให้เข้ารหัสnเป็นสตริงฐานB ของ Bijective

กรณีทดสอบ

กรณีทดสอบทั้งหมดระบุการป้อนข้อมูลในการสั่งซื้อ , n , B

Input:  "4" "" "8"
Output: ""

Input:  "A" "16" "2"
Output: "1112"

Input:  "2" "122" "A"
Output: "A"

Input:  "3" "31" "1"
Output: "1111111111"

Input:  ">" "Fe" "a"
Output: "RS"

กฎระเบียบ

  • คุณสามารถอ่านสามสตริงในลำดับที่สะดวกเช่นอาร์เรย์ของสตริงการแทนสตริงการต่อกันหรือคั่นด้วยตัวคั่นอักขระเดี่ยวที่คุณเลือก

  • หากคุณเลือกที่จะพิมพ์ผลลัพธ์ไปที่ STDOUT คุณสามารถพิมพ์สัญลักษณ์และขึ้นบรรทัดใหม่ (หรือเป็นทางเลือก)

  • อนุญาตการแปลงฐานบิวด์อินทุกชนิด

  • ใช้กฎมาตรฐานของ

คำตอบ:


6

CJam, 43

qA,s"?[a{A<":,:^+:Mf#):B;(bLa{(Bmd)M=\j\+}j

กำจัด 3 ไบต์ด้วยความช่วยเหลือจาก Dennis :) ลองออนไลน์

คำอธิบาย:

อินพุตถูกนำมาเป็นbnBตัดแบ่งเป็นสตริงเดียว

q           read the input
A,s         make an array of numbers from 0 to 9 and convert to string
"?[a{A<"    push this string, which contains the ends of 3 character ranges:
             uppercase letters: ['A'…'[')
             lowercase letters: ['a'…'{')
             "<=>": ['<'…'?')
             they're in a special order for the symmetric difference below
:,          for each character, make a range of all characters smaller than it
:^          fold/reduce these 6 ranges using symmetric difference
+           concatenate with the digits before
:M          save in M; this is like the M from the statement,
             except it starts with a zero (for matching indexes)
f#          find the indexes in M of all characters from the input string
)           take out the last value from the array
:B;         save it in B and pop it
(           take out the first value
b           use it as a base and convert the remaining array to a number
             this works even if some of the digits are not in the "normal" range
La{…}j      calculate with memoized recursion, using an empty string for value 0
  (         decrement the number
  Bmd       divide by B and get the quotient and remainder
  )         increment the remainder (this is the last digit in bijective base B)
  M=        get the corresponding character from M
  \j        swap with the quotient, and convert the quotient recursively
  \+        swap again and concatenate

โอ้คุณสามารถใช้ตัวดำเนินการแปลงพื้นฐานปกติสำหรับการแปลงฐานแรกได้หรือไม่ ตอนนี้ฉันรู้สึกเซ่อที่จะใช้รหัสทั้งหมดที่ฉันมีในโซลูชันของฉัน :) ฉันไม่ได้ตระหนักว่ามันจะทำงานกับค่าที่อยู่นอกช่วงของฐาน ในความเข้าใจย้อนหลังไม่มีเหตุผลที่ดีว่าทำไมมันไม่ควร
Reto Koradi

@RetoKoradi ใช่คุณทำได้ วันหนึ่งมันจะถูกบันทึก :)
aditsu

คุณรังเกียจไหมถ้าฉันเปลี่ยนวิธีแก้ปัญหาเพื่อใช้การแปลงพื้นฐาน ปกติฉันจะพยายามหลีกเลี่ยงความคิดจากโซลูชันอื่น ๆ แต่มันทำให้ฉันเป็นบ้าจริง ๆ ที่จะให้ฉันยืนด้วยวิธีที่ดีที่สุด มีโอกาสสูงที่โซลูชันของคุณจะยังสั้นกว่า
Reto Koradi

@RetoKoradi ไม่มีปัญหาไปเลย
aditsu

4

Pip, 84 80 78 bytes

m:J[,tAZLCAZ"<=>"]p:$+(m@?^b)*(m@?a)**RV,#bs:m@?cWn:px:(mn-(p:n//s-!n%s)*s).xx

ที่เก็บ GitHub สำหรับ Pip

อัลกอริทึมที่ดัดแปลงมาจากบทความ Wikipedia นี่คือคำอธิบายสำหรับเวอร์ชั่นก่อนหน้านี้ที่ไม่ได้รับความสนใจเล็กน้อย:

                 Implicit: initialize a,b,c from cmdline args; t=10;
                 AZ=uppercase alphabet; x=""
m:               Build lookup table m:
 (J,t)             0123456789 (i.e. join(range(10)))...
 .AZ               plus A-Z...
 .LCAZ             plus lowercase a-z...
 ."<=>"            plus <=>
f:{              Define f(a,b) to convert a from bijective base b to decimal:
 $+                Sum of...
  (m@?^a)            list of index of each character of a in m
  *                  multiplied item-wise by 
  b**RV,#a           b to the power of each number in reverse(range(len(a)))
}
t:{              Define t(a,b) to convert a from decimal to bijective base b:
 x:""              Reset x to empty string (not needed if only calling the function once)
 Wa{               While a is not zero:
  p:a//b-!a%b        p = ceil(a/b) - 1 (= a//b if a%b!=0, a//b-1 otherwise)
  x:m@(a-p*b).x      Calculate digit a-p*b, look up the corresponding character in m, and
                     prepend to x
  a:p                p becomes the new a
 }
 x                 Return x
}
(t               Return result of calling t with these arguments:
 (f                Result of calling f with these arguments:
  b                  2nd cmdline arg
  m@?a)              1st cmdline arg's decimal value
 m@?c              3rd cmdline arg's decimal value
)
                 Print (implicit)

วิ่งตัวอย่าง:

dlosc@dlosc:~/golf$ python pip.py bijectivebase.pip ">" "Fe" "a"
RS

4

คู่, 166 ไบต์

function z=b(o,x,n)
M=['1':'9','A':'Z','a':'z','<=>'];N(M)=1:64;n=N(n);x=polyval(N(x),N(o));z='';while x>0 r=mod(x,n);t=n;if r t=r;end;z=[M(t),z];x=fix(x/n)-(r<1);end

รุ่นหลายสาย:

function z=b(o,x,n)
   M=['1':'9','A':'Z','a':'z','<=>'];
   N(M)=1:64;
   n=N(n);
   x=polyval(N(x),N(o));
   z='';
   while x>0
      r=mod(x,n);
      t=n;if r t=r;end;
      z=[M(t),z];
      x=fix(x/n)-(r<1);
   end
%end // implicit - not included above

แทนที่จะสร้างแผนที่เพื่อแปลงอักขระเป็นค่าดัชนีฉันเพิ่งสร้างตารางการค้นหาแบบผกผันNสำหรับค่า ascii 1..'z'และเติมด้วยดัชนีที่ค่าที่เหมาะสม

polyval ประเมินสมการ

c 1 x k + c 2 x k-1 + ... + c k x 0

ใช้ค่าการป้อนข้อมูลทศนิยมที่แปลงเป็นเวกเตอร์ของค่าสัมประสิทธิ์และฐานเดิมc x(น่าเสียดายที่อ็อกเทฟbase2dec()ปฏิเสธสัญลักษณ์ที่อยู่นอกช่วงปกติ)

เมื่อเรามีค่าอินพุตในฐาน 10 แล้วการคำนวณค่าในฐานใหม่นั้นตรงไปตรงมา

ทดสอบไดรเวอร์:

% script bijecttest.m
a=b('4','','8');
disp(a);
a=b('A','16','2');
disp(a);
a=b('2','122','A');
disp(a);
a=b('3','31','1');
disp(a);
a=b('>','Fe','a');
disp(a);

ผล:

>> bijecttest

1112
A
1111111111
RS
>>

2

Perl, 261 248 229 ไบต์

sub t{$b=0;$b*=$_[1],$b+=ord($1=~y/0-9A-Za-z<=>/\0-A/r)while$_[0]=~/(.)/g;return$b}sub r{$n=$_[0];$n-=$m=($n-1)%$_[1]+1,$d=(chr$m)=~y/\0-A/0-9A-Za-z<=>/r.$d,$n/=$_[1]while$n;print$d}@a=split/,/,<>;r(t(@a[1],t@a[0],64),t@a[2],64)

หลายบรรทัดในขณะที่ลูป ungolfed:

sub t{ # convert bijective base string to number
    $b=0;
    while($_[0]=~/(.)/g)
        {$b*=$_[1];$b+=ord($1=~y/0-9A-Za-z<=>/\0-A/r)}
    return$b}
sub r{ # convert number to bijective base string
    $n=$_[0];
    while($n)
        {$n-=$m=($n-1)%$_[1]+1;$d=(chr$m)=~y/\0-A/0-9A-Za-z<=>/r.$d;$n/=$_[1]}
    print$d}
@a=split/,/,<>; # parse input
r(t(@a[1],t@a[0],64),t@a[2],64)

tเป็นฟังก์ชันในการแยกตัวเลขจากสตริง bijective-base ของฐานที่กำหนด rเป็นฟังก์ชั่นในการสร้างสตริง bijective-base ของฐานที่กำหนดจากตัวเลข พารามิเตอร์ที่คั่นด้วยเครื่องหมายจุลภาค 3 ตัวจะถูกวิเคราะห์คำจาก stdin และฟังก์ชันจะถูกเรียกใช้ตามต้องการ

การแปลงจำนวนบวกไปเป็นสตริงฐาน bijective จะคล้ายกับฐานปกติ อย่างไรก็ตามคุณจะทำอะไรแบบนี้กับฐานปกติ:

string s = ""
while(n)
{
    c = (n % base)
    s = (c + '0') + s
    n -= c // not necessary because the division will take care of it
    n /= base 
}

คุณปรับ mod เพื่อให้มีช่วงตั้งแต่ 1 ถึงเบสแทนที่จะเป็น 0 ถึง base - 1:

string s = ""
while(n)
{
    c = (((n-1) % base)+1)
    s = (c + '0') + s
    n -= c  // necessary in the case c = base
    n /= base 
}

2

Python 2, ... 317 307 298 311 ไบต์

สามารถเล่นกอล์ฟได้อย่างแน่นอน findฉันเกลียดจริงๆว่าสตริงมีการกำหนดรายการและรายการไม่มีไม่มี ฉันจะดูวิธีที่ดีกว่าการแก้ไขอย่างรวดเร็วของฉันที่ฉันมีตอนนี้

วิธีการของฉันคือการแปลงอินพุตให้เป็นตัวเลขทศนิยมจากนั้นเป็นฐานเอาต์พุตจากนั้นแปลงเป็นฐานไบโอเจล

แก้ไข : พบว่าโปรแกรมของฉันไม่ทำงานเมื่อแปลงเป็น Unary มีค่าใช้จ่าย 13 ไบต์ในการแก้ไขe=F(o)<2ฯลฯ

ลองที่นี่

R=range;M="".join(map(chr,R(48,58)+R(65,91)+R(97,123)))+"<=>"
b,s,o=input()
F=M.find
e=F(o)<2
B=lambda n:n and B(n/F(o)-e)+M[n%F(o)+e]or""
n=B(sum(F(s[~j])*F(b)**j for j in R(len(s))))
i=n.find('0')
n=list(n)
while-~i:n=n[:i-1]+[M[F(n[i-1])-1]]+[o]+n[i+1:];n=n["0"==n[0]:];i="".join(n).find('0')
print"".join(n)

1
ฉันเห็นด้วยกับสัตว์เลี้ยง Python ของคุณ
DLosc

@DLosc ขอบคุณสำหรับความช่วยเหลือของกอล์ฟ
mbomb007


รายการมี.index()วิธีการ .. ทำไมไม่ลองใช้มันแทนการค้นหาล่ะ นอกจากนี้แทนที่จะบันทึกF(b)และF(o)ตัวแปรคุณใช้เพียงครั้งเดียวดังนั้นให้ย่อยในที่ที่จำเป็น ในที่สุด'n'[2::5]สั้นกว่า''.join(n)(แทนที่ apostrophes สำหรับ backticks)
Kade

นอกจากนี้ฉันคิดว่าคุณกำลังซับซ้อนเกินไป .. การแปลงจากสตริง M bijective base b เป็นทศนิยมไม่ควรใช้เกิน 35-40 ไบต์ ทศนิยมให้เป็นสตริงของฐาน bijective B จะไม่มากไปกว่านั้น
Kade

2

Python 2, 167 ไบต์

ไม่มีเทคนิคพิเศษในที่นี่จริง ๆ ยกเว้นการ[2::5]แบ่งส่วนเพื่อรับชุดอักขระที่จำนวนไบต์ที่ต่ำกว่า

x=range;A=`map(chr,x(49,58)+x(65,91)+x(97,123))`[2::5]+'<=>'
r=A.find
b,n,B=input()
B=r(B)+1
d=0;s=''
for c in n:d=d*-~r(b)+r(c)+1
while d:d-=1;s=A[d%B]+s;d/=B
print s

แบบทดสอบ:

"4","","8"     >>> (empty string)
">","Fe","a"   >>> RS
"3","31","1"   >>> 1111111111
"A","16","2"   >>> 1112
"2","122","A"  >>> A

2

CJam, 73 70 69 55 51 48 ไบต์

เวอร์ชันล่าสุดใช้ตัวดำเนินการแปลงฐาน CJam สำหรับการแปลงจากฐานต้นทางซึ่งฉันไม่เคยคิดมาก่อนจนกระทั่งเห็นโซลูชันของ @ aditsu นอกจากนี้ยังใช้เคล็ดลับล่าสุดโดย @Dennis สำหรับการสร้างสตริง "หลัก" ( /codegolf//a/54348/32852 ) รวมถึงแนวคิดอื่น ๆ ที่ใช้ร่วมกันในการแชท

lA,s'[,_el^+"<=>"+:Lf#Ll#bLl#:K;{(Kmd)L=\}hs-]W%

รูปแบบอินพุตเป็นค่าตามด้วยแหล่งที่มาและฐานปลายทางโดยแต่ละรายการอยู่ในบรรทัดแยกต่างหาก สำหรับสตริงว่างให้เว้นบรรทัดแรกว่างไว้ อินพุตตัวอย่าง:

122
2
A

ลองออนไลน์

คำอธิบาย:

l       Get and interpret value from input.
A,s     Build the list of 64 "digits". Start with [0..9]
'[,     Build character sequence from \0 to Z.
_el     Lower case copy of the same sequence.
^       Symmetric set difference gives only letters from both sequences.
+       Concatenate with sequence of decimal digits, creating [0..9A..Za..z].
"<=>"   Remaining 4 characters.
+       Concatenate, resulting in full 64 character "digit" string.
:L      ... and store it in variable L for repeated use.
f#      Look up input characters in digit list.
Ll#     Get source base from input, and look up value in digit list.
b       Base conversion. This produces the input value.
Ll#     Get destination base from input, and look up value in digit list.
:K;     Store it in variable K for use in loop, and pop it off stack.
{       Loop for generating output digits.
  (       Decrement to get ceiling minus 1 after division.
  Kmd     Calculate divmod of current value with destination base.
  )       Increment mod to get 1-based value for digit.
  L=      Look up digit character for digit value.
  \       Swap. Digit stays on stack for output, remaining value is processed
          in next loop iteration until it is 0.
}h      End of loop for generating output digits.
s       Final value is 0. Covert it to a string.
-       And subtract it from second but last value. This eliminates the 0,
        as well as the second but last value if it was a \0 character.
]       Wrap digits in array.
W%      Reverse array, to get result from MSB to LSB.

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