Convierte entre teclado coreano de dos juegos y teclado qwerty

14

Introducción

Es algo así como el diseño del teclado DVORAK , pero MUCHO más difícil.

Hablemos primero del teclado coreano. Como puede ver en Wikipedia , hay una clave Kor / Eng para cambiar entre conjuntos de claves coreano e inglés.

Los coreanos a veces escriben mal: intentan escribir en coreano en un teclado qwerty o en inglés en un teclado de dos juegos.

Entonces, aquí está el problema: si se dan caracteres coreanos escritos en un teclado de dos juegos, conviértalos a caracteres alfabéticos escritos en el teclado qwerty. Si se le dan caracteres alfabéticos escritos en qwerty, cámbielo a teclado de dos juegos.

Teclado de dos juegos

Aquí está la distribución del teclado de dos conjuntos:

ㅂㅈㄷㄱㅅㅛㅕㅑㅐㅔ
 ㅁㄴㅇㄹㅎㅗㅓㅏㅣ
  ㅋㅌㅊㅍㅠㅜㅡ

y con la tecla shift:

ㅃㅉㄸㄲㅆㅛㅕㅑㅒㅖ

solo la fila superior cambia mientras que las otras no.

Sobre caracteres coreanos

si terminara aquí, podría ser fácil, pero no. Cuando escribes

dkssud, tprP!

la salida no se muestra de esta manera:

ㅇㅏㄴㄴㅕㅇ, ㅅㅔㄱㅖ!

pero de esta manera:

안녕, 세계!(means Hello, World!)

y hace las cosas mucho más difíciles.

Los caracteres coreanos se separan en tres partes: 'Choseong (consonante)', 'Jungseong (Vocal)' y 'Jongseong (consonante al final de la sílaba: puede estar en blanco)', y debe separarlo.

Afortunadamente, hay forma de hacerlo.

Cómo separar

Hay 19 Choseong, 21 Jungseong y 28 Jongseong (en blanco), y 0xAC00 es '가', primer carácter de los caracteres coreanos. Con esto, podemos separar los caracteres coreanos en tres partes. Aquí está el orden de cada uno y su posición en el teclado de dos juegos.

Elige un pedido:

ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ
r R s e E f a q Q t T d w W c z x v g

orden de jungseong:

ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ
k o i O j p u P h hk ho hl y n nj np nl b m ml l

orden de jongseong:

()ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ
()r R rt s sw sg e f fr fa fq ft fx fv fg a q qt t T d w c z x v g

Digamos Vamos (unicode value of some character) - 0xAC00es Korean_code, y el índice de choseong, Jungseong, Jongseong es Cho, Jung, Jong.

Entonces, Korean_codees(Cho * 21 * 28) + Jung * 28 + Jong

Aquí está el código javascript que separa el carácter coreano de este sitio web coreano, para su conveniencia.

var rCho = [ "ㄱ", "ㄲ", "ㄴ", "ㄷ", "ㄸ", "ㄹ", "ㅁ", "ㅂ", "ㅃ", "ㅅ", "ㅆ", "ㅇ", "ㅈ", "ㅉ", "ㅊ", "ㅋ", "ㅌ", "ㅍ", "ㅎ" ];
var rJung =[ "ㅏ", "ㅐ", "ㅑ", "ㅒ", "ㅓ", "ㅔ", "ㅕ", "ㅖ", "ㅗ", "ㅘ", "ㅙ", "ㅚ", "ㅛ", "ㅜ", "ㅝ", "ㅞ", "ㅟ", "ㅠ", "ㅡ", "ㅢ", "ㅣ" ];
var rJong = [ "", "ㄱ", "ㄲ", "ㄳ", "ㄴ", "ㄵ", "ㄶ", "ㄷ", "ㄹ", "ㄺ", "ㄻ", "ㄼ", "ㄽ", "ㄾ","ㄿ", "ㅀ", "ㅁ", "ㅂ", "ㅄ", "ㅅ", "ㅆ", "ㅇ", "ㅈ", "ㅊ", "ㅋ", "ㅌ", "ㅍ", "ㅎ" ];
var cho, jung, jong;
var sTest = "탱";
var nTmp = sTest.charCodeAt(0) - 0xAC00;
jong = nTmp % 28; // Jeongseong
jung = ((nTmp - jong) / 28 ) % 21 // Jungseong
cho = ( ( (nTmp - jong) / 28 ) - jung ) / 21 // Choseong

