Tüm bijektif tabanınız bize aittir


25

Arka fon

Bir örten baz b sayılandırma , b bir pozitif tamsayıdır, yapar kullanımı bir örten konumsal notasyondur b ilişkili değerlere sahip sembollerin 1 için b .

Önyargılı olmayan karşıtının aksine, hiçbir sembolün değeri 0 değildir . Bu yolla, negatif olmayan her bir tamsayı n , bibif baz b'de benzersiz bir temsildir .

Popüler bijektif sayılar, unary, bibektif taban 2 (bzip2'nin çalışma uzunluğu kodlamasında kullanılır ) ve bibektif taban 26'yı (elektronik tablolardaki sütunları numaralandırmak için kullanılır) içerir.

Tanım

Bu mücadelede, sembollerin M kümesini şu şekilde tanımlarız:

123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz<=>

ve i ( M) 'nin doğal sayısına, i (' 1 ') = 1,…, i ('> ') = 64 olduğu bir fonksiyon .

Bir baz verilen b arasında 1 ve 64 (her ikisi dahil), her bir negatif olmayan bir sayıyı bu tanımlar , n dize karşılık gelir , bir k ... bir 0 sembollerinden oluşan M , öyle ki n = b k i (a k +) … + B 0 i ( 0 ) .

Bu yazışma iyi tanımlanmış ve bibekti. Boş toplamı olarak tanımlanır yana 0 , tam sayı 0 boş bir dize kodlanabilir.

Görev

Giriş olarak üç dizeyi kabul edin:

  • 1 ila 64 arasında bir giriş tabanı b olup , bir bijektif baz 64 dize olarak kodlanmıştır .

  • Bir münferit temel b dizesi olarak kodlanan negatif olmayan bir tam sayı n .

  • 1 ila 64 arasında bir çıkış tabanı B , bir bijektif baz 64 dize olarak kodlanmıştır .

Bu üç giriş göz önüne alındığında, n'yi bir bijektif temel B dizesi olarak kodlayın .

Test durumları

Tüm test senaryoları girişi b , n , B sırasına göre belirtir .

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"

kurallar

  • Üç dizeyi, istediğiniz bir tek karakter sınırlayıcıları ile birleştirilen veya ayıran bir dizge dizisi, dizge gösterimi gibi herhangi bir uygun sırayla okuyabilirsiniz.

  • Çıktıyı STDOUT konumuna yazdırmayı seçerseniz, sadece sembolleri ve (isteğe bağlı olarak) izleyen bir yeni satırı yazdırabilirsiniz.

  • Her türlü temel dönüşüm yerleşik yapılara izin verilir.

  • Standart kuralları geçerlidir.

Yanıtlar:


6

CJam, 43

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

3 byte Dennis yardımı ile yok edildi :) Çevrimiçi deneyin

Açıklama:

Giriş, bnBtek bir dizgide birleştirilerek alınır .

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

İlk temel dönüşüm için normal temel dönüşüm operatörünü kullanabilirsiniz. Şimdi çözümümde sahip olduğum tüm kodları kullandığım için kendimi aptal hissediyorum. :) Bunun, taban aralığının dışındaki değerlerle çalışacağının farkında değildim. Eh, görüşte, olmamasının iyi bir nedeni yok.
Reto Koradi

@RetoKoradi evet, bunu yapabilirsiniz; bir gün belgelenecek :)
aditsu

Temel dönüşümü kullanmak için çözümümü değiştirmem sorun olur mu? Normalde diğer çözümlerden fikir almaktan kaçınmaya çalışırım. Fakat benimkiler böylesine optimal bir yaklaşımla ayakta durmamı gerçekten zorluyor. Çözümünüzün hala daha kısa sürmesi muhtemeldir.
Reto Koradi

@RetoKoradi sorun değil, devam edin
aditsu

4

Pip, 84 80 78 bayt

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

Pip için GitHub deposu

Wikipedia makalesinden uyarlanmış algoritmalar. İşte biraz eskimiş eski sürümün açıklaması:

                 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)

