Romanize ภาษาเกาหลี


12

ใช่มันเป็นพื้นคุณเป็น Romanizer เด็กแต่ยาก ชอบวิธีที่ยากขึ้น

เรียนภาษาเกาหลีอย่างหนัก อย่างน้อยสำหรับคนที่อยู่นอกเอเชีย แต่อย่างน้อยพวกเขาก็มีโอกาสเรียนรู้ใช่ไหม

สิ่งที่คุณต้องทำ

คุณจะได้รับใบแจ้งยอดเกาหลี ตัวอย่างเช่น안녕하세요. คุณต้องแปลงอินพุตเป็นการออกเสียงโรมัน annyeonghaseyoยกตัวอย่างเช่นกำหนดให้การส่งออกสามารถ

ตอนนี้มันได้รับทางเทคนิค

ตัวอักษรเกาหลีมีสามส่วนเริ่มต้นพยัญชนะสระและสิ้นสุดพยัญชนะ พยัญชนะสิ้นสุดอาจไม่มีอยู่ในตัวละคร

ยกตัวอย่างเช่นเป็น(เริ่มต้นพยัญชนะ) และ(สระ) และเป็น(เริ่มต้นพยัญชนะ) (สระ) และ(พยัญชนะสิ้นสุด)

หลีกเลี่ยงเสียงพยัญชนะและสระที่มีการออกเสียง การออกเสียงของพยัญชนะแต่ละตัวมีดังต่อไปนี้

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

(- หมายถึงไม่มีการออกเสียงหรือไม่ได้ใช้คุณไม่ต้องจัดการกับมัน)

และการออกเสียงสำหรับแต่ละสระมีดังต่อไปนี้

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

ตอนนี้มันเป็นส่วนที่ยากจริง

การออกเสียงของพยัญชนะเปลี่ยนไปตามพยัญชนะสิ้นสุดในก่อน การออกเสียงสำหรับพยัญชนะเริ่มต้น / สิ้นสุดทุกภาพเป็นดังต่อไปนี้ ขอบคุณ Wikipedia  หากไม่มีสิ่งนี้ฉันจะต้องเขียนทั้งหมดนี้ (คุณไม่ต้องใช้เครื่องหมายขีดคั่นระหว่างการออกเสียงมันไม่จำเป็นถ้าเซลล์มีการออกเสียงสองหรือมากกว่านั้นให้เลือกหนึ่งถ้าไม่มีพยัญชนะลงท้ายให้ใช้การออกเสียงดั้งเดิม)

ตัวอย่าง

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

ยินดีรับข้อเสนอแนะตัวอย่าง คุณสามารถได้คำตอบสำหรับปัจจัยการผลิตของตัวเองที่นี่ (หนึ่งใน "ข้อความทั่วไป" ฉบับแก้ไขคือสิ่งที่ฉันขอ)


อินพุตจะประกอบด้วยอักขระ Unicode AC00-D7AF + space เสมอหรือไม่
Arnauld

1
มีชุดค่าผสมㅎ + X หลายชุดที่ไม่เน้นสีเหลือง (เช่นㅎ + ㅈ = ch) นั่นหมายความว่าเราไม่ต้องให้การสนับสนุนพวกเขา? (นอกจากนี้ㅎคือ 'romanized' เป็นtแทนhในภาพซึ่งค่อนข้างสับสน)
Arnauld

1
กรณีทดสอบ: gist.github.com/perey/563282f8d62c2292d11aabcde0b94d2dตามที่ @Arnauld พูดว่ามีความแปลกประหลาดบางอย่างในชุดค่าผสมพิเศษ สิ่งนี้มีการทดสอบสำหรับทุกสิ่งที่ฉันพบในตารางไม่ว่าจะเน้นหรือไม่ ในกรณีที่มีหลายตัวเลือกพวกเขาจะถูกคั่นด้วยช่องว่าง ไม่มีการใช้ยัติภังค์ตามที่คาดไว้
ทิม Pederick

1
ฉันไม่เห็น "ข้อความทั่วไป" ในลิงก์ตรวจสอบผลลัพธ์ที่แนะนำของคุณ คุณหมายถึง "สิ่งทั่วไป" หรือไม่? ถ้าเป็นเช่นนั้นหนึ่งในสามที่เราควรใช้ (แก้ไข McCune, เยล) ดูเหมือนจะไม่มีใครเทียบโต๊ะของคุณ ตัวอย่างเช่นㅈตามด้วยㄹควรเป็น "nn" ตามที่คุณ แต่เป็น "tr" หรือ "cl" ที่ลิงก์นั้น (โปรดทราบว่ากรณีทดสอบของฉันในความคิดเห็นก่อนหน้าจะขึ้นอยู่กับการทับศัพท์ในคำถาม!)
Tim Pederick

ตามด้วยㄱ, ㄷ, ㅈเป็นกรณีพิเศษ (พวกเขากลายเป็นแรงบันดาลใจให้ㅋ, ㅌ, ㅈ(k, t, j)) ควรเน้นเหล่านั้นด้วย
JungHwan Min