alert("Choseong:" + rCho[cho] + "\n" + "Jungseong:" + rJung[jung] + "\n" + "Jongseong:" + rJong[jong]);

Cuando se ensambla

  1. Tenga en cuenta que , , , , , , es una combinación de otros jungseongs.
ㅗ+ㅏ=ㅘ, ㅗ+ㅐ=ㅙ, ㅗ+ㅣ=ㅚ, ㅜ+ㅓ=ㅝ, ㅜ+ㅔ=ㅞ, ㅜ+ㅣ=ㅟ, ㅡ+ㅣ=ㅢ
  1. Choseong es necesario. Eso significa que, si frkse da, es decir ㄹㄱㅏ, puede cambiar de dos maneras: ㄺㅏy ㄹ가. Luego, debe convertirlo de una manera que haya elegido. Si jjjrjrdada, que es ㅓㅓㅓㄱㅓㄱ, que conducen s no tienen nada que pueda ser CHOSEONG, pero el cuarto tiene que se puede CHOSEONG, por lo que se transforma en ㅓㅓㅓ걱.

Otro ejemplo: 세계( tprP). Se puede cambiar a 섹ㅖ( (ㅅㅔㄱ)(ㅖ)), pero debido a que elegirong es necesario, se cambia a 세계( (ㅅㅔ)(ㄱㅖ))

Ejemplos

entrada 1

안녕하세요

salida 1

dkssudgktpdy

entrada 2

input 2

salida 2

ㅑㅞㅕㅅ 2

entrada 3

힘ㄴㄴ

salida 3

glass

entrada 4

아희(Aheui) is esolang which you can program with pure Korean characters.

salida 4

dkgml(모뎌ㅑ) ㅑㄴ ㄷ내ㅣ뭏 조ㅑ초 ㅛㅐㅕ ㅊ무 ㅔ갷ㄱ므 쟈소 ㅔㅕㄱㄷ ㅏㅐㄱㄷ무 촘ㄱㅁㅊㅅㄷㄱㄴ.

entrada 5

dkssud, tprP!

salida 5

안녕, 세계!

entrada 6

ㅗ디ㅣㅐ, 째깅! Hello, World!

salida 6

hello, World! ㅗ디ㅣㅐ, 째깅!

El código más corto gana. (en bytes)

Nueva regla para tu conveniencia

Puede descartar caracteres como los Aque no tienen su contraparte en el teclado de dos conjuntos. así Aheuique Aㅗ뎌ㅑestá bien. Pero, si cambia Aheuia 모뎌ㅑ, puede obtener -5 puntos, por lo que puede ganar 5 bytes.

Se pueden separar dos jungseongs (como a ㅗ+ㅏ). al igual rhkque 고ㅏ, o howa ㅗㅐㅈ. Pero si se combina (como rhkal o howa ㅙㅈ), usted puede ganar -5 puntos adicionales.

LegenDUST
fuente
En la sección de orden jungseong falta una de las letras. Veo 21 símbolos coreanos, pero solo 20 letras (pares) s. EDITAR: Parece faltar una prueba lposterior mlpara el símbolo coreano .
Kevin Cruijssen
@KevinCruijssen editado. l para ㅣ.
LegenDUST
1
A veces puede haber más de una interpretación. Por ejemplo, fjfaupodría interpretarse como 럶ㅕo 럴며. ¿Cómo resolvemos esto?
Nick Kennedy
1
@LegenDUST Bueno, no puedo leer una sola palabra coreano, así que tendré que ir con tu explicación. ; p Como tprPen el caso de prueba 5: esto se transforma en ㅅㅔㄱㅖ, donde es un elegido, es un jungseong y es un jongseong. Entonces, ¿no debería transformarse esto en 섷ㅖ(agrupado como (ㅅㅔㄱ)(ㅖ)) en lugar de 세계(agrupado como (ㅅㅔ)(ㄱㅖ))? En un comentario anterior, usted afirma que se interpreta escribiendo, por lo que esperaría ㅅㅔㄱtransformarme en . ¿O el coreano está escribiendo de derecha a izquierda en lugar de izquierda a derecha?
Kevin Cruijssen
1
@KevinCruijssen Archivo PDF de Unicode.org. AC00 ( ) a D7AF ( ).
LegenDUST

