Converter entre teclado coreano de dois conjuntos e teclado qwerty

14

Introdução

É um pouco como o layout do teclado DVORAK , mas muito mais difícil.

Vamos falar sobre o teclado coreano primeiro. Como você pode ver na Wikipedia , existe uma chave Kor / Eng para alternar entre os conjuntos de chaves coreano e inglês.

Às vezes, os coreanos digitam errado: eles tentam escrever em coreano em um teclado qwerty ou em inglês em um teclado de dois conjuntos.

Então, aqui está o problema: se os caracteres coreanos digitados no teclado de dois conjuntos forem convertidos para caracteres alfabéticos digitados no teclado qwerty. Se os caracteres alfabéticos digitados em qwerty forem alterados, mude para teclado de dois conjuntos.

Teclado de dois conjuntos

Aqui está o layout do teclado de dois conjuntos:

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

e com a tecla shift:

ㅃㅉㄸㄲㅆㅛㅕㅑㅒㅖ

apenas a linha superior muda enquanto as outras não.

Sobre caracteres coreanos

se terminasse aqui, poderia ser fácil, mas não. Quando você digita

dkssud, tprP!

a saída não é mostrada desta maneira:

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

mas desta maneira:

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

e isso torna as coisas muito mais difíceis.

Os caracteres coreanos se separam em três partes: 'Choseong (consoante)', 'Jungseong (vogal)' e 'Jongseong (consoante no final da sílaba: pode ficar em branco)', e você deve separá-lo.

Felizmente, há uma maneira de fazer isso.

Como separar

Existem 19 Choseong, 21 Jungseong e 28 Jongseong (com espaço em branco), e 0xAC00 é '가', primeiro caractere dos caracteres coreanos. Usando isso, podemos separar caracteres coreanos em três partes. Aqui está a ordem de cada uma e sua posição no teclado de dois conjuntos.

ordem escolhida:

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

ordem do jungseong:

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

ordem 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

Vamos dizer (unicode value of some character) - 0xAC00é Korean_code, eo índice de choseong, jungseong, Jongseong é Cho, Jung,Jong .

Então Korean_codeé(Cho * 21 * 28) + Jung * 28 + Jong

Aqui está o código javascript que separa o caractere coreano deste site coreano, para sua conveniência.

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

Quando montado

  1. Note-se que , , , , , , é uma combinação de outros jungseongs.
ㅗ+ㅏ=ㅘ, ㅗ+ㅐ=ㅙ, ㅗ+ㅣ=ㅚ, ㅜ+ㅓ=ㅝ, ㅜ+ㅔ=ㅞ, ㅜ+ㅣ=ㅟ, ㅡ+ㅣ=ㅢ
  1. Choseong é necessário. Isso significa que, se frkfor dado, ou seja ㄹㄱㅏ, pode mudar de duas maneiras: ㄺㅏe ㄹ가. Então, você deve convertê-lo de uma maneira que escolheu. Se jjjrjrdado, ou seja ㅓㅓㅓㄱㅓㄱ, os líderes não têm nada que possa ser escolhido, mas o quarto tem que pode ser escolhido, então é transformado em ㅓㅓㅓ걱.

Outro exemplo: 세계( tprP). Pode ser alterado para 섹ㅖ( (ㅅㅔㄱ)(ㅖ)), mas, como é necessário escolher uma opção, ele é alterado para 세계()(ㅅㅔ)(ㄱㅖ) )

Exemplos

entrada 1

안녕하세요

saída 1

dkssudgktpdy

entrada 2

input 2

saída 2

ㅑㅞㅕㅅ 2

entrada 3

힘ㄴㄴ

saída 3

glass

entrada 4

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

saída 4

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

entrada 5

dkssud, tprP!

saída 5

안녕, 세계!

entrada 6

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

saída 6

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

O menor código vence. (em bytes)

Nova regra para sua conveniência

