Romanisasi bahasa Korea

12

Ya, pada dasarnya Anda seorang Romanizer, Sayang , tetapi lebih sulit . seperti, jauh lebih sulit.

Belajar bahasa Korea adalah KERAS. setidaknya untuk seseorang di luar Asia. Tetapi mereka setidaknya memiliki kesempatan untuk belajar, bukan?

Apa yang harus Anda lakukan

Anda akan diberikan Pernyataan Korea. Sebagai contoh 안녕하세요,. Anda harus mengonversi input ke pengucapan Romawi. Untuk contoh yang diberikan, hasilnya bisa annyeonghaseyo.

Sekarang menjadi teknis

Karakter Korea memiliki tiga bagian, Konsonan awal, Vokal, dan Konsonan akhir. Konsonan akhir mungkin tidak ada dalam karakter.

Misalnya, adalah (Konsonan awal) dan (Vokal), dan adalah (Konsonan awal), (Vokal), dan (Akhir konsonan).

Evert konsonan dan vokal memiliki pengucapannya. Pengucapan untuk setiap konsonan adalah sebagai berikut.

Korean                 ㄱ   ㄲ  ㄴ  ㄷ   ㄸ  ㄹ  ㅁ  ㅂ  ㅃ  ㅅ  ㅆ  ㅇ   ㅈ   ㅉ  ㅊ ㅋ  ㅌ   ㅍ  ㅎ
Romanization Starting   g   kk  n   d   tt  r   m   b   pp  s   ss  –   j   jj  ch  k   t   p   h
               Ending   k   k   n   t   –   l   m   p   –   t   t   ng  t   –   t   k   t   p   h

(- Berarti tidak ada pengucapan atau tidak digunakan. Anda tidak harus menanganinya.)

dan pengucapan untuk setiap vokal adalah sebagai berikut.

Hangul          ㅏ  ㅐ  ㅑ  ㅒ   ㅓ  ㅔ  ㅕ  ㅖ  ㅗ   ㅘ   ㅙ  ㅚ ㅛ  ㅜ  ㅝ  ㅞ  ㅟ   ㅠ  ㅡ   ㅢ ㅣ
Romanization    a   ae  ya  yae eo  e   yeo ye  o   wa  wae oe  yo  u   wo  we  wi  yu  eu  ui  i

Sekarang bagian yang sangat sulit

Pengucapan konsonan berubah oleh konsonan Ending sebelumnya. Pengucapan untuk setiap konsonan Starting / Ending adalah seperti gambar berikut. Terima kasih, Wikipedia.  Jika tidak ada ini, saya harus MENULIS semua ini. (Anda tidak harus melakukan tanda hubung di antara pengucapan. Itu tidak perlu. Jika sel memiliki dua pengucapan atau lebih, pilih satu. Jika tidak ada konsonan akhir, gunakan pengucapan aslinya.)

Contohnya

Korean => English
안녕하세요 => annyeonghaseyo
나랏말싸미 듕귁에달아 => naranmalssami dyunggwigedara  //See how the ㅅ in 랏 changes from 't' to 'n'

Saran contoh disambut. Anda bisa mendapatkan jawaban untuk masukan Anda sendiri di sini . (Yang ada di "Teks umum", Direvisi adalah apa yang saya minta)