Örnek çalışma:

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

4

Octave, 166 bayt

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

Çok hatlı versiyon:

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

Bir karakteri bir indeks değerine dönüştürmek için bir harita oluşturmak yerine, Nascii değerleri için ters arama tablosunu oluşturdum 1..'z've onu uygun değerlerde indekslerle doldurdum.

polyval denklemi değerlendirir

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

ondalık dönüştürülmüş girdi değerinin katsayılar vektörü cve orijinal baz olarak kullanılması x. (Maalesef, Octave's base2dec()sembolleri normal sınırların dışına çıkarır.)

10 tabanındaki giriş değerine sahip olduğumuzda, yeni tabandaki değerin hesaplanması kolaydır.

Test sürücüsü:

% 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);

Sonuçlar:

>> bijecttest

1112
A
1111111111
RS
>>

2

Perl, 261 248 229 bayt

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)

çok satırlı, halkalar çözülürken:

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)

tbir sayıyı verilen bir kaidenin bir kaideli katar dizisinden ayrıştırma işlevidir. rbir sayının verilen bir kaidenin bir bijectif-base dizesini üretme işlevidir. Virgülle ayrılmış 3 parametre stdin'den ayrıştırılır ve işlevler gerektiği gibi çağrılır.

Pozitif bir sayıyı bir bijektif temel dizgisine dönüştürmek normal bir tabana benzer. Ancak normal bir üs için böyle bir şey yapacağınız yerde:

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'u 0 yerine base - 1 yerine 1 - base aralığında olacak şekilde ayarlarsınız:

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 bayt

Kesinlikle golf oynayabilir. Dizelerin öğe ataması olmaması ve listelerin olmasından nefret ediyorum find. Şimdi sahip olduğum hızlı düzeltmeden daha iyi bir yol arayacağım.

Benim yöntemim girdiyi ondalık sayıya, sonra çıktı tabanına dönüştürmek, sonra da bunu bijektif tabanına dönüştürmektir.

Düzenleme : Unary'e dönüştürülürken programımın çalışmadığını buldu. Düzeltmek için 13 bayta mal oldu e=F(o)<2, vb.

Burada dene

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 evcil hayvan peeling'inle aynı fikirdeyim.
DLosc

@DLosc Golf yardımınız için teşekkürler.
mbomb007 18

Bu kod bowlingi mi? : P
Doktoru

Listeleri .index()yöntem var .. Neden bulmak yerine bunu kullanmıyorsunuz? Ayrıca, kaydetme F(b)ve F(o)değişkenler yerine, yalnızca bir kez kullanırsınız, bu yüzden gerektiğinde onları alt yapın. Son olarak, 'n'[2::5]daha kısadır ''.join(n)(geri tepmeler için kesme işaretlerini değiştirin).
Kade

Ayrıca, bunun fazla karmaşık olduğunu düşünüyorum. M dizgesindeki bir mermi üssünden b ondalık basamağa dönüşüm 35-40 bayttan fazla sürmemelidir. Bir dizi bijektif üs B'nin ondalık değeri bundan daha fazlası olmayacak.
Kade

2

Python 2, 167 Bayt

Burada gerçekten özel numaralar yok [2::5], karakter kümesini daha düşük bayt sayısında almak için dilimleme dışında .

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

Testler:

"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 bayt

En son sürüm, @ aditsu'nun çözümünü görene kadar düşünemediğim kaynak tabanından dönüştürme için CJam baz dönüştürme operatörünü kullanıyor. Aynı zamanda, @Dennis tarafından "digit" string'ini ( /codegolf//a/54348/32852 ) ve sohbette paylaşılan diğer bazı fikirleri uygulamak için de geçerlidir .

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

Giriş biçimi, her biri ayrı bir satırda olmak üzere kaynak ve hedef taban tarafından takip edilen değerdir. Boş dize için ilk satırı boş bırakın. Örnek giriş:

122
2
A

Çevrimiçi deneyin

Açıklama:

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.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.