Você pode descartar caracteres como os Aque não têm seu equivalente no teclado de dois conjuntos. de modo Aheuique Aㅗ뎌ㅑé OK. Mas, se você mudar Aheuipara 모뎌ㅑ, poderá obter -5 pontos e ganhar 5 bytes.

Você pode separar dois jungseongs (como a ㅗ+ㅏ). gosta rhkde 고ㅏou howpara ㅗㅐㅈ. Mas se você combiná-lo (como rhka ou howa ㅙㅈ), você pode ganhar -5 pontos adicionais.

LegenDUST
fonte
Na seção de ordem do jungseong, falta uma das letras. Eu vejo 21 símbolos coreanos, mas apenas 20 letras (-par) s. EDIT: Parece estar faltando um teste ldepois mlpara o símbolo coreano .
Kevin Cruijssen
@KevinCruijssen editado. l para ㅣ.
LegenDUST
1
Às vezes, pode haver mais de uma interpretação. Por exemplo, fjfaupoderia ser interpretado como 럶ㅕou 럴며. Como resolvemos isso?
Nick Kennedy
1
@LegenDUST Bem, não consigo ler uma única palavra coreana, então terei que seguir sua explicação. ; p Como tprPno caso de teste 5: isso se transforma em ㅅㅔㄱㅖ, onde é umongo escolhido, é um jungseong e é um jongseong. Então isso não deveria se transformar em 섷ㅖ(agrupado como (ㅅㅔㄱ)(ㅖ)) em vez de 세계(agrupado como (ㅅㅔ)(ㄱㅖ))? Em um comentário anterior, você afirma que é interpretado digitando, então eu esperaria ㅅㅔㄱme transformar em . Ou o coreano está digitando da direita para a esquerda em vez da esquerda para a direita?
Kevin Cruijssen 27/05/19
1
@KevinCruijssen Arquivo PDF de Unicode.org. AC00 ( ) a D7AF ( ).
LegenDUST 31/05/19

Respostas:

6

Jelly , 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+⁽.[Ɗ$ẈṪ$ÞṚ¤ñỌ

Experimente online!

Um programa completo que usa uma string como argumento e retorna uma string (que é impressa implicitamente). Isso funciona em três passagens: primeiro, converte todos os caracteres coreanos em listas de pontos de código para as letras latinas. Em seguida, ele identifica e constrói os caracteres coreanos compostos. Finalmente, transforma todas as letras latinas perdidas restantes no equivalente coreano. Observe que outros caracteres e letras latinas que não aparecem na especificação (por exemplo A) são deixados em paz.

Se for necessária a conversão para minúsculas de letras maiúsculas fora da especificação, isso pode ser feito a um custo de 10 bytes adicionais .

Explicação

Link auxiliar 1 : link diádico com argumentos x e y. x é uma lista de pares de pesquisa e substitui sublistas. y substituirá cada sublist de pesquisa pela sublist de substituir correspondente

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

Link auxiliar 2 : lista de caracteres latinos / pares de caracteres na ordem que corresponde à ordem Unicode dos 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)

Link auxiliar 3 : listas de caracteres latinos usados ​​para Choseong, Jungseong e 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

Link auxiliar 4 : listas acima de caracteres latinos enumerados e classificados em ordem decrescente de comprimento

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

Link principal : Mônada que pega uma string Jelly como argumento e retorna a string Jelly traduzida

Seção 1 : Converter blocos morfêmicos nos pontos de código Unicode dos caracteres latinos correspondentes

Seção 1.1 : Obtenha a lista de caracteres em latim necessários para criar os blocos

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)

Seção 1.2 : Crie todas as combinações dessas letras (19 × 21 × 28 = 11.172 combinações na ordem lexical apropriada)

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

Seção 1.3 : Emparelhe os pontos de código Unicode dos blocos com a lista correspondente de caracteres latinos e use-os para converter os blocos morfêmicos na string 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

Seção 2 : Converta os caracteres coreanos individuais na saída da seção 1 nos pontos de código do 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