คำตอบ:


8

Python 3.6, 400 394 ไบต์

แก้ไข:ขอบคุณRootTwoสำหรับ -6 ไบต์

นี่คือการส่งครั้งแรกของฉันใน CodeGolf ดังนั้นฉันค่อนข้างมั่นใจว่ามีวิธีที่ดีกว่าในการตีกอล์ฟ แต่ฉันคิดว่าฉันยังโพสต์ไว้เนื่องจากยังไม่มีใครพูดถึงแนวคิดหลักและยังสั้นกว่าโซลูชันอื่น ๆ อย่างมาก .

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)

มันทำงานอย่างไร

วิธีการแก้ปัญหาพยายามที่จะใช้ประโยชน์จากความจริง (ที่ฉันได้เรียนรู้จากความท้าทายของภาษาญี่ปุ่นดั้งเดิม) ที่ชื่อตัวอักษรโรมันสามารถเข้าถึงได้ผ่านโมดูลหน่วยความจำแบบซินิกอนของไพ ธ อน HANGUL SYLLABLE <NAME>สำหรับภาษาเกาหลีที่พวกเขาใช้รูปแบบของ น่าเสียดายที่การประมวลผลชื่อเหล่านี้เพื่อให้ตรงตามข้อกำหนดที่ให้ไว้และเพื่อให้ครอบคลุมสถานการณ์การรวมพยางค์ทั้งหมดยังคงต้องใช้ความพยายามค่อนข้างน้อย (และไบต์)

ชื่อตัวละครที่ได้รับรายชื่อพยัญชนะทั้งหมดในทุกที่ทุกรูปแบบของเสียงในพยางค์เช่นGGAGGสำหรับ, R/Lมีการถ่ายทอดตามที่ตั้งใจไว้ (เริ่มRตอนจบL) และCHจะได้รับเป็นC(นี้จริงเราประหยัดบิตของอาการปวดหัว)

ก่อนอื่นเราตัดHANGUL SYLLABLEส่วน (16 ตัวอักษรแรก) ทำเครื่องหมายขอบเขตของพยางค์ด้วย-แล้วใช้ชุด RegEx'es เพื่อทำการแปลง

RegEx แรกดูน่ารังเกียจเป็นพิเศษ สิ่งที่มันโดยทั่วไปจะเป็นของการเริ่มต้นการแปลงพยัญชนะเข้าเทียบเท่าสิ้นสุดของพวกเขา (ยังเอาตัวอักษรพิเศษในกรณีของพยัญชนะคู่) เมื่อพวกเขาจะไม่ได้ตามด้วยสระหรือตัวอักษรบาง - hเมื่อพวกเขาจะนำหน้าด้วย (?<!n)จับคู่ lookbehind ป้องกันgซึ่งเป็นส่วนหนึ่งngและ(?!\\1)เพื่อให้แน่ใจ lookahead ว่าเราไม่ได้แปลงเช่นการ ssatsa

RegEx'es ไม่กี่ตัวต่อไปจะแปลงพยัญชนะเริ่มต้นเป็นคู่ที่ไม่ออกเสียง นี่คือที่-ตัวคั่นมีประโยชน์เช่นกันเนื่องจากช่วยแยกแยะขอบเขตการชน ( g-g) จากพยัญชนะสองตัว ( gg) ตอนนี้พวกเขายังสามารถลบได้

ต่อไปเราจัดการh+consonantชุดค่าผสมที่เหลือl->rก่อนสระและกรณีพิเศษอื่น ๆ

สุดท้ายเราเรียกคืนcไปchและแก้ไขบาง pecularities อื่น ๆ ของถ่านชื่อเข้าของเราเช่นyiแทนuiและแทนweowo

ฉันไม่ใช่ผู้เชี่ยวชาญในภาษาเกาหลีและไม่สามารถออกความเห็นได้อีกมากมาย แต่ดูเหมือนว่าจะผ่านการทดสอบทั้งหมดที่โพสต์ในงานและบน Github เห็นได้ชัดว่าสามารถลบข้อมูลออกได้อีกสองสามไบต์หากเอาต์พุตเป็นที่ยอมรับในตัวพิมพ์ใหญ่เนื่องจากนี่คือสิ่งที่เราได้รับจากฟังก์ชันชื่อ


ยินดีต้อนรับสู่ PPCG! คำตอบแรกที่ดี
FantaC

1
คำตอบที่ดี จาก python 3.6 นั้นm[0]เป็นเช่นเดียวกับm.group(0); ประหยัด 6 ไบต์
RootTwo

5

JavaScript (ES6), 480 ไบต์ (WIP)

นี่เป็นความพยายามแรกเริ่มที่ขึ้นอยู่กับข้อมูลจำเพาะปัจจุบันเพื่อรับลูกบอลกลิ้ง มันอาจต้องมีการแก้ไขเมื่อคำถามในความคิดเห็นจะถูกแก้ไข

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``

