Tujuannya adalah untuk membuat konverter yang sepenuhnya sesuai antara pengkodean Unicode resmi seperti yang diberikan dalam FAQ UTF . Mengingat bahwa ini berpusat pada Unicode, saya akan menerima jawaban dengan jumlah byte terendah menggunakan yang terbaik dari pengkodean yang terlibat (yang mungkin akan menjadi UTF-8, kecuali mungkin Anda memprogramnya di APL). Saya minta maaf atas posting lama, tetapi banyak yang menjelaskan tentang pengkodean yang juga dapat diakses dalam spesifikasi resmi (pdf, bagian 3.9 D90 - D92) , atau Wikipedia .
Spesifikasi
Jika suatu saat bahasa pilihan Anda tidak dapat secara tepat memenuhi persyaratan, gantikan dengan sesuatu yang melekat pada semangat aturan yang diberikan. Misalnya. tidak setiap bahasa memiliki susunan bawaan, fungsi dll.
Tidak menggunakan string libraries / functions, atau encoding libraries / functions. Inti dari kode golf ini adalah untuk mengimplementasikan konverter menggunakan manipulasi bit / byte. Menggunakan string sendiri dalam kapasitasnya sebagai karakter atau byte array diperbolehkan. Oh, dan tidak ada panggilan OS yang melakukan konversi.
Konverter adalah fungsi yang akan mengambil tiga parameter: array byte yang mewakili string input yang dikodekan, dan pengkodean "input" dan "output" direpresentasikan sebagai angka. Secara sewenang-wenang kami akan menetapkan
UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE, and UTF32LE
angka dari 0 hingga 6 dalam urutan itu. Tidak perlu memeriksa apakah nomornya< 0
atau> 6
, kami akan menganggap parameter ini benar. Konverter akan mengembalikan array byte yang valid dalam pengkodean output yang diinginkan.Kami akan menggunakan karakter nol (
U+0000
) sebagai terminator string. Apa pun setelah ini tidak masalah. Kami akan menganggap bahwa array input memiliki karakter nol di suatu tempat sehingga Anda tidak perlu melakukan pemeriksaan batas.Sesuai FAQ , jika array byte input tidak valid untuk pengkodean yang dinyatakannya, kami harus memberi sinyal kesalahan. Kami akan melakukan ini dalam salah satu cara berikut: crash program, lempar pengecualian, kembalikan null atau kembalikan array yang empat byte pertamanya semuanya 0 (sehingga dapat dikenali
U+0000
dalam setiap penyandian).
Pengkodean
Spesifikasi resmi harus dipatuhi, tetapi Wikipedia memberikan penjelasan yang baik (dan sejauh yang saya yakini benar) dari pengkodean, dan saya akan meringkasnya di sini untuk kelengkapan. Perhatikan bahwa UTF-16 dan UTF-32 memiliki varian untuk endianness .
UTF-32, UTF-32LE, UTF-32BE
Pengkodean paling sederhana, setiap titik kode hanya dikodekan dalam 4 byte sama dengan nilai numeriknya. LE / BE mewakili endianness (little endian / big endian).
UTF-16, UTF-16LE, UTF-16BE
Poin kode dari U+0000 - U+FFFF
dikodekan dalam 2 byte sama dengan nilai numeriknya. Nilai yang lebih besar dikodekan menggunakan sepasang pengganti yang merupakan nilai yang dicadangkan dari U+D800 - U+DFFF
. Jadi untuk menyandikan poin lebih besar dari itu U+FFFF
, algoritma berikut ini dapat digunakan (disalin tanpa malu-malu dari Wikipedia ):
- 0x010000 dikurangi dari titik kode, meninggalkan angka 20 bit di kisaran 0..0x0FFFFF.
- Sepuluh bit teratas (angka dalam kisaran 0..0x03FF) ditambahkan ke 0xD800 untuk memberikan unit kode pertama atau pengganti pengganti, yang akan berada dalam kisaran 0xD800..0xDBFF [...].
- Sepuluh bit rendah (juga dalam kisaran 0..0x03FF) ditambahkan ke 0xDC00 untuk memberikan unit kode kedua atau pengganti jejak, yang akan berada dalam kisaran 0xDC00..0xDFFF [...].
UTF-8
Poin kode dari U+0000 - U+007F
dikodekan sebagai 1 byte sama dengan nilai numeriknya. Dari U+0080 - U+07FF
mereka dikodekan sebagai 110xxxxx 10xxxxxx
, U+0800 - U+FFFF
adalah 1110xxxx 10xxxxxx 10xxxxxx
, nilai yang lebih tinggi 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
. Ini x
adalah bit dari nilai numerik dari titik kode.
BOM
Tanda byte-order (BOM, U+FEFF
) digunakan sebagai titik kode pertama untuk menunjukkan endianness. Mengikuti pedoman FAQ tentang BOM, BOM akan digunakan sebagai berikut: Untuk UTF-8, UTF-16 and UTF-32
itu opsional. Jika BOM tidak ada di UTF-16
atau UTF-32
, diasumsikan sebagai big endian. BOM tidak boleh muncul diUTF-16LE, UTF-16BE, UTF-32LE and UTF-32BE
.
Kesalahan Umum Menyebabkan UTF Tidak Valid
Berbagai hal dapat menyebabkan urutan byte menjadi UTF tidak valid.
- UTF-8 dan UTF-32: Langsung menyandikan poin kode pengganti (
U+D800 - U+DFFF
), atau poin kode lebih besar dariU+10FFFF
. - UTF-8: Banyak urutan byte yang tidak valid.
- UTF-16: pengganti yang berpasangan atau tidak berpasangan.
- BOM: Harus digunakan seperti yang ditentukan di bagian penyandian. Perhatikan bahwa ketika mengeluarkan
UTF-16
atauUTF-32
(tidak ditentukan endianness inheren) Anda dapat memilih, tetapi dengan sedikit endian, Anda harus memasukkan BOM.
Perhatikan bahwa non-karakter dan titik kode yang tidak ditetapkan (keduanya berbeda dari pengganti) harus diperlakukan seperti karakter biasa.
''⎕R''⍠'InEnc' 'UTF16BE' 'OutEnc' 'UTF8-BOM'
,.Jawaban:
C ++, (UTF-8) 971 byte
Program yang dapat dibaca di bawah ini dapat diringkas ke formulir di atas dengan memfilternya melalui perintah Perl berikut:
Perintah di atas
#include
garisKode yang bisa dibaca
Fungsi yang akan dipanggil adalah
t()
, dengan pengkodean input dan output diteruskan dalam variabel globali
dano
masing - masing, danp
menunjuk pada byte input, yang harus diakhiri null.q
menunjuk ke buffer output, yang akan ditimpa, dan harus cukup besar untuk hasilnya - tidak ada upaya untuk menghindari buffer overrun.Saya harap komentar kode cukup jelas - tanyakan di bawah ini apakah salah satunya terlalu samar (tapi usahakan dulu!).
Saya menyusun suite uji substansial sambil mengembangkan jawaban ini; Saya memasukkannya di bawah ini untuk kepentingan pendatang lain, dan untuk mendokumentasikan interpretasi saya tentang persyaratan:
Fungsi tes
Suite uji
sumber
Python - 1367 karakter UTF-8
Baik! Ini adalah pertanyaan yang sangat sulit karena banyaknya pekerjaan yang diperlukan untuk memahami dan mengimplementasikan semua spesifikasi, tetapi saya pikir saya memiliki implementasi yang benar.
convert
adalah fungsi yang mengambil objek data 'bytes', ID input, dan ID output. Tampaknya bekerja - meskipun python tampaknya memiliki penggunaan BOM yang sedikit rusak ketika tidak ditentukan dalam pengkodean, jadi menggunakan pengkodean builtin python untuk menguji mode 1 dan 4 tidak akan berfungsi.Fakta menyenangkan: Ukurannya juga 555 16 atau 10101010101 2 .
773 karakter untuk decoding, 452 untuk encoding, 59 untuk verifikasi dan 83 untuk bagian lain-lain.
sumber
Python 3, 1138 byte (UTF-8)
Jadi ternyata 14 jam perjalanan internasional adalah kesempatan luar biasa untuk menyelesaikan tantangan golf ...
Fungsi konversi adalah
C()
. Ini panggilanu()
,v()
danw()
untuk decode, danU()
,V()
, danW()
untuk encode, UTF-8, -16 dan -32, masing-masing. Tidak satu pun dari penyandi akan menghasilkan BOM, tetapi semua dekoder akan menangani dengan benar. Kondisi kesalahan menghasilkan pengecualian (biasanya aZeroDivisionError
, berkat fungsi "mati-tiba-tiba"E()
).sumber