Romanizar coreano

12

Sí, básicamente eres un romanizador, bebé , pero más difícil . como, mucho más difícil.

Aprender coreano es DURO. al menos para una persona fuera de Asia. Pero al menos tienen la oportunidad de aprender, ¿verdad?

Lo que debes hacer

Se le dará una declaración coreana. Por ejemplo, 안녕하세요. Debe convertir la entrada a su pronunciación romana. Para el ejemplo dado, la salida puede ser annyeonghaseyo.

Ahora se pone técnico

Un carácter coreano tiene tres partes: consonante inicial, vocal y consonante final. La consonante final puede no existir en el carácter.

Por ejemplo, es (consonante inicial) y (vocal), y es (consonante inicial), (vocal) y (consonante final).

Evert consonante y vocal tiene su pronunciación. La pronunciación de cada consonante es la siguiente.

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

(- significa que no hay pronunciación o que no se utiliza. No tiene que manejarlos).

y la pronunciación de cada vocal es la siguiente.

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

Ahora es la parte realmente difícil

La pronunciación de la consonante cambia por la consonante final en antes. La pronunciación de cada consonante inicial / final es la siguiente imagen. Gracias Wikipedia.  Si no hubiera esto, tendría que ESCRIBIR todo esto. (No tiene que hacer el guión entre las pronunciaciones. Es innecesario. Si una celda tiene dos o más pronunciaciones, elija una. Si no hay una consonante final, use la pronunciación original).

Ejemplos

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

Sugerencia de ejemplo bienvenida. Puede obtener respuestas para sus propias entradas aquí . (El que está en "Texto general", Revisado es lo que estoy pidiendo)

Matthew Roh
fuente
¿La entrada siempre consistirá en caracteres Unicode AC00-D7AF + espacio?
Arnauld
1
Hay varias combinaciones especiales de ㅎ + X que no están resaltadas en amarillo (por ejemplo, ㅎ + ㅈ = ch). ¿Eso significa que no tenemos que apoyarlos? (Además, ㅎ está 'romanizado' como t en lugar de h en la imagen, lo cual es un poco confuso.)
Arnauld
1
Casos de prueba: gist.github.com/perey/563282f8d62c2292d11aabcde0b94d2d Como dice @Arnauld, hay algunas rarezas en las combinaciones especiales; Esto tiene pruebas para todos los que encontré en la tabla, ya sea resaltados o no. Donde existen múltiples opciones, están separadas por espacios. No se usan guiones ya que espero que la gente los juegue.
Tim Pederick
1
No veo "Texto general" en el enlace de comprobación de salida sugerido; ¿te refieres a "cosas generales"? Si es así, ¿cuál de los tres deberíamos usar (Revisado, McCune, Yale)? Ninguno parece coincidir con su mesa; por ejemplo, ㅈ seguido de ㄹ debería ser "nn" según usted, pero es "tr" o "cl" en ese enlace. (¡Tenga en cuenta que mis casos de prueba en el comentario anterior se basan en transliteraciones en la pregunta!)
Tim Pederick
seguidos ㄱ, ㄷ, ㅈtambién son casos especiales (que se aspiran a ㅋ, ㅌ, ㅈ(k, t, j)) también deberían resaltarse.
JungHwan Min

Respuestas:

8

Python 3.6, 400 394 bytes

Editar: Gracias a RootTwo por -6 bytes.

Esta es mi primera presentación en CodeGolf, así que estoy bastante seguro de que hay mejores formas de jugarlo, pero pensé que aún lo publicaría, ya que nadie ha mencionado la idea clave todavía, y esto es significativamente más corto que otras soluciones .

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)

Cómo funciona

La solución intenta explotar el hecho (que aprendí del desafío de romanización japonés original) de que los nombres de caracteres romanizados son accesibles a través del módulo unicodedata de Python. Para el idioma coreano, toman la forma de HANGUL SYLLABLE <NAME>. Desafortunadamente, procesar estos nombres para cumplir con la especificación provista y para cubrir todos los escenarios de combinación de sílabas aún requiere bastante esfuerzo (y bytes).

Los nombres de caracteres obtenidos enumeran todas las consonantes en su forma sonora en cualquier parte de la sílaba, por ejemplo, GGAGGfor , R/Lse transcriben según lo previsto (inicio R, finalización L) y CHse dan como C(esto realmente nos ahorra un poco de dolor de cabeza).

En primer lugar, eliminamos la HANGUL SYLLABLEparte (primeros 16 caracteres), marcamos los límites de las sílabas con -, y luego aplicamos una serie de RegEx'es para hacer las conversiones.