Matthew Roh
sumber
Apakah input selalu terdiri dari karakter Unicode AC00-D7AF + spasi?
Arnauld
1
Ada beberapa kombinasi ㅎ + X khusus yang tidak disorot dengan warna kuning (mis. ㅎ + ㅈ = ch). Apakah itu berarti kita tidak harus mendukung mereka? (Juga, ㅎ diromanisasi 'sebagai t bukannya h dalam gambar, yang agak membingungkan.)
Arnauld
1
Test case: gist.github.com/perey/563282f8d62c2292d11aabcde0b94d2d Seperti yang dikatakan @Arnauld, ada beberapa keanehan dalam kombinasi khusus; ini memiliki tes untuk semua yang saya temukan di tabel, apakah disorot atau tidak. Di mana ada banyak pilihan, mereka dipisahkan oleh ruang. Tidak ada tanda hubung yang digunakan karena saya berharap orang bisa bermain golf.
Tim Pederick
1
Saya tidak melihat "Teks umum" di tautan pemeriksaan keluaran yang disarankan; maksudmu "hal-hal umum"? Jika demikian, yang mana dari ketiganya yang harus kita gunakan (Revisi, McCune, Yale)? Tampaknya tidak ada yang cocok dengan meja Anda; misalnya, ㅈ diikuti oleh ㄹ harus "nn" menurut Anda tetapi "tr" atau "cl" di tautan itu. (Perhatikan bahwa kasus pengujian saya di komentar sebelumnya didasarkan pada transliterasi dalam pertanyaan!)
Tim Pederick
diikuti oleh ㄱ, ㄷ, ㅈjuga kasus khusus (mereka menjadi aspirasi ㅋ, ㅌ, ㅈ(k, t, j)) harus menyoroti itu juga.
JungHwan Min

Jawaban:

8

Python 3.6, 400 394 byte

Sunting: Berkat RootTwo untuk -6 byte.

Ini adalah pengajuan pertama saya pada CodeGolf, jadi saya cukup yakin ada cara yang lebih baik untuk bermain golf, tapi saya pikir saya masih akan mempostingnya, karena belum ada yang menyebutkan ide kunci, dan ini masih jauh lebih singkat daripada solusi lain .

import re,unicodedata as u
t='-'.join(u.name(i)[16:]for i in input()).lower()
for i in range(19):t=re.sub('h-[gdb]|(?<!n)([gdbsjc]+)(?!\\1)(?!-?[aeiouyw]) gg dd bb -- - h(?=[nmrcktp])|hh hj l(?=[aeiouyw]) l[nr] [nt][nr] tm pm [pm][nr] km kn|kr|ngr c yi weo'.split()[i],([lambda m:'ktpttt'['gdbsjc'.index(m[0][-1])]]+'kk,tt,pp, ,,t,c,r,ll,nn,nm,mm,mn,ngm,ngn,ch,ui,wo'.split(","))[i],t)
print(t)

Bagaimana itu bekerja

Solusi ini mencoba untuk mengeksploitasi fakta (yang saya pelajari dari tantangan romanisasi Jepang asli) bahwa nama karakter yang diromanisasi dapat diakses melalui modul unicodedata Python. Untuk bahasa Korea, mereka mengambil bentuk HANGUL SYLLABLE <NAME>. Sayangnya, memproses nama-nama ini untuk memenuhi spesifikasi yang disediakan dan untuk mencakup semua skenario kombinasi suku kata masih membutuhkan sedikit usaha (dan byte).

Nama-nama karakter yang diperoleh mendaftar semua konsonan dalam bentuk suara mereka di mana saja dalam suku kata, misalnya GGAGGuntuk , R/Lditranskripsikan sebagaimana dimaksud (mulai R, berakhir L), dan CHdiberikan sebagai C(ini sebenarnya menghemat sedikit sakit kepala).

Pertama-tama, kita menanggalkan HANGUL SYLLABLEbagian (16 karakter pertama), menandai batas suku kata dengan -, dan kemudian menerapkan serangkaian RegEx'es untuk melakukan konversi.

RegEx pertama terlihat sangat jahat. Apa yang pada dasarnya dilakukannya adalah konversi konsonan awal ke dalam ekuivalen akhir mereka (juga menghapus huruf tambahan dalam kasus konsonan ganda), ketika mereka tidak diikuti oleh vokal, atau untuk beberapa huruf - ketika mereka didahului oleh h. Tampilan di belakang (?<!n)mencegah pencocokan gyang merupakan bagian dari ng, dan (?!\\1)lookahead memastikan bahwa kami tidak mengonversi, misalnya ssamenjadi tsa.

Beberapa RegEx'es berikutnya mengkonversi mulai konsonan ganda menjadi padanan tidak bersuara mereka. Di sinilah -pemisah juga berguna karena mereka membantu membedakan tumbukan batas ( g-g) dari konsonan ganda ( gg). Sekarang mereka juga bisa dihapus.

Selanjutnya, kami menangani h+consonantkombinasi yang tersisa , l->rsebelum vokal, dan case khusus lainnya.

Akhirnya, kami mengembalikan cke ch, dan menyelesaikan beberapa kekhasan lainnya dari nama char kami yang masuk, seperti yibukannya uidan weobukannya wo.

Saya bukan ahli bahasa Korea dan tidak bisa berkomentar lebih banyak, tetapi ini tampaknya lulus semua tes yang diposting di tugas dan di Github. Jelas, beberapa byte lagi dapat dicukur, jika outputnya dapat diterima dalam huruf besar, karena ini adalah apa yang kita dapatkan dari fungsi nama.

Kirill L.
sumber
Selamat datang di PPCG! Jawaban pertama yang bagus.
FantaC
1
Jawaban bagus. Pada python 3.6, m[0]sama dengan m.group(0); menghemat 6 byte.
RootTwo
5

JavaScript (ES6), 480 byte (WIP)

Ini adalah upaya awal berdasarkan spesifikasi saat ini untuk mendapatkan bola bergulir. Ini mungkin memerlukan beberapa perbaikan ketika pertanyaan dalam komentar ditujukan.

s=>[...s].map(c=>c<'!'?c:(u=c.charCodeAt()-44032,y='1478ghjlmnpr'.search((p=t).toString(36)),t=u%28,u=u/28|0,v=u%21,x=[2,5,6,11,18].indexOf(u=u/21|0),~x&~y&&(z=parseInt(V[y+68][x],36))>10?V[z+69]:V[p+40]+V[u+21])+V[v],t=0,V='8a6y8ye6e46ye4y64w8wa6o6y4u/w4w6wi/yu/eu/ui/i/g/k21d/t7r/3b/p0s/ss95j5ch/270h922/197l999930/77ng/77270h/bbcd6afaa8gghi5ffak8alaa8llmn4gghp8abaa8gghq5gghr5ggha5gghs8ng1ng3g/2ll/n1n3d/7r/m1m3b/0s/5ch/h'.replace(/\d/g,n=>'pnkmojeta/'[n]+'/').split`/`).join``

Uji kasus

Bagaimana?

Setelah didekompresi, array V berisi data berikut:

00-20 vowels
a/ae/ya/yee/eo/e/yeo/ye/o/wa/wae/oe/yo/u/wo/we/wi/yu/eu/ui/i

21-39 starting consonants
g/kk/n/d/tt/r/m/b/pp/s/ss//j/jj/ch/k/t/p/h

40-67 ending consonants
/k/k//n///t/l////////m/p//t/t/ng/t/t/k/t/p/h

68-79 indices of substitution patterns for consecutive consonants
      ('a' = no substitution, 'b' = pattern #0, 'c' = pattern #1, etc.)
bbcde/afaaa/gghij/ffaka/alaaa/llmno/gghpa/abaaa/gghqj/gghrj/gghaj/gghsa

80-97 substitution patterns
ngn/ngm/g/k/ll/nn/nm/d/t/r/mn/mm/b/p/s/j/ch/h

Kami membagi setiap karakter Hangul menjadi konsonan awal, vokal dan konsonan akhir. Kami menambahkan hasilnya:

  • V[80 + substitution] + V[vowel] jika ada substitusi
  • V[40 + previousEndingConsonant] + V[21 + startingConsonant] + V[vowel] jika tidak
Arnauld
sumber
Tidak '!'bisa 33?
Jonathan Frech
@JonathanFrech cbukan byte. Ini adalah string 1 karakter. Yang mengatakan , ketika menerapkan operasi aritmatika, spasi dipaksa 0sementara karakter non-digit lainnya dipaksa NaN. Yang berarti c<1harus benar-benar berfungsi seperti yang diharapkan. (Dan c<33juga akan berfungsi untuk karakter non-digit, meskipun ini agak kebetulan.)
Arnauld
@JonathanFrech Addendum: c<1juga benar untuk "0"(yang mungkin OK jika input dijamin tidak mengandung angka Arab.)
Arnauld
Terima kasih. Saya tidak berpikir bahwa JavaScript akan memiliki karakter yang diimplementasikan sebagai byte tunggal, meskipun saya sudah mencoba. Namun, tampaknya itu berhasil. Senang sekarang tahu kenapa.
Jonathan Frech
2

Tcl, 529 byte

fconfigure stdin -en utf-8
foreach c [split [read stdin] {}] {scan $c %c n
if {$n < 256} {append s $c} {incr n -44032
append s [string index gKndTrmbPsS-jJCktph [expr $n/588]][lindex {a ae ya yae eo e yeo ye o wa wae oe yo u wo we wi yu eu ui i} [expr $n%588/28]][string index -Ak-n--tl-------mp-BGQDEkFph [expr $n%28]]}}
puts [string map {nr nn
A- g An ngn Ar ngn Am ngm A kk
t- d p- b B- s D- j
nr ll l- r ln ll lr ll
A k B t G t D t E t F t
K kk T tt P pp S ss J jj C ch Q ng
- ""} [regsub -all -- {[tpBDEFh]([nrm])} $s n\\1]]

Algoritma

  1. Dekomposisi menjadi indeks timbal, vokal, dan ekor
  2. Pencarian pertama ke representasi alfabet menengah
  3. Terapkan pass awal untuk semua transformasi xn → nn / xm → nm
  4. Terapkan pass terakhir untuk transformasi yang tersisa

Algoritma ini berderak untuk tujuan tantangan; trade-off adalah bahwa input diasumsikan tidak mengandung karakter alfabet Latin, atau untuk menggunakan karakter di luar blok Hangul U + AC00 seperti yang dijelaskan dalam tantangan. Apakah ini kode asli, saya akan menyimpan semua transformasi di Jamo sampai lulus terakhir.

Saya kira saya bisa melempar lebih banyak kekuatan otak pada vokal-vokal itu dan beberapa pengulangan dalam tabel pencarian, tetapi ini sama baiknya dengan yang saya dapatkan hari ini.

Pengujian

Pastikan Anda dapat menyediakan input UTF-8 ke juru bahasa Tcl. Ini paling mudah dilakukan dengan file teks UTF-8 yang sederhana. Sayangnya, Tcl masih tidak default ke UTF-8 secara default; ini harganya 33 byte.

Ini file pengujian saya (saat ini menyedihkan):

한
안녕하세요
나랏말싸미 듕귁에달아

Catatan

Saya tidak tahu apa-apa tentang bahasa Korea (kecuali sedikit yang telah saya pelajari di sini). Ini adalah upaya pertama, sambil menunggu revisi potensial karena pembaruan dalam spesifikasi pertanyaan.

Dan, tentang itu, beberapa informasi tambahan bermanfaat. Secara khusus, tidak ada korespondensi 1: 1 antara konsonan memimpin dan ekor seperti yang disarankan dalam tantangan. Dua situs berikut sangat membantu mengetahuinya:
Wikipedia: Bahasa Korea, Hangul
Wikipedia: Hangul Jamo (blok Unicode)

Dúthomhas
sumber