Seção 3 : Arrume caracteres não traduzidos na saída da seção 2 (funciona porque qualquer coisa traduzida do coreano agora estará em uma sublist e, portanto, terá profundidade 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

Seção 4 : Converter blocos morfêmicos de caracteres latinos em coreano

Seção 4.1 : obtenha todas as combinações possíveis de Choseong e Jungseong

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

Seção 4.2 : Rotule cada combinação com o ponto de código Unicode para o bloco morfêmico básico (ou seja, sem 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]

Seção 4.3 : Substitua essas cadeias de caracteres latinos na saída da seção 3 pelos pontos de código Unicode do bloco morfêmico base

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

Seção 4.4: Identifique se existe um Jongseong como parte de cada bloco morfêmico

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

Seção 5 : Manuseie os caracteres latinos restantes que correspondem aos coreanos, mas não fazem parte de um bloco morfêmico

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
fonte
1
A saída está errada: quando eu coloquei , exceto cor, mas deu cBor. E isso não muda cpara . canteve que se converter em ㅊ무, mas se converteu em c무. E também excluí que caracteres grandes que não aparecem nas especificações seriam decapitalizados, mas pode ser bom.
LegenDUST
@LegenDUST o problema c foi corrigido. Eu usei Acomo espaço reservado para o segundo caractere de caracteres únicos e, por algum motivo, o seguinte cfoi lançado como a B. A conversão para letras minúsculas de outras letras poderia ser feita, mas parece uma complicação desnecessária para o que já é um desafio difícil.
Nick Kennedy
Eu entendo isso é difícil. Então, adicionei uma nova regra: se você decapitalizar, poderá ganhar 5 bytes. Mas tudo bem.
LegenDUST
3

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

Se você não sabia disso 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):"")

Experimente online!

547 se caracteres fora dos alfabetos e jamos coreanos puderem ser ignorados.

Ok, lutei por tanto tempo para escrever isso, mas isso deve funcionar. Nenhum jamo / sílaba coreana é usado porque eles são muito caros (3 bytes por uso). Usado na expressão regular para salvar 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
fonte
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&

Experimente online!

Ligeiramente não-destruído

Para testar isso no Mathematica, basta substituir alphabetpor Alphabet; no entanto, o TIO não suporta a Wolfram Cloud, então eu definiAlphabet["Korean"] no cabeçalho.

Primeiro decompomos todas as sílabas Hangul no alfabeto Hangul, depois trocamos caracteres latinos e Hangul e recompomos as sílabas.

lirtosiast
fonte
1
O caso de teste input 2resulta em ㅑㅜㅔㅕㅅ 2vez de ㅑㅞㅕㅅ 2em seu TIO. Embora o mesmo acontece na solução eu estava a trabalhar, uma vez que ambos e são jungseong, e estava sob a impressão única CHOSEONG + jungseong + jongseong ou CHOSEONG + jungseong + vazio seria combinada. Eu pedi a OP para verificação por que ㅜㅔse tornou .
Kevin Cruijssen 27/05/19
@KevinCruijssen ㅞ (np) é um jungseong por si só
Nick Kennedy
1
Isso não parece funcionar corretamente para consoantes ou vogais de dois caracteres. Por exemplo, fnpfadeve ser um personagem único, mas acaba sendo:루ㅔㄹㅁ
Nick Kennedy
Correção em andamento. Não deve custar muito.
Lirtosiast 28/05/19
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;}

Saídas com letras maiúsculas ASDFGHJKLZXCVBNMinalteradas, pois .toLowerCase()custa mais que o bônus -5.

Voltar +7 bytes como uma correção de bug para caracteres não coreanos acima do valor unicode 20.000 (obrigado @NickKennedy por perceber).

Experimente online.

Explicação:

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
fonte
1
eles são de 44032 a 55203. Você já tem o local de início codificado. O fim é justo44032 + 19×21×28 - 1
Nick Kennedy
Funciona bem agora. Pensei que já tinha te votado, mas não o fiz, então aqui está!
Nick Kennedy