El primer RegEx parece particularmente desagradable. Lo que básicamente hace es convertir las consonantes iniciales en sus equivalentes finales (también eliminando la letra extra en caso de consonantes dobles), cuando no están seguidas de una vocal, o para algunas letras, cuando están precedidas por h. El (?<!n)lookbehind evita la coincidencia, gque es parte de ng, y (?!\\1)lookahead asegura que no se conviertan, por ejemplo, ssaa tsa.

Los siguientes RegEx'es convierten las consonantes dobles iniciales en sus equivalentes sordos. Aquí es donde los -separadores también son útiles ya que ayudan a discernir colisiones de límites ( g-g) de consonantes dobles ( gg). Ahora también se pueden eliminar.

A continuación, manejamos las h+consonantcombinaciones restantes , l->rantes de las vocales y otros casos especiales.

Por último, restauramos ca ch, y resolver algunas otras peculiaridades de nuestros nombres Char entrante, como yilugar de uiy weoen lugar de wo.

No soy un experto en coreano y no puedo comentar mucho más, pero parece que pasa todas las pruebas publicadas en la tarea y en Github. Obviamente, se podrían eliminar unos pocos bytes más, si la salida es aceptable en mayúsculas, ya que esto es lo que obtenemos de la función de nombre.

Kirill L.
fuente
Bienvenido a PPCG! Gran primera respuesta.
FantaC
1
Buena respuesta. A partir de python 3.6, m[0]es lo mismo que m.group(0); ahorrando 6 bytes.
RootTwo
5

JavaScript (ES6), 480 bytes (WIP)

Este es un intento temprano basado en las especificaciones actuales para hacer rodar la pelota. Puede requerir un poco de corrección cuando se abordan las preguntas en los comentarios.

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

Casos de prueba

¿Cómo?

Una vez descomprimido, la matriz V contiene los siguientes datos:

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

Dividimos cada carácter de Hangul en consonante inicial, vocal y consonante final. Anexamos al resultado:

  • V[80 + substitution] + V[vowel] si hay una sustitución
  • V[40 + previousEndingConsonant] + V[21 + startingConsonant] + V[vowel] de otra manera
Arnauld
fuente
No '!'puede ser 33?
Jonathan Frech
@JonathanFrech cno es un byte. Es una cadena de 1 carácter. Dicho esto , cuando se aplica una operación aritmética, se coacciona un espacio 0mientras se coaccionan otros caracteres que no son dígitos NaN. Lo que significa que en c<1realidad debería funcionar como se esperaba. (Y c<33también funcionaría para caracteres que no sean dígitos, aunque esto es algo fortuito).
Arnauld
@JonathanFrech Addendum: c<1también sería cierto para "0"(lo que probablemente está bien si se garantiza que la entrada no contenga ningún número arábigo).
Arnauld
Gracias. No pensé que JavaScript tendría caracteres implementados como un solo byte, aunque lo intenté de todos modos. Sin embargo, parecía funcionar. Me alegra saber ahora por qué.
Jonathan Frech
2

Tcl, 529 bytes

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

Algoritmo

  1. Descomposición en índices de plomo, vocal y cola
  2. Primera búsqueda de representación alfabética intermedia
  3. Aplique un pase inicial para todas las transformaciones xn → nn / xm → nm
  4. Aplicar un pase final para las transformaciones restantes

Este algoritmo está desarrollado para los propósitos del desafío; La compensación es que se supone que la entrada no contiene caracteres alfabéticos latinos, ni que usa caracteres fuera del bloque Hangul U + AC00 como se describe en el desafío. Si este código real, mantendría todas las transformaciones en Jamo hasta el último pase.

Supongo que podría arrojar un poco más de capacidad mental para hacer crujir esas vocales y algunas de las repeticiones en la tabla de búsqueda, pero esto es tan bueno como lo obtengo hoy.

Pruebas

Asegúrese de que puede proporcionar la entrada UTF-8 al intérprete Tcl. Esto se logra más fácilmente con un simple archivo de texto UTF-8. Por desgracia, Tcl todavía no usa UTF-8 por defecto; Esto me costó 33 bytes.

Aquí está mi archivo de prueba (actualmente patético):

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

Notas

No sé nada sobre el idioma coreano (excepto lo poco que he aprendido aquí). Este es un primer intento, pendiente de revisión potencial debido a actualizaciones en la especificación de la pregunta.

Y, sobre eso, alguna información adicional es útil. En particular, no hay una correspondencia 1: 1 entre las consonantes de plomo y cola como parece sugerirse en el desafío. Los siguientes dos sitios ayudaron enormemente a descubrirlo:
Wikipedia: idioma coreano, Hangul
Wikipedia: Hangul Jamo (bloque Unicode)

Dúthomhas
fuente