Respuestas:

6

Gelatina , 296 264 bytes

Ẏœṣjƭƒ
“ȮdȥŒ~ṙ7Ṗ:4Ȧịعʂ ="÷Ƥi-ẓdµ£f§ñỌ¥ẋaḣc~Ṡd1ÄḅQ¥_æ>VÑʠ|⁵Ċ³(Ė8ịẋs|Ṇdɼ⁼:Œẓİ,ḃṙɠX’ṃØẠs2ḟ€”A
“|zƒẉ“®6ẎẈ3°Ɠ“⁸)Ƙ¿’ḃ2’T€ị¢
¢ĖẈṪ$ÞṚƊ€
3£OŻ€3¦ŒpFḟ0Ɗ€J+“Ḥœ’,ƲyO2£OJ+⁽.[,Ʋ¤y¹ỌŒḊ?€µ¢ṖŒpZF€’ḋ588,28+“Ḥþ’Ʋ0;,ʋ/ṚƲ€ñṣ0ḊḢ+®Ṫ¤Ɗ;ṫ®$Ɗ¹Ḋ;⁶Ṫ⁼ṁ@¥¥Ƈ@¢ṪẈṪ‘;Ʋ€¤ḢƲ©?€ṭḢƲF2£żJ+⁽.[Ɗ$ẈṪ$ÞṚ¤ñỌ

Pruébalo en línea!

Un programa completo que toma una cadena como argumento y devuelve una cadena (que se imprime implícitamente). Esto funciona en tres pasadas: primero convierte todos los caracteres coreanos en listas de puntos de código para las letras latinas. Luego identifica y construye los caracteres coreanos compuestos. Finalmente, convierte cualquier letra latina perdida restante al equivalente coreano. Tenga en cuenta que otros caracteres y letras latinas que no aparecen en la especificación (p A. Ej. ) Se dejan solos.

Si se necesita la conversión a minúsculas de mayúsculas fuera de las especificaciones, esto se puede hacer a un costo de 10 bytes adicionales .

Explicación

Enlace auxiliar 1 : enlace diádico con argumentos x e y. x es una lista de pares de sublistas de búsqueda y reemplazo. y tendrá cada sublista de búsqueda reemplazada por la sublista de reemplazo correspondiente

Ẏ      | Tighten (reduce to a single list of alternating search and replace sublists)
     ƒ | Reduce using y as starting argument and the following link:
    ƭ  | - Alternate between using the following two links:
 œṣ    |   - Split at sublist
   j   |   - Join using sublist

Enlace auxiliar 2 : Lista de caracteres latinos / pares de caracteres en el orden que corresponde al orden Unicode de los caracteres coreanos

“Ȯ..X’          | Base 250 integer 912...
      ṃØẠ       | Base decompress into Latin letters (A..Za..z)
         s2     | Split into twos
           ḟ€”A | Filter out A from each (used as filler for the single characters)

Enlace de ayuda 3 : listas de caracteres latinos utilizados para Choseong, Jungseong y Jongseong

“|...¿’        | List of base 250 integers, [1960852478, 2251799815782398, 2143287262]
       ḃ2      | Convert to bijective base 2
         ’     | Decrease by 1
          T€   | List of indices of true values for each list
            ị¢ | Index into helper link 2

Enlace auxiliar 4 : Listas anteriores de caracteres latinos enumerados y ordenados en orden decreciente de longitud

¢         | Helper link 3 as a nilad
       Ɗ€ | For each list, the following three links as a monad
 Ė        | - Enumerate (i.e. prepend a sequential index starting at 1 to each member of the list)
    $Þ    | - Sort using, as a key, the following two links as a monad
  Ẉ       |   - Lengths of lists
   Ṫ      |   - Tail (this will be the length of the original character or characters)
      Ṛ   | - Reverse

Enlace principal : Mónada que toma una cadena Jelly como argumento y devuelve la cadena Jelly traducida

Sección 1 : Convierta bloques morfemicos a los puntos de código Unicode de los caracteres latinos correspondientes

Sección 1.1 : Obtenga la lista de caracteres latinos necesarios para hacer los bloques

3£      | Helper link 3 as a nilad (lists of Latin characters used for Choseong, Jungseong and Jongseong)
  O     | Convert to Unicode code points
   Ż€3¦ | Prepend a zero to the third list (Jongseong)

Sección 1.2 : Cree todas las combinaciones de estas letras (19 × 21 × 28 = 11,172 combinaciones en el orden léxico apropiado)

Œp      | Cartesian product
     Ɗ€ | For each combination:
  F     | - Flatten
   ḟ0   | - Filter zero (i.e. combinations with an empty Jonseong)

Sección 1.3 : Empareje los puntos de código Unicode de los bloques con la lista correspondiente de caracteres latinos, y utilícelos para traducir los bloques morfemicos en la cadena de entrada

       Ʋ   | Following as a monad
J          | - Sequence from 1..11172
 +“Ḥœ’     | - Add 44031
      ,    | - Pair with the blocks themelves
        y  | Translate the following using this pair of lists
         O | - The input string converted to Unicode code points

Sección 2 : Convierta los caracteres coreanos individuales en la salida de la sección 1 a los puntos de código del equivalente latino

          ¤  | Following as a nilad
2£           | Helper link 2 (list of Latin characters/character pairs in the order that corresponds to the Unicode order of the Korean characters)
  O          | Convert to Unicode code points
         Ʋ   | Following as a monad:
   J         | - Sequence along these (from 1..51)
    +⁽.[     | - Add 12592
        ,    | - Pair with list of Latin characters
           y | Translate the output from section 1 using this mapping

Sección 3 : Ordene los caracteres no traducidos en la salida de la sección 2 (funciona porque todo lo traducido del coreano ahora estará en una sublista y, por lo tanto, tendrá profundidad 1)

  ŒḊ?€  | For each member of list if the depth is 1:
¹       | - Keep as is
 Ọ      | Else: convert back from Unicode code points to characters
      µ | Start a new monadic chain using the output from this section as its argument

Sección 4 : Convierta bloques morfemicos de caracteres latinos en coreano

Sección 4.1 : Obtenga todas las combinaciones posibles de Choseong y Jungseong

¢    | Helper link 4 (lists of Latin characters enumerated and sorted in decreasing order of length)
 Ṗ   | Discard last list (Jongseong)
  Œp | Cartesian product

Sección 4.2 : Etiquete cada combinación con el punto de código Unicode para el bloque morfemico base (es decir, sin Jongseong)

                       Ʋ€ | For each Choseong/Jungseong combination
Z                         | - Transpose, so that we now have e.g. [[1,1],["r","k"]]
 F€                       | - Flatten each, joining the strings together
                    ʋ/    | - Reduce using the following as a dyad (effectively using the numbers as left argument and string of Latin characters as right)
                Ʋ         |   - Following links as a monad
   ’                      |     - Decrease by 1
    ḋ588,28               |     - Dot product with 21×28,28
           +“Ḥþ’          |     - Add 44032
                 0;       |     - Prepend zero; used for splitting in section 4.3 before each morphemic block (Ż won’t work because on a single integer it produces a range)
                   ,      |     - Pair with the string of Latin characters
                      Ṛ   |   - Reverse (so we now have e.g. ["rk", 44032]

Sección 4.3 : Reemplace estas cadenas de caracteres latinos en la salida de la sección 3 con los puntos de código Unicode del bloque morfemico base

ñ   | Call helper link 1 (effectively search and replace)
 ṣ0 | Split at the zeros introduced in section 4.2

Sección 4.4: Identifique si hay un Jongseong como parte de cada bloque morfemico

                                        Ʋ | Following as a monad:
Ḋ                                         | - Remove the first sublist (which won’t contain a morphemic block; note this will be restored later)
                                     €    | - For each of the other lists Z returned by the split in section 4.3 (i.e. each will have a morphemic block at the beginning):
                                  Ʋ©?     |   - If the following is true (capturing its value in the register in the process) 
             Ḋ                            |     - Remove first item (i.e. the Unicode code point for the base morphemic block introduced in section 4.3)
              ;⁶                          |     - Append a space (avoids ending up with an empty list if there is nothing after the morphemic block code point)
                                          |       (Output from the above will be referred to as X below)
                                ¤         |       * Following as a nilad (call this Y):
                        ¢                 |         * Helper link 4
                         Ṫ                |         * Jongseong
                              Ʋ€          |         * For each Jongseong Latin list:
                          Ẉ               |           * Lengths of lists
                           Ṫ              |           * Tail (i.e. length of Latin character string)
                            ‘             |           * Increase by 1
                             ;            |           * Prepend this (e.g. [1, 1, "r"]
                     ¥Ƈ@                  |     - Filter Y using X from above and the following criteria
                Ṫ                         |       - Tail (i.e. the Latin characters for the relevant Jongseong
                 ⁼ṁ@¥                     |       - is equal to the beginning of X trimmed to match the relevant Jongseong (or extended but this doesn’t matter since no Jongseong are a double letter)
                                  Ḣ       |       - First matching Jongseong (which since they’re sorted by descending size order will prefer the longer one if there is a matching shorter one)
           Ɗ                              | - Then: do the following as a monad (note this is now using the list Z mentioned much earlier):
      Ɗ                                   |   - Following as a monad
 Ḣ                                        |     - Head (the Unicode code point of the base morphemic block)
  +®Ṫ¤                                    |     - Add the tail of the register (the position of the matched Jongsepng in the list of Jongseong)
       ;                                  |   - Concatenate to:
        ṫ®$                               |     - The rest of the list after removing the Latin characters representing the Jongseong
            ¹                             | - Else: leave the list untouched (no matching Jongseong)
                                       ṭ  | - Prepend:
                                        Ḣ |   - The first sublist from the split that was removed at the beginning of this subsection

Sección 5 : Maneje los caracteres latinos restantes que coinciden con los coreanos pero que no son parte de un bloque morphemuc

F                   | Flatten
                ¤   | Following as a nilad
 2£                 | - Helper link 2 (Latin characters/pairs of characters in Unicode order of corresponding Korean character)
          $         | - Following as a monad
   ż     Ɗ          |   - zip with following as a monad
    J               |     - Sequence along helper link 2 (1..51)
     +⁽.[           |     - Add 12592
             $Þ     | - Sort using following as key
           Ẉ        |   - Lengths of lists
            Ṫ       |   - Tail (i.e. length of Latin string)
               Ṛ    | - Reverse
                 ñ  | Call helper link 1 (search Latin character strings and replace with Korean code points)
                  Ọ | Finally, convert all Unicode code points back to characters and implicitly output
Nick Kennedy
fuente
1
La salida es incorrecta: cuando puse , exceptué cor, pero dio cBor. Y no cambia ca . cantuvo que convertirse en ㅊ무, pero se convirtió en c무. Y también exceptué que los caracteres grandes que no aparecen en las especificaciones se descapitalizarían, pero puede estar bien.
LegenDUST
@LegenDUST se solucionó el problema de c. Utilicé Acomo marcador de posición para el segundo carácter de caracteres individuales, y por alguna razón, el siguiente capareció como a B. La conversión a minúsculas de otras letras podría hacerse, pero se siente como una complicación innecesaria a lo que ya es un desafío difícil.
Nick Kennedy
Entiendo que esto es difícil. Así que agregué una nueva regla: si descapitalizas, puedes ganar 5 bytes. Pero esto está bien.
LegenDUST
3

JavaScript (Node.js) , 587 582 575 569 557 554 550 549 bytes

No lo sabías string.charCodeAt() == string.charCodeAt(0).

s=>s.replace(eval(`/[ㄱ-힣]|${M="(h[kol]?|n[jpl]?|ml?|[bi-puyOP])"}|([${S="rRseEfaqQtTdwWczxvg"}])(${M}((s[wg]|f[raqtxvg]|qt|[${S}])(?!${M}))?)?/g`,L="r,R,rt,s,sw,sg,e,E,f,fr,fa,fq,ft,fx,fv,fg,a,q,Q,qt,t,T,d,w,W,c,z,x,v,g,k,o,i,O,j,p,u,P,h,hk,ho,hl,y,n,nj,np,nl,n,m,ml,l".split`,`,l=L.filter(x=>!/[EQW]/.test(x)),I="indexOf"),(a,E,A,B,C,D)=>a<"~"?E?X(E):A&&C?F(43193+S[I](A)*588+L[I](C)*28+l[I](D)):X(A)+X(C)+X(D):(b=a.charCodeAt()-44032)<0?L[b+31439]||a:S[b/588|0]+L[30+b/28%21|0]+["",...l][b%28],F=String.fromCharCode,X=n=>n?F(L[I](n)+12593):"")

Pruébalo en línea!

547 si los caracteres fuera de los alfabetos y los jamos coreanos pueden ignorarse.

De acuerdo, luché por tanto tiempo para escribir esto, pero esto debería funcionar. No se usa jamo / sílaba coreana porque son demasiado caros (3 bytes por uso). Se usa en la expresión regular para guardar bytes.

s=>                                                    // Main Function:
 s.replace(                                            //  Replace all convertible strings:
  eval(
   `/                                                  //   Matching this regex:
    [ㄱ-힣]                                             //   ($0) All Korean jamos and syllables
    |${M="(h[kol]?|n[jpl]?|ml?|[bi-puyOP])"}           //   ($1) Isolated jungseong codes
    |([${S="rRseEfaqQtTdwWczxvg"}])                    //   ($2) Choseong codes (also acts as lookup)
     (                                                 //   ($3) Jungseong and jongseong codes:
      ${M}                                             //   ($4)  Jungseong codes
      (                                                //   ($5)  Jongseong codes:
       (                                               //   ($6)
        s[wg]|f[raqtxvg]|qt                            //          Diagraphs unique to jongseongs
        |[${S}]                                        //          Or jamos usable as choseongs
       ) 
       (?!${M})                                        //         Not linked to the next jungseong
      )?                                               //        Optional to match codes w/o jongseong
     )?                                                //       Optional to match choseong-only codes
   /g`,                                                //   Match all
   L="(...LOOKUP TABLE...)".split`,`,                  //   Lookup table of codes in jamo order
   l=L.filter(x=>!/[EQW]/.test(x)),                    //   Jongseong lookup - only first half is used
   I="indexOf"                                         //   [String|Array].prototype.indexOf
  ),
  (a,E,A,B,C,D)=>                                      //   Using this function:
   a<"~"?                                              //    If the match is code (alphabets):
    E?                                                 //     If isolated jungseongs code:
     X(E)                                              //      Return corresponding jamo
    :A&&C?                                             //     Else if complete syllable code:
     F(43193+S[I](A)*588+L[I](C)*28+l[I](D))           //      Return the corresponding syllable
    :X(A)+X(C)+X(D)                                    //     Else return corresponding jamos joined
   :(b=a.charCodeAt()-44032)<0?                        //    Else if not syllable:
    L[b+31439]||a                                      //     Return code if jamo (if not, ignore)
   :S[b/588|0]+L[30+b/28%21|0]+["",...l][b%28],        //    Else return code for the syllable
  F=String.fromCharCode,                               //   String.fromCharCode
  X=n=>                                                //   Helper function to convert code to jamo
   n?                                                  //    If not undefined:
    F(L[I](n)+12593)                                   //     Return the corresponding jamo
   :""                                                 //    Else return empty string
 )
Shieru Asakoto
fuente
2

Wolfram Language (Mathematica) , 405 401 400 bytes

c=CharacterRange
p=StringReplace
q=StringReverse
r=Reverse
t=Thread
j=Join
a=j[alphabet@"Korean",4520~c~4546]
x=j[#,r/@#]&@t[a->Characters@"rRseEfaqQtTdwWczxvgkoiOjpuPh"~j~StringSplit@"hk ho hl y n nj np nl b m ml l r R rt s sw sg e f fr fa fq ft fx fv fg a q qt t T d w c z x v g"]
y=t[""<>r@#&/@Tuples@TakeList[Insert[a,"",41]~p~x~p~x,{19,21,28}]->44032~c~55203]
f=q@p[q@#,#2]&
g=f[#,r/@y]~p~x~f~y&

Pruébalo en línea!

Ligeramente no golfista

Para probar esto en Mathematica simplemente reemplace alphabetconAlphabet ; sin embargo, TIO no es compatible con Wolfram Cloud, así que definí Alphabet["Korean"]en el encabezado.

Primero descomponemos todas las sílabas de Hangul al alfabeto Hangul, luego intercambiamos caracteres latinos y Hangul, luego recomponemos las sílabas.

lirtosiast
fuente
1
input 2Resultados de casos de prueba en ㅑㅜㅔㅕㅅ 2lugar de ㅑㅞㅕㅅ 2en su TIO. Aunque sucede lo mismo en la solución en la que estaba trabajando, ya que ambos y jungseong, y tenía la impresión de que solo se elegiríanongong + jungseong + jongseong o chooseong + jungseong + vacío. Le pedí a OP que verificara por qué se ㅜㅔhizo .
Kevin Cruijssen
@KevinCruijssen ㅞ (np) es un jungseong por derecho propio
Nick Kennedy
1
Esto no parece funcionar correctamente para las consonantes o vocales de dos caracteres. Por ejemplo, fnpfadebería ser un solo personaje, pero en su lugar termina como루ㅔㄹㅁ
Nick Kennedy,
Arreglo en progreso. No debería costar demasiado.
lirtosiast
2

Java 19, 1133 1126 1133 bytes

s->{String r="",k="ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ",K[]=k.split(" "),a="r R s e E f a q Q t T d w W c z x v g k o i O j p u P h hk ho hl y n nj np nl b m ml l r R rt s sw sg e f fr fa fq ft fx fv fg a q qt t T d w c z x v g";var A=java.util.Arrays.asList(a.split(" "));k=k.replace(" ","");int i,z,y,x=44032;for(var c:s.toCharArray())if(c>=x&c<55204){z=(i=c-x)%28;y=(i=(i-z)/28)%21;s=s.replace(c+r,r+K[0].charAt((i-y)/21)+K[1].charAt(y)+(z>0?K[2].charAt(z-1):r));}for(var c:s.split(r))r+=c.charAt(0)<33?c:(i=k.indexOf(c))<0?(i=A.indexOf(c))<0?c:k.charAt(i):A.get(i);for(i=r.length()-1;i-->0;r=z>0?r.substring(0,i)+(char)(K[0].indexOf(r.charAt(i))*588+K[1].indexOf(r.charAt(i+1))*28+((z=K[2].indexOf(r.charAt(i+2)))<0?0:z+1)+x)+r.substring(z<0?i+2:i+3):r)for(z=y=2;y-->0;)z&=K[y].contains(r.charAt(i+y)+"")?2:0;for(var p:"ㅗㅏㅘㅗㅐㅙㅗㅣㅚㅜㅓㅝㅜㅔㅞㅜㅣㅟㅡㅣㅢ".split("(?<=\\G...)"))r=r.replace(p.substring(0,2),p.substring(2));return r;}

Salidas con letras mayúsculas ASDFGHJKLZXCVBNMsin cambios, ya que .toLowerCase()cuesta más que la bonificación de -5.

Atrás +7 bytes como corrección de errores para caracteres no coreanos por encima del valor Unicode 20,000 (gracias @NickKennedy por notarlo).

Pruébalo en línea.

Explicación:

s->{                         // Method with String as both parameter and return-type
  String r="",               //  Result-String, starting empty
         k="ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ",
                             //  String containing the Korean characters
         K[]=k.split(" "),   //  Array containing the three character-categories
         a="r R s e E f a q Q t T d w W c z x v g k o i O j p u P h hk ho hl y n nj np nl b m ml l r R rt s sw sg e f fr fa fq ft fx fv fg a q qt t T d w c z x v g"; 
                             //  String containing the English characters
  var A=java.util.Arrays.asList(a.split(" "));
                             //  List containing the English character-groups
  k=k.replace(" ","");       //  Remove the spaces from the Korean String
  int i,z,y,                 //  Temp integers
      x=44032;               //  Integer for 0xAC00
  for(var c:s.toCharArray()) //  Loop over the characters of the input:
    if(c>=x&c<55204){        //   If the unicode value is in the range [44032,55203]
                             //   (so a Korean combination character):
      z=(i=c-x)%28;          //    Set `i` to this unicode value - 0xAC00,
                             //    And then `z` to `i` modulo-28
      y=(i=(i-z)/28)%21;     //    Then set `i` to `i`-`z` integer divided by 28
                             //    And then `y` to `i` modulo-21
      s=s.replace(c+r,       //    Replace the current non-Korean character with:
        r+K[0].charAt((i-y)/21)
                             //     The corresponding choseong
         +K[1].charAt(y)     //     Appended with jungseong
         +(z>0?K[2].charAt(z-1):r));}
                             //     Appended with jongseong if necessary
  for(var c:s.split(r))      //  Then loop over the characters of the modified String:
    r+=                      //   Append to the result-String:
       c.charAt(0)<33?       //    If the character is a space:
        c                    //     Simply append that space
       :(i=k.indexOf(c))<0?  //    Else-if the character is NOT a Korean character:
         (i=A.indexOf(c))<0? //     If the character is NOT in the English group List:
          c                  //      Simply append that character
         :                   //     Else:
          k.charAt(i)        //      Append the corresponding Korean character
       :                     //    Else:
        A.get(i);            //     Append the corresponding letter
  for(i=r.length()-1;i-->0   //  Then loop `i` in the range (result-length - 2, 0]:
      ;                      //    After every iteration:
       r=z>0?                //     If a group of Korean characters can be merged:
          r.substring(0,i)   //      Leave the leading part of the result unchanged
          +(char)(K[0].indexOf(r.charAt(i))
                             //      Get the index of the first Korean character,
                   *588      //      multiplied by 588
                  +K[1].indexOf(r.charAt(i+1))
                             //      Get the index of the second Korean character,
                   *28       //      multiplied by 28
                  +((z=K[2].indexOf(r.charAt(i+2)))
                             //      Get the index of the third character
                    <0?      //      And if it's a Korean character in the third group:
                      0:z+1) //       Add that index + 1
                  +x         //      And add 0xAC00
                 )           //      Then convert that integer to a character
          +r.substring(z<0?i+2:i+3) 
                             //      Leave the trailing part of the result unchanged as well
         :                   //     Else (these characters cannot be merged)
          r)                 //      Leave the result the same
     for(z=y=2;              //   Reset `z` to 2
         y-->0;)             //   Inner loop `y` in the range (2, 0]:
       z&=                   //    Bitwise-AND `z` with:
         K[y].contains(      //     If the `y`'th Korean group contains
           r.charAt(i+y)+"")?//     the (`i`+`y`)'th character of the result
          2                  //      Bitwise-AND `z` with 2
         :                   //     Else:
          0;                 //      Bitwise-AND `z` with 0
                             //   (If `z` is still 2 after this inner loop, it means
                             //    Korean characters can be merged)
  for(var p:"ㅗㅏㅘㅗㅐㅙㅗㅣㅚㅜㅓㅝㅜㅔㅞㅜㅣㅟㅡㅣㅢ".split("(?<=\\G...)"))
                             //  Loop over these Korean character per chunk of 3:
    r=r.replace(p.substring(0,2),
                             //   Replace the first 2 characters in this chunk
         p.substring(2));    //   With the third one in the result-String
  return r;}                 //  And finally return the result-String
Kevin Cruijssen
fuente
1
son de 44032 a 55203. Ya tienes la ubicación de inicio codificada. El final es justo44032 + 19×21×28 - 1
Nick Kennedy,
Funciona bien ahora. Pensé que ya te había votado pero no lo había hecho, ¡así que aquí tienes!
Nick Kennedy