Dizelerle Temel Dönüşüm


16

Giriş

Geçmişte burada birkaç temel dönüşüm zorluğumuz var, ancak rastgele uzunluk sayılarını (yani, tamsayı veri türünü aşacak kadar uzun olan sayıları) ele almak için tasarlanmamış pek çok şey yok ve bunlardan çoğu, karmaşık. Bunun gibi bir baz kod değişikliğini nasıl golf oynayabileceğini merak ediyorum.

Meydan okuma

Seçtiğiniz dilde, bir tabandaki bir dizeyi başka bir tabandaki dizeye dönüştürebilen bir program veya işlev yazın. Girdi, dönüştürülecek sayı (dize), tabandan (taban-10 sayı), tabana (taban-10 sayı) ve karakter kümesi (dize) olmalıdır. Çıktı dönüştürülen sayı (dize) olmalıdır.

Bazı detaylar ve kurallar aşağıdaki gibidir:

  • Dönüştürülecek sayı negatif olmayan bir tamsayı olacaktır (çünkü karakter kümesinde olabilir -ve .olabilir). Çıktı da öyle olacak.
  • Baştaki sıfırlar (karakter kümesindeki ilk karakter) kesilmelidir. Sonuç sıfırsa, tek bir sıfır basamağı kalmalıdır.
  • Desteklenen minimum taban aralığı, yazdırılabilir ascii karakterlerden oluşan 2 ila 95 arasındadır.
  • Dönüştürülecek sayının girdisi, karakter kümesi ve çıktının tümü dizgi veri türünden olmalıdır. Bazlar, base-10 tamsayı veri tipinden (veya tamsayı yüzer) olmalıdır.
  • Giriş numarası dizesinin uzunluğu çok büyük olabilir. Makul bir minimum ölçmek zordur, ancak en az 1000 karakteri işleyebilmesini ve iyi bir makinede 10 saniyeden daha kısa sürede 100 karakter girdisini tamamlamasını bekleyebilirsiniz (bu tür bir sorun için çok cömert, ancak istemiyorum hız odak).
  • Yerleşik temel değişikliği işlevlerini kullanamazsınız.
  • Karakter seti girişi, sadece tipik 0-9a-z ... vb. Değil, herhangi bir düzenlemede olabilir.
  • Yalnızca geçerli girdinin kullanılacağını varsayın. Hata işleme konusunda endişelenmeyin.

Kazanan, kriterleri yerine getiren en kısa kodla belirlenir. Bunlar en az 7 baz-10 gün içinde veya yeterli sayıda başvuru olduğunda / olduğunda seçilecektir. Beraberlik durumunda, daha hızlı çalışan kod kazanan olacaktır. Hız / performansta yeterince yakınsa, daha önce gelen cevap kazanır.

Örnekler

Kodunuzun işleyebilmesi için birkaç giriş ve çıkış örneği:

F("1010101", 2, 10, "0123456789")
> 85

F("0001010101", 2, 10, "0123456789")
> 85

F("85", 10, 2, "0123456789")
> 1010101

F("1010101", 10, 2, "0123456789")
> 11110110100110110101

F("bababab", 2, 10, "abcdefghij")
> if

F("10", 3, 2, "0123456789")
> 11

F("<('.'<)(v'.'v)(>'.'>)(^'.'^)", 31, 2, "~!@#$%^v&*()_+-=`[]{}|';:,./<>? ")
> !!~~~~~~~!!!~!~~!!!!!!!!!~~!!~!!!!!!~~!~!~!!!~!~!~!!~~!!!~!~~!!~!!~~!~!!~~!!~!~!!!~~~~!!!!!!!!!!!!~!!~!~!~~~~!~~~~!~~~~~!~~!!~~~!~!~!!!~!~~

F("~~~~~~~~~~", 31, 2, "~!@#$%^v&*()_+-=`[]{}|';:,./<>? ")
> ~

F("9876543210123456789", 10, 36, "0123456789abcdefghijklmnopqrstuvwxyz")
> 231ceddo6msr9

F("ALLYOURBASEAREBELONGTOUS", 62, 10, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
> 6173180047113843154028210391227718305282902

F("howmuchwoodcouldawoodchuckchuckifawoodchuckcouldchuckwood", 36, 95, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_-+=[{]}\\|;:'\",<.>/? ")
> o3K9e(r_lgal0$;?w0[`<$n~</SUk(r#9W@."0&}_2?[n

F("1100111100011010101010101011001111011010101101001111101000000001010010100101111110000010001001111100000001011000000001001101110101", 2, 95, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_-+=[{]}\\|;:'\",<.>/? ")
> this is much shorter

Bizde var keyfi uzunluk numaralarını çözmek için tasarlanmış bir tane vardı.
Peter Taylor

@PeterTaylor Dan dang, bir şekilde aramamda bunu kaçırdı. Yine de, yeterince farklı olduklarını iddia ediyorum. Diğeri varsayılan karakter seti, çok baytlı diziler, hata işleme ve diziden diziye dönüşüm içerir. Tüm bunlar cevaplarda çok daha büyük şişkinliğe katkıda bulunur ve farklı optimizasyonlara odaklanır. Bu meydan okuma çok daha kısaltılmıştır ve diğer meydan okumadan tamamen farklı bir kodla sonuçlanacaktır (çekirdek algoritmanın kısaltması).
Mwr247

@PeterTaylor Plus, diğer soru 4 yıl önce soruldu ve sadece iki geçerli cevap aldı (ve bir tanesi zaten kabul edildi, çarpmak için çok az neden). Topluluğun, bir öncekinden çok az etkisi olan ya da "tekrarlanabilirlik" duyguları ile bu zorluğun tadını çıkaracağına bahse girmeye hazırım.
Mwr247

7
Bu meydan okuma bir öncekine çok benzer olsa da, aslında bir öncekini bunun bir kopyası olarak kapatmaktan yanayım. Bu zorluk eskisinden çok daha net ve kalitelidir.
Mego

Biraz detay verebilir misiniz You cannot use built in change-of-base functions to convert the entire input string/number at once? Özellikle, girdiyi ara tabana dönüştürmek için yerleşik bir yöntem kullanabilir miyim? Daha sonra hedef tabana dönüştürmek için yerleşik bir yöntem kullanabilir miyim? Bir şey ister convert input with canonical form for given base; convert to base 10; convert to target base; convert back to specified character set with string replacementmisiniz?
Mego

Yanıtlar:


5

CJam, 34 bayt

0ll:Af#lif{@*+}~li:X;{XmdA=\}h;]W%

Giriş formatı input_N alphabet input_B output_Bher biri ayrı bir satırdadır.

Tüm test senaryolarını çalıştırın.

açıklama

0     e# Push a zero which we'll use as a running total to build up the input number.
l     e# Read the input number.
l:A   e# Read the alphabet and store it in A.
f#    e# For each character in the input number turn it into its position in the alphabet,
      e# replacing characters with the corresponding numerical digit value.
li    e# Read input and convert to integer.
f{    e# For each digit (leaving the base on the stack)...
  @*  e#   Pull up the running total and multiply it by the base.
  +   e#   Add the current digit.
}
~     e# The result will be wrapped in an array. Unwrap it.
li:X; e# Read the output base, store it in X and discard it.
{     e# While the running total is not zero yet...
  Xmd e#   Take the running total divmod X. The modulo gives the next digit, and
      e#   the division result represents the remaining digits.
  A=  e#   Pick the corresponding character from the alphabet.
  \   e#   Swap the digit with the remaining value.
}h
;     e# We'll end up with a final zero on the stack which we don't want. Discard it.
]W%   e# Wrap everything in an array and reverse it, because we've generated the 
      e# digits from least to most significant.

Bu aynı bayt sayısı için çalışır:

L0ll:Af#lif{@*+}~li:X;{XmdA=@+\}h;

Tek fark, yığıntaki her şeyi toplamak ve tersine çevirmek yerine bir dize oluşturmamızdır.


7

Piton 2 , 115 114 106 105 94 bayt

Golf önerileri hoş geldiniz. Çevrimiçi deneyin!

Düzenle: mbomb007 sayesinde -9 bayt. FlipTack sayesinde -2 bayt.

def a(n,f,t,d,z=0,s=''):
 for i in n:z=z*f+d.find(i)
 while z:s=d[z%t]+s;z/=t
 print s or d[0]

Ungolfed:

def arbitrary_base_conversion(num, b_from, b_to, digs, z=0, s=''):
    for i in num:
        z = z * b_from + digs.index(i)
    while z:
        s = digs[z % b_to] + s
        z = z / t
    if s:
        return s
    else:
        return d[0]

1
while z:s=d[z%t]+s;z/=t9 bayt tasarruf sağlar.
mbomb007

Sen koyabilirsiniz z=0ve s=''fonksiyon bildiriminde bayt kaydedin.
FlipTack

kullanılarak printyerine returnedilmektedir varsayılan olarak izin .
FlipTack

6

Ciddi, 50 bayt

0╗,╝,2┐,3┐,4┐╛`4└í╜2└*+╗`MX╜ε╗W;3└@%4└E╜@+╗3└@\WX╜

Hex Dökümü:

30bb2cbc2c32bf2c33bf2c34bfbe6034c0a1bd32c02a2bbb60
4d58bdeebb573b33c0402534c045bd402bbb33c0405c5758bd

Uzunluğuna rağmen bununla gurur duyuyorum. Neden? Çünkü ikinci denemede mükemmel çalıştı. Yazdım ve tam anlamıyla 10 dakika içinde hata ayıkladım. Genellikle Ciddi bir programda hata ayıklamak bir saat emeğidir.

Açıklama:

0╗                                                  Put a zero in reg0 (build number here)
  ,╝,2┐,3┐,4┐                                       Put evaluated inputs in next four regs
             ╛                                      Load string from reg1
              `         `M                          Map over its chars
               4└                                   Load string of digits
                 í                                  Get index of char in it.
                  ╜                                 Load number-so-far from reg0
                   2└*                              Multiply by from-base
                      +                             Add current digit.
                       ╗                            Save back in reg0
                          X                         Discard emptied string/list.
                           ╜                        Load completed num from reg0
                            ε╗                      Put empty string in reg0
                              W                W    While number is positive
                               ;                    Duplicate
                                3└@%                Mod by to-base.
                                    4└E             Look up corresponding char in digits
                                       ╜@+          Prepend to string-so-far.
                                                      (Forgetting this @ was my one bug.)
                                          ╗         Put it back in reg0
                                           3└@\     integer divide by to-base.
                                                X   Discard leftover 0
                                                 ╜  Load completed string from reg0
                                                    Implicit output.

3

GMP kütüphanesi ile C (fonksiyon) , 260

Bu umduğumdan daha uzun çıktı, ama işte zaten. mpz_*Şeyler gerçekten bayt çok yiyor. Denedim #define M(x) mpz_##x, ama bu 10 baytlık net bir kazanç sağladı.

#include <gmp.h>
O(mpz_t N,int t,char*d){mpz_t Q,R;mpz_inits(Q,R,0);mpz_tdiv_qr_ui(Q,R,N,t);mpz_sgn(Q)&&O(Q,t,d);putchar(d[mpz_get_ui(R)]);}F(char*n,int f,int t,char*d){mpz_t N;mpz_init(N);while(*n)mpz_mul_ui(N,N,f),mpz_add_ui(N,N,strchr(d,*n++)-d);O(N,t,d);}

İşlev F()giriş noktasıdır. Girdi dizesini mpz_tarka arkaya çarpma ilefrom -base ile işlemine dönüştürür ve basamak listesinde belirtilen basamağın dizinini ekler.

İşlev O(), yinelemeli bir çıkış işlevidir. Her özyineleme mpz_t,to bölünür. Bu, çıkış basamaklarını ters sırada verdiğinden, özyineleme, basamakların yığın üzerinde depolanmasına ve doğru sırada çıkmasına olanak tanır.

Test sürücüsü:

Okunabilirlik için satırsonu ve girinti eklendi.

#include <stdio.h>
#include <string.h>

#include <gmp.h>
O(mpz_t N,int t,char*d){
  mpz_t Q,R;
  mpz_inits(Q,R,0);
  mpz_tdiv_qr_ui(Q,R,N,t);
  mpz_sgn(Q)&&O(Q,t,d);
  putchar(d[mpz_get_ui(R)]);
}
F(char*n,int f,int t,char*d){
  mpz_t N;
  mpz_init(N);
  while(*n)
    mpz_mul_ui(N,N,f),mpz_add_ui(N,N,strchr(d,*n++)-d);
  O(N,t,d);
}

int main (int argc, char **argv) {
  int i;

  struct test_t {
    char *n;
    int from_base;
    int to_base;
    char *digit_list;
  } test[] = {
    {"1010101", 2, 10, "0123456789"},
    {"0001010101", 2, 10, "0123456789"},
    {"85", 10, 2, "0123456789"},
    {"1010101", 10, 2, "0123456789"},
    {"bababab", 2, 10, "abcdefghij"},
    {"10", 3, 2, "0123456789"},
    {"<('.'<)(v'.'v)(>'.'>)(^'.'^)", 31, 2, "~!@#$%^v&*()_+-=`[]{}|';:,./<>? "},
    {"~~~~~~~~~~", 31, 2, "~!@#$%^v&*()_+-=`[]{}|';:,./<>? "},
    {"9876543210123456789", 10, 36, "0123456789abcdefghijklmnopqrstuvwxyz"},
    {"ALLYOURBASEAREBELONGTOUS", 62, 10, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"},
    {"howmuchwoodcouldawoodchuckchuckifawoodchuckcouldchuckwood", 36, 95, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_-+=[{]}\\|;:'\",<.>/? "},
    {"1100111100011010101010101011001111011010101101001111101000000001010010100101111110000010001001111100000001011000000001001101110101", 2, 95, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_-+=[{]}\\|;:'\",<.>/? "},
    {0}
  };

  for (i = 0; test[i].n; i++) {
    F(test[i].n, test[i].from_base, test[i].to_base, test[i].digit_list);
    puts("");
  }

  return 0;
}

3

JavaScript (ES6), 140 bayt

(s,f,t,m)=>[...s].map(c=>{c=m.indexOf(c);for(i=0;c||i<r.length;i++)r[i]=(n=(r[i]|0)*f+c)%t,c=n/t|0},r=[0])&&r.reverse().map(c=>m[c]).join``

@ Mwr247 kodundan farklı olarak (her seferinde s'yi t'ye bölmek için base-f aritmetiği kullanan, her bir geri kalanını toplarken) Her seferinde cevabı f ile çarpıp her s basamağını ekleyerek baz-t aritmetiği kullanıyorum.

Ungolfed:

function base(source, from, to, mapping) {
    result = [0];
    for (j = 0; j < s.length; s++) {
        carry = mapping.indexOf(s[j]);
        for (i = 0; carry || i < result.length; i++) {
            next = (result[i] || 0) * from + carry;
            result[i] = next % to;
            carry = Math.floor(next / to);
         }
    }
    string = "";
    for (j = result.length; j --> 0; )
        string += mapping[result[j]];
    return string;
}

3

Yakut, 113 112 105 98 97 95 87 bayt

Python cevabımı bir şekilde iki kez gönderdim (bir şekilde), işte bir Ruby cevabı. Manatwork sayesinde yedi bayt daha , Martin Büttner sayesinde bir bayt daha ve cia_rana sayesinde 8 bayt daha .

->n,f,t,d{z=0;s='';n.chars{|i|z=z*f+d.index(i)};(s=d[z%t]+s;z/=t)while z>0;s[0]?s:d[0]}

Ungolfed:

def a(n,f,t,d)
  z=0
  s=''
  n.chars do |i|
    z = z*f + d.index(i)
  end
  while z>0 
    s = d[z%t] + s
    z /= t
  end
  if s[0]   # if n not zero
    return s
  else
    return d[0]
  end
end

s=d[z%t]+s;z/=tBunun yerine kullanıma ne dersiniz z,m=z.divmod t;s=d[m]+s?
cia_rana

3

APL, 10 bayt

{⍺⍺[⍵⍵⍳⍵]}

Bu bir APL operatörüdür. APL olarak, ve süre değerleri iletmek için kullanılır ⍵⍵ve ⍺⍺genellikle işlevleri geçirmek için kullanılır. Burada 3 argümanım var. ⍺⍺sol argüman, ⍵⍵"iç" sağ argüman ve "dış" sağ argüman.

Temelde: ⍺(⍺⍺{...}⍵⍵)⍵

Sonra tek gereken girdi dizesinin "from" tablosundaki pozisyonlarını bulmak ve sonra []bu pozisyonlarla "to" tablosuna indekslemek için kullanmaktır .

Misal:

    ('012345'{⍺⍺[⍵⍵⍳⍵]}'abcdef')'abcabc'
012012

2

JavaScript (ES6), 175 bayt

(s,f,t,h)=>eval('s=[...s].map(a=>h.indexOf(a));n=[];while(s.length){d=m=[],s.map(v=>((e=(c=v+m*f)/t|0,m=c%t),e||d.length?d.push(e):0)),s=d,n.unshift(m)}n.map(a=>h[a]).join``')

Örnekleri oluşturmak için yaptığım kişiyi gönderebilmemin artık yeterince uzun olduğunu düşündüm. Daha sonra biraz daha iyi denemek ve golf olabilir.


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.