กรณีทดสอบ

อย่างไร?

เมื่อคลายการบีบอัดแล้วอาร์เรย์V จะมีข้อมูลต่อไปนี้:

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

เราแยกอักขระฮันกึลแต่ละตัวออกเป็นพยัญชนะเริ่มต้นเสียงสระและพยัญชนะลงท้าย เราผนวกเข้ากับผลลัพธ์:

  • V[80 + substitution] + V[vowel] หากมีการทดแทน
  • V[40 + previousEndingConsonant] + V[21 + startingConsonant] + V[vowel] มิฉะนั้น

'!'ไม่สามารถเป็นได้33?
Jonathan Frech

@JonathanFrech cไม่ใช่ไบต์ มันคือสตริง 1 ตัวอักษร ที่กล่าวว่าเมื่อใช้การดำเนินการเลขคณิตพื้นที่ถูกบังคับให้0ในขณะที่ตัวละครอื่น ๆ NaNที่ไม่ใช่หลักจะถูกบังคับให้ ซึ่งหมายความว่าc<1ควรใช้งานได้จริงตามที่คาดไว้ (และc<33ยังสามารถใช้ได้กับตัวละครที่ไม่ใช่ตัวเลขแม้ว่านี่จะเป็นเรื่องบังเอิญ)
Arnauld

@JonathanFrech ภาคผนวก: c<1ก็จะเป็นจริงสำหรับ"0"(ซึ่งอาจจะตกลงถ้าข้อมูลมีการรับประกันว่าจะไม่มีเลขอารบิคใด ๆ )
Arnauld

ขอบคุณ ฉันไม่คิดว่า JavaScript จะมีอักขระที่ใช้งานเป็นไบต์เดียว แต่ก็ยังพยายามอยู่ อย่างไรก็ตามมันดูเหมือนว่าจะทำงาน ดีใจที่รู้ว่าทำไมตอนนี้
Jonathan Frech

2

Tcl, 529 ไบต์

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]]

ขั้นตอนวิธี

  1. การสลายตัวเป็นดัชนีตะกั่วสระและหาง
  2. การค้นหาครั้งแรกถึงการแสดงตัวอักษรระดับกลาง
  3. ใช้การผ่านครั้งแรกสำหรับการแปลง xn → nn / xm → nm ทั้งหมด
  4. ใช้บัตรผ่านรอบสุดท้ายสำหรับการเปลี่ยนรูปที่เหลือ

อัลกอริทึมนี้ได้รับการแก้ไขเพื่อวัตถุประสงค์ในการท้าทาย การแลกเปลี่ยนเป็นสิ่งที่อินพุตถือว่าไม่มีตัวอักษรละตินใด ๆ หรือใช้อักขระนอกบล็อก U + AC00 Hangul ดังอธิบายในการท้าทาย เป็นรหัสจริงฉันจะเก็บการเปลี่ยนแปลงทั้งหมดใน Jamo จนกว่าจะผ่านรอบสุดท้าย

ฉันคิดว่าฉันสามารถเพิ่มพลังสมองอีกหน่อยเพื่อบีบเสียงสระเหล่านั้นและการทำซ้ำ ๆ ในตารางการค้นหา แต่สิ่งนี้ดีเท่าที่ฉันจะได้รับจากฉันในวันนี้

การทดสอบ

ตรวจสอบให้แน่ใจว่าคุณสามารถจัดหาอินพุต UTF-8 ให้กับล่าม Tcl สามารถทำได้อย่างง่ายดายที่สุดด้วยไฟล์ข้อความแบบง่าย UTF-8 อนิจจา Tcl ยังไม่เริ่มต้นเป็น UTF-8 โดยค่าเริ่มต้น; ค่าใช้จ่ายฉัน 33 ไบต์

นี่คือไฟล์ทดสอบของฉัน (น่าสงสารในปัจจุบัน):

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

หมายเหตุ

ฉันไม่รู้อะไรเกี่ยวกับภาษาเกาหลี (ยกเว้นสิ่งที่ฉันได้เรียนรู้เล็กน้อยที่นี่) นี่เป็นครั้งแรกที่รอการแก้ไขที่อาจเกิดขึ้นเนื่องจากการอัปเดตในข้อกำหนดคำถาม

และข้อมูลเพิ่มเติมบางอย่างก็มีประโยชน์ โดยเฉพาะอย่างยิ่งไม่มีการโต้ตอบ 1: 1 ระหว่างพยัญชนะนำและหางตามที่ดูเหมือนว่าจะได้รับการแนะนำในการท้าทาย ไซต์สองแห่งต่อไปนี้ช่วยในการค้นหาอย่างมาก:
วิกิพีเดีย: ภาษาเกาหลี, อังกูล
วิกิพีเดีย: Hangul Jamo (บล็อก Unicode)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.