Unicode UTF Dönüştürücü


17

Amaç, UTF SSS bölümünde verilen resmi Unicode kodlamaları arasında tam uyumlu bir dönüştürücü oluşturmaktır . Bu Unicode merkezli olduğu göz önüne alındığında, dahil kodlamalar mümkün olan en iyi kullanarak en düşük bayt sayısı ile cevap kabul edecek (belki APL programlamak sürece muhtemelen UTF-8 olacak). Uzun yazı için özür dilerim, ancak birçoğu resmi şartnamede (pdf, bölüm 3.9 D90 - D92) veya Wikipedia'da da erişilebilen kodlamaları açıklıyor .

Özellikler

Seçim diliniz herhangi bir zamanda bir gereksinimi tam olarak karşılayamıyorsa, bunu verilen kuralların ruhuna yapışan bir şeyle değiştirin. Örneğin. her dilde yerleşik diziler, işlevler vb. bulunmaz.

  • Dize kitaplıkları / işlevleri kullanma veya kitaplıkları / işlevleri kodlama yok. Bu kod golfünün amacı dönüştürücüyü bit / bayt manipülasyonu kullanarak uygulamaktır. Dizeleri kendi kapasitelerinde karakter veya bayt dizisi olarak kullanmaya izin verilir. Oh, ve dönüşümü yapan OS çağrıları da yok.

  • Dönüştürücü üç parametre alacak bir fonksiyondur: kodlanmış giriş dizesini temsil eden bir bayt dizisi ve sayı olarak temsil edilen "giriş" ve "çıkış" kodlamaları. Keyfi olarak UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE, and UTF32LE, bu sırayla 0 ila 6 arasında sayılar atayacağız . Numaranın olup olmadığını kontrol etmeye gerek yoktur, < 0ya da > 6bu parametrelerin doğru olduğunu varsayacağız. Dönüştürücü, istenen çıkış kodlamasında geçerli bir bayt dizisi döndürür.

  • Null karakterini ( U+0000) dize sonlandırıcı olarak kullanacağız . Bundan sonraki hiçbir şey önemli değil. Giriş dizisinin bir yerde boş karakterine sahip olduğunu varsayacağız, böylece sınır kontrolü yapmanız gerekmez.

  • Gereğince SSS giriş bayt dizisi onun beyan kodlama için geçersizse, biz bir hata olarak bildirmelidir. Bunu aşağıdaki yollardan biriyle yapacağız: programı çökertme, bir istisna atma, null döndürme veya ilk dört baytın tümü 0 olan bir dizi döndürme (böylece U+0000her kodlamada olduğu gibi tanınabilir ).

Kodlamalar

Resmi şartnamelere uyulmalıdır, ancak Wikipedia kodlamalar hakkında iyi bir açıklama sağlar (ve doğru olduğuna inandığım kadarıyla) ve tamlık için burada özetleyeceğim. UTF-16 ve UTF-32'nin endianite için varyantları olduğuna dikkat edin .

UTF-32, UTF-32LE, UTF-32BE

En basit kodlama olan her kod noktası, sayısal değerine eşit 4 baytta kodlanır. LE / BE endianlığı temsil eder (küçük endian / büyük endian).

UTF-16, UTF-16LE, UTF-16BE

Kaynak kodları U+0000 - U+FFFFsayısal değerine eşit 2 bayt olarak kodlanır. Büyük değerler, ayrılmış değerler olan bir çift taşıyıcı kullanılarak kodlanır U+D800 - U+DFFF. Bu nedenle, daha büyük noktaları kodlamak U+FFFFiçin aşağıdaki algoritma kullanılabilir (utanmadan Wikipedia'dan kopyalanır ):

  • 0x010000 kod noktasından çıkarılır ve 0..0x0FFFFF aralığında 20 bit bir sayı kalır.
  • 0xD800'e ilk on bit (0..0x03FF aralığında bir sayı) eklenir ve 0xD800..0xDBFF [...] aralığında olacak ilk kod birimini veya potansiyel vekili temsil eder.
  • En düşük on bit (ayrıca 0..0x03FF aralığında) 0xDC00'e eklenir ve 0xDC00..0xDFFF aralığında olacak ikinci kod birimi veya iz vekilini verir [...].

UTF-8

Kaynağından gelen kod noktaları U+0000 - U+007F, sayısal değerine eşit 1 bayt olarak kodlanır. Gönderen U+0080 - U+07FFonlar kodlanmıştır 110xxxxx 10xxxxxx, U+0800 - U+FFFFolduğu 1110xxxx 10xxxxxx 10xxxxxx, daha yüksek değerlerdir 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx. xSitesindeki bir kod noktası sayısal değerden bittir.

BOM

Bayt sırası işareti (BOM, U+FEFF) endianizmi belirtmek için ilk kod noktası olarak kullanılır. Malzeme Listeleri ile ilgili SSS yönergelerini izleyerek Malzeme Listesi aşağıdaki gibi kullanılacaktır: Çünkü UTF-8, UTF-16 and UTF-32isteğe bağlıdır. Malzeme Listesinde yoksa UTF-16veya UTF-32büyük endian olduğu varsayılır. BOM olmamalıdır görünür UTF-16LE, UTF-16BE, UTF-32LE and UTF-32BE.

Geçersiz UTF'ye Neden Olan Yaygın Tuzaklar

Çeşitli şeyler bir bayt dizisinin geçersiz UTF olmasına neden olabilir.

  • UTF-8 ve UTF-32: Doğrudan yedek kod noktalarını ( U+D800 - U+DFFF) veya daha büyük kod noktalarını doğrudan kodlama U+10FFFF.
  • UTF-8: Birçok geçersiz bayt dizisi.
  • UTF-16: Eşleştirilmemiş veya yanlış eşleştirilmiş taşıyıcılar.
  • BOM: Kodlama bölümünde belirtildiği gibi kullanılmalıdır. Çıktı alırken UTF-16veya UTF-32(doğal bir endianness belirtilmediğinde) seçebileceğinizi, ancak küçük endian ile Malzeme Listesini eklemeniz gerektiğini unutmayın .

Karakter olmayan ve atanmamış kod noktalarının (her ikisi de taşıyıcılardan farklı) normal karakterler gibi ele alınacağını unutmayın.


"Hayır dize kütüphaneleri / fonksiyonları kullanarak, veya kodlama kütüphaneleri / fonksiyonları." Gerçek yerleşiklere ne dersiniz? APL'de ''⎕R''⍠'InEnc' 'UTF16BE' 'OutEnc' 'UTF8-BOM',.
Adam

2
@NBZ Bu zorluğun amacı, sağladıkları davranışı uygulamak olduğundan bunlara izin verilmez.
DPenner1

Yanıtlayanlara not: Bu soruyu az çok terk ettim, ancak yakın zamanda yenilenen ilgi göz önüne alındığında, önümüzdeki günlerde cevapları incelemek için biraz zaman alacağım.
DPenner1

Yanıtlar:


3

C ++, (UTF-8) 971 bayt

#include<cstdint>
using u=uint8_t;using U=uint32_t;U i,o,x,b,m;U R(u*&p){x=*p++;if(!i){m=0;while(128>>m&x)++m;if(m>1)for(x&=127>>m;--m;)x=x<<6|((*p&192)-128?~0:*p++&63);return m?x=~0:x;}else if(i<3){x<<=8;x+=*p++;}else if(i<4){x+=*p++<<8;}else if(i<6){x<<=24;x+=*p++<<16;x+=*p++<<8;x+=*p++;}else{x+=*p++<<8;x+=*p++<<16;x+=*p++<<24;}return x;}U r(u*&p){U x0=R(p);if(i&&i<4&&x>>10==54)x=R(p)>>10==55?(x0<<10)+x-56613888:~0;if(!b++){if(x==65279)if(!i||i%3==1)r(p);else x=~0;else if(x==65534&&i==1)i=3,r(p);else if(x==4294836224&&i==4)i=6,r(p);}return x>1114111||x>>11==27?x=~0:x;}void w(U x,u*&p){if(!o){if(x<128)*p++=x;else{for(m=0;~63<<m&x;m+=6);for(*p++=~127>>m/6|x>>m;m;)*p++=128|x>>(m-=6)&63;}}else if(o<4&&x>65535)x-=65536,w(55296|x>>10,p),w(56320|x&1023,p);else if(o<3)*p++=x>>8,*p++=x;else if(o<4)*p++=x,*p++=x>>8;else if(o<6)*p++=x>>24,*p++=x>>16,*p++=x>>8,*p++=x;else*p++=x,*p++=x>>8,*p++=x>>16,*p++=x>>24;}int t(u*&p,u*&q){for(b=0,x=1;U(x+x);)w(r(p),q);return x;}

Aşağıdaki okunabilir program, aşağıdaki Perl komutuyla filtrelenerek yukarıdaki forma yoğunlaştırılabilir:

perl -p0 -e 's!//.*!!g;s/\s+/ /g;s/ \B|\B //g;s/0x[\da-f]+/hex($&)/ige;s/#include<[^<>]+>/\n$&\n/g;s/^\n+//mg'

Yukarıdaki komut

  • yorumları kaldırır
  • gereksiz boşlukları kaldırır
  • onaltılı değişmezleri ondalık sayıya dönüştürür
  • etrafında yeni satır geri getiriyor #includehatları

Okunabilir kod

#include <cstdint>
using u = uint8_t;
using U = uint32_t;

U   i,                          // input encoding
    o,                          // output encoding
    x,                          // last read value
    b,                          // char count(BOM only valid when b==0)
    m;                          // temporary variable for measuring UTF-8

//   Encodings:
// 0 UTF-8
// 1 UTF-16
// 2 UTF-16BE
// 3 UTF-16LE
// 4 UTF-32
// 5 UTF-32BE
// 6 UTF-32LE

// Read a character or UTF-16 surrogate
U R(u*& p) {
    x = *p++;
    if (!i) { // UTF-8
        m=0; while (128>>m&x) ++m; // how many bytes?
        if (m>1) for (x&=127>>m; --m; ) x = x<<6 | ((*p&192)-128?~0:*p++&63);
        return m ? x=~0 : x;
    } else if (i<3) { // UTF-16, UTF-16BE
        x<<=8; x+=*p++;
    } else if (i<4) { // UTF-16LE
        x+=*p++<<8;
    } else if (i<6) { // UTF-32, UTF-32BE
        x<<=24; x+=*p++<<16; x+=*p++<<8; x+=*p++;
    } else { // UTF-32LE
        x+=*p++<<8; x+=*p++<<16; x+=*p++<<24;
    }
    return x;
}

// Read a character, combining surrogates, processing BOM, and checking range
U r(u*& p) {
    U x0 = R(p);
    if (i && i<4 && x>>10==54)
        x = R(p)>>10==55 ? (x0<<10)+x-56613888: ~0; // 56613888 == 0xd800<<10 + 0xdc00 - 0x10000
    if (!b++) {                 // first char - is it BOM?
        if (x==0xFEFF)
            if (!i || i%3==1)
                r(p); // BOM in UTF-8 or UTF-16 or UTF-32 - ignore, and read next char
            else
                x = ~0; // not allowed in these modes
        else if (x==0xFFFE && i==1)
            i=3,r(p); // reversed BOM in UTF-16 - change to little-endian, and read next char
        else if (x==0xFFFE0000 && i==4)
            i=6,r(p); // reversed BOM in UTF-32 - change to little-endian, and read next char
    }
    return x>0x10ffff || x>>11==27 ? x=~0 : x;
}


// Write character(assumed in-range)
void w(U x, u*& p) {
    if (!o) { // UTF-8
        if (x<128) *p++=x;        // ASCII
        else {
            for (m=0; ~63<<m&x; m+=6); // how many bits?
            for (*p++=~127>>m/6|x>>m; m; ) *p++ = 128|x>>(m-=6)&63;
        }
    } else if (o<4 && x>65535)  // UTF-16 surrogate
        x-=65536, w(0xD800|x>>10,p), w(0xDC00|x&0x3FF,p);
    else if (o<3)  // UTF-16, UTF-16BE
        *p++=x>>8, *p++=x;
    else if (o<4)  // UTF-16LE
        *p++=x, *p++=x>>8;
    else if (o<6)  // UTF-32, UTF-32BE
        *p++=x>>24, *p++=x>>16, *p++=x>>8, *p++=x;
    else  // UTF-32LE
        *p++=x, *p++=x>>8, *p++=x>>16, *p++=x>>24;
}

// Transcode
int t(u*& p, u*& q)                  // input, output
{
    for (b=0,x=1;U(x+x);)    // exit condition is true only for x==-x, i.e. 0 and ~0
        w(r(p),q);
    return x;
}

Çağrılacak fonksiyonudur t()giriş ve çıkış kodlamaları global değişkenler içinde geçirilen, ive o, sırasıyla, ve pgiriş bayt, işaret gerekir boş sonlandırılmış olabilir. qüzerine yazılacak ve sonuç için yeterince büyük olması gereken çıktı arabelleğine işaret eder - arabellek taşmasını engelleme girişimi yoktur.

Umarım kod yorumları yeterince açıklayıcıdır - bunlardan birinin çok şifreli olup olmadığını aşağıda sorun (ama önce çaba gösterin!).

Bu cevabı geliştirirken önemli bir test paketi hazırladım; Diğer katılımcıların yararına ve gereksinimleri yorumladığımı belgelemek için aşağıya ekliyorum:

Test fonksiyonları

#include <vector>
#include <iostream>

std::ostream& operator<<(std::ostream& out, const std::vector<u>& v)
{
    out << "{ ";
    for (int i: v) out << i << " ";
    out << "}";
    return out;
}

int test_read(int encoding, std::vector<u> input, U expected)
{
    b = 0;
    i = encoding;
    auto d = input.data();
    U actual = r(d);
    if (actual == expected) return 0;
    std::cerr << std::hex << "Decoding " << encoding << "; " << input << " gave " << actual
              << " instead of " << expected << std::endl;
    return 1;
}

int test_write(int encoding, U input, std::vector<u> expected)
{
    o = encoding;
    u buf[20], *p = buf;
    w(input, p);
    std::vector<u> actual(buf,p);
    if (expected == actual) return 0;
    std::cerr << std::hex << "Encoding " << encoding << "; " << input << " gave " << actual
              << " instead of " << expected << std::endl;
    return 1;
}

int test_transcode(int ienc, std::vector<u> input, int oenc, std::vector<u> expected)
{
    b = 0;
    i = ienc; o = oenc;
    u buf[200], *p = buf, *d = input.data();
    int result = t(d, p);
    std::vector<u> actual(buf,p);
    if (result ? expected.empty() : expected == actual) return 0;
    std::cerr << std::hex << "Encoding " << ienc << " to " << oenc << "; " << input << " gave " << actual
              << " instead of " << expected << std::endl;
    return 1;
}

Test odası

static const U FAIL = ~0;
int main() {
    int e = 0;                        // error count
    // UTF-8
    e += test_read(0, { 128 }, FAIL); // unexpected continuation
    e += test_read(0, { 128, 1 }, FAIL);
    e += test_read(0, { 128, 128 }, FAIL);
    e += test_read(0, { 192, 192 }, FAIL); // start without continuation
    e += test_read(0, { 192, 0 }, FAIL);
    e += test_read(0, { 224, 0 }, FAIL);
    e += test_read(0, { 224, 192 }, FAIL);
    e += test_read(0, { 0xf4, 0x90, 128, 128 }, FAIL); // Unicode maximum+1

    e += test_read(0, { 127 }, 127);
    e += test_read(0, { 192, 129 }, 1); // We accept overlong UTF-8
    e += test_read(0, { 0xc2, 128 }, 128);
    e += test_read(0, { 224, 128, 129 }, 1);
    e += test_read(0, { 0xef, 128, 128 }, 0xF000);
    e += test_read(0, { 0xef, 191, 191 }, 0xFFFF);
    e += test_read(0, { 0xf4, 128, 128, 128 }, 0x100000);
    e += test_read(0, { 0xf4, 0x8f, 191, 191 }, 0x10FFFF); // Unicode maximum

    e += test_read(0, { 0xEF, 0xBB, 0xBF, 127 }, 127); // byte-order mark

    e += test_write(0, 0, { 0 });
    e += test_write(0, 127, { 127 });
    e += test_write(0, 128, { 0xc2, 128 });
    e += test_write(0, 255, { 0xc3, 191 });
    e += test_write(0, 0xFFFF, { 0xef, 191, 191 });
    e += test_write(0, 0x10FFFF, { 0xf4, 0x8f, 191, 191 });

    // UTF-16
    e += test_read(1, { 0, 1 }, 1);
    e += test_read(1, { 0xd8, 0, 0xdc, 1 }, 0x10001);
    e += test_read(1, { 0xdb, 0xff, 0xdf, 0xff }, 0x10ffff);

    e += test_read(1, { 0xd8, 0, 0xd8, 1 }, FAIL); // mismatched surrogate
    e += test_read(1, { 0xd8, 0, 0, 1 }, FAIL); // mismatched surrogate
    e += test_read(1, { 0xdc, 0 }, FAIL);

    e += test_write(1, 1, { 0, 1 });
    e += test_write(1, 256, { 1, 0 });
    e += test_write(1, 0xffff, { 255, 255 });
    e += test_write(1, 0x10001, { 0xd8, 0, 0xdc, 1 });
    e += test_write(1, 0x10ffff, { 0xdb, 0xff, 0xdf, 0xff });

    // UTF-16LE
    e += test_write(3, 1, { 1, 0 });
    e += test_write(3, 256, { 0, 1 });
    e += test_write(3, 0x10001, { 0, 0xd8, 1, 0xdc });
    e += test_write(3, 0x10fffe, { 0xff, 0xdb, 0xfe, 0xdf });

    // UTF-16 byte-order mark
    e += test_read(1, { 0xFE, 0xFF, 0x0, 1 }, 1); // byte-order mark
    e += test_read(1, { 0xFF, 0xFE, 1, 0x0 }, 1); // reversed byte-order mark
    // disallowed byte-order marks
    e += test_read(2, { 0xFE, 0xFF }, FAIL);
    e += test_read(3, { 0xFF, 0xFE }, FAIL);
    // reversed byte-order mark is an unassigned character - to be treated like regular character, according to question
    e += test_read(2, { 0xFF, 0xFE }, 0xfffe);
    e += test_read(3, { 0xFE, 0xFF }, 0xfffe);

    // UTF-32
    e += test_read(4, { 0, 0, 0, 1 }, 1);
    e += test_read(4, { 1, 0, 0, 0 }, FAIL);
    e += test_write(4, 1, { 0, 0, 0, 1 });
    e += test_write(4, 0x10203, { 0, 1, 2, 3 });

    // UTF-32LE
    e += test_read(6, { 0, 0, 0, 1 }, FAIL);
    e += test_read(6, { 1, 0, 0, 0 }, 1);

    // UTF-32 byte-order mark
    e += test_read(4, { 0, 0, 0xFE, 0xFF,  0, 0, 0, 1 }, 1); // byte-order mark
    e += test_read(4, { 0xFF, 0xFE, 0, 0,  1, 0, 0, 0 }, 1); // reversed byte-order mark
    // disallowed byte-order marks
    e += test_read(5, { 0, 0, 0xFE, 0xFF }, FAIL);
    e += test_read(5, { 0xFF, 0xFE, 0, 0 }, FAIL);
    e += test_read(6, { 0, 0, 0xFE, 0xFF }, FAIL);
    e += test_read(6, { 0xFF, 0xFE, 0, 0 }, FAIL);

    e += test_transcode(1, { 1, 2, 0xFE, 0xFF, 0, 0 }, // That's not a BOM; it's a zwnj when not the first char
                        1, { 1, 2, 0xFE, 0xFF, 0, 0 });
    e += test_transcode(1, { 0xFF, 0xFE, 1, 2, 0, 0 }, // reversed byte-order mark implies little-endian
                        1, { 2, 1, 0, 0 });
    e += test_transcode(4, { 0xFF, 0xFE, 0, 0, 1, 2, 0, 0, 0, 0 }, // reversed BOM means little-endian
                        4, { 0, 0, 2, 1, 0, 0, 0, 0 });
    e += test_transcode(1, { 0xdb, 0xff, 0xdf, 0xff, 0, 0 }, // U+10ffff UTF-16 to UTF-8
                        0, { 0xf4, 0x8f, 191, 191, 0 });

    return e;
}

Dang .. C ++ Python'u yendi.
TickTock

5

Python - 1367 UTF-8 karakter

Peki! Bu, tüm özellikleri anlamak ve uygulamak için gereken çok fazla iş nedeniyle son derece zor bir soruydu, ancak doğru bir uygulamaya sahip olduğumu düşünüyorum.

O,P,Q,R=65536,128,b'\xff\xfe\x00\x00',63
def A(x,y):assert x;return y
def B(x):
    o,c=[],0
    for b in x:
        if c:c,v=c-1,A(127<b<192,v<<6)|(b-P)
        else:
            c,v=(b>127)+(b>223)+(b>239),b
            if b>127:v=A(191<b<248,b&(R>>c))
        o+=[v][c:]
    return o[o[0]in(65279,O-2):]
def C(k):
    def o(x,s=None):
        for a,b in zip(x[k::2],x[1-k::2]):
            d=a|(b<<8)
            if s!=None:yield(A(56319<d<57344,d-56320)|(s<<10))+O;s=None
            elif 55295<d<57344:s=A(s<1024,d-55296)
            else:yield d
    return o
def D(x):n=(2,3,1)[[Q[:2],Q[1::-1],x[:2]].index(x[:2])];return C(n&1)(x[n&2:])
E=lambda a,b,c,d:lambda x:[L|(l<<8)|(m<<16) for L,l,m in zip(x[a::4],x[b::4],x[c::4])]
def F(x):n,m=((1,4),(-1,4),(-1,0))[[Q,Q[::-1],x[:4]].index(x[:4])];return E(*range(4)[::n])(x[m:])
S=lambda x,s=0,a=255:(x>>s)&a
G=lambda e:(e,)if e<P else(192|S(e,6),P|(e&R))if e<2048 else(224|S(e,12),P|S(e,6,R),P|(e&R))if e<O else(240|S(e,18),P|S(e,12,R),P|S(e,6,R),P|(e&R))
H=lambda e:(S(e,8),S(e))if e<O else(216|S(e-O,18),S(e-O,10),220+S((e-O)&1023,8),S(e-O))
I=lambda e:(S(e),S(e,8))if e<O else(S(e-O,10),216|S(e-O,18),S(e-O),220+S((e-O)&1023,8))
J=lambda e:(S(e,24),S(e,16),S(e,8),S(e))
K=lambda e:(S(e),S(e,8),S(e,16),S(e,24))
convert=lambda d,i,o:bytes(sum(map(L[o],N(list(M[i](d)))),()))if d else d
L,M=[G,H,H,I,J,J,K],[B,D,C(1),C(0),F,E(3,2,1,0),E(0,1,2,3)]
N=lambda d:[A(-1<x<1114112 and x&~2047!=55296,x)for x in d]

convertveri 'bayt' nesnesini, giriş kimliğini ve çıkış kimliğini alan işlevdir. İşe yarıyor gibi görünüyor - python kodlamada belirtilmediğinde BOM'ların biraz kırılmış gibi görünse de, python'un yerleşik kodlamasını test modları 1 ve 4 için kullanmak işe yaramaz.

Eğlenceli gerçek: Boyut da 555 16 veya 10101010101 2'dir .

Kod çözme için 773 karakter, kodlama için 452, doğrulama için 59 ve çeşitli parçalar için 83 karakter.


@TrangOul: Genellikle, önemsiz düzenlemeler (dil etiketleme gibi) üzerine kaşlarını çatar.
Zach Gates


Bu soru / cevap bir topluluk mutabakatı göstermez. Ağ genelinde, bunlar gibi önemsiz düzenlemeler hoş karşılanmaz. <1000 veya> 1000 rep kullanıcısı, içeriği veya biçimi açıkça iyileştirmedikleri sürece bu düzenlemeleri yapmamalıdır. Dil etiketleri, tek kelime düzeltmeleri / değişiklikleri vb. Gibi şeyleri düzenlemeye devam etmek en iyisidir. @Cat
Zach Gates

Ben :-( boyutu artık 0x555 olduğunu düşünüyorum Ama girintiler için bir boşluk kullanarak standart Python golf ucunu kullanarak daha yakın olabilir..
Toby Speight'ın

@TobySpeight şu anda 0x557, haklısın. Ve aslında, yayınlamak için boşluklara dönüştürülmesi gereken, ancak yine de bir karakter olarak sayılan sekmeler kullandım. Şansım olduğunda birkaç karakteri başka türlü tıraş edip edemeyeceğimi göreceğim.
Cel Skeggs

4

Python 3, 1138 bayt (UTF-8)

Bu nedenle, 14 saatlik uluslararası seyahatin bir golf mücadelesini bitirmek için harika bir fırsat olduğu ortaya çıkıyor ...

Dönüştürme işlevi C(). Bu çağrılar u(), v()ve w()kod çözme, ve U(), V()ve W()kodlamak için UTF-8, sırasıyla -16 ve -32. Kodlayıcıların hiçbiri bir ürün ağacı vermez, ancak tüm kod çözücüler bir tanesini doğru şekilde işler. Hata koşulları bir istisnayla sonuçlanır (genellikle a ZeroDivisionError, "aniden" işlevinin izniyle E()).

from struct import*
l=len
j=''.join
b=lambda c:[*bin(c)[2:]]
P,Q,i,o,z,Z='HI10><'
B=65279
O,F,H,L,X=1024,65536,55296,56320,57344
E=lambda:1/0
R=lambda y,e,c,n:unpack(([[z,Z][y[:n]==pack(Z+c,B)],e][l(e)])+c*(l(y)//n),y)
S=lambda d,e:B!=d[0]and d or e and E()or d[1:]
def u(y,d=(),p=0):
 while p<l(y):
  q=b(y[p])
  if l(q)>7:
   x=q.index(o);C=1<x<5and q[x+1:]or E();X=x+p;X>l(y)>E();p+=1
   while p<X:q=b(y[p]);C=l(q)>7and(i,o==q[:2])and(*C,*q[2:])or E();p+=1
   d=*d,int(j(C),2)
  else:d=*d,y[p];p+=1
 return S(d,0)
def T(p):
 q=b(p);C=()
 while l(q)not in(7,11,16,21):q=o,*q
 while l(q)>6:C=int(i+o+j(q[-6:]),2),*C;q=q[:-6]
 return bytes(p<128and[p]or[int(i*(7-l(q))+o+j(q),2),*C])
U=lambda c:b''.join(map(T,c))
def v(y,e=''):
 c=R(y,e,P,2);d=[];n=0
 while n<l(c)-1:h,a=c[n:n+2];D=[(h,a),(F+(h-H)*O+a-L,)][H<=h<L<=a<X];M=3-l(D);n+=M;d+=D[:M]
 if n<l(c):d=*d,c[n]
 return S(d,e)
V=lambda c,e=z:W(sum(map(lambda p:([H+(p-F)//O,L+(p-F)%O],[p])[p<F],c),[]),e,P)
w=lambda y,e='':S(R(y,e,Q,4),e)
W=lambda c,e=z,C=Q:pack(e+C*l(c),*c)
K=(u,U),(v,V),(v,V,z),(v,V,Z),(w,W),(w,W,z),(w,W,Z)
def C(y,f,t):f,_,*a=K[f];_,t,*b=K[t];return t(f(y,*a),*b)
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.