Konwertuj między koreańską dwuskładnikową klawiaturą a klawiaturą qwerty

14

Wprowadzenie

Jest trochę podobny do układu klawiatury DVORAK , ale DUŻO trudniejszy.

Porozmawiajmy najpierw o koreańskiej klawiaturze. Jak widać w Wikipedii , istnieje klucz Kor / Eng do zmiany między zestawami kluczy koreańskiego i angielskiego.

Koreańczycy czasami źle wpisują: próbują pisać po koreańsku na klawiaturze qwerty lub po angielsku na dwuczęściowej klawiaturze.

Oto problem: jeśli podano koreańskie znaki wpisywane na dwuczęściowej klawiaturze, przekonwertuj je na znaki alfabetyczne wpisane na klawiaturze qwerty. Jeśli podano znaki alfabetyczne wpisane w qwerty, zmień je na klawiaturę z dwoma zestawami.

Dwuczęściowa klawiatura

Oto dwuczęściowy układ klawiatury:

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

i klawiszem Shift:

ㅃㅉㄸㄲㅆㅛㅕㅑㅒㅖ

zmienia się tylko górny wiersz, a inne nie.

O koreańskich znakach

jeśli to się tu skończy, może być łatwo, ale nie. Kiedy piszesz

dkssud, tprP!

dane wyjściowe nie są wyświetlane w ten sposób:

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

ale w ten sposób:

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

i to znacznie utrudnia.

Koreańskie znaki dzielą się na trzy części: „Choseong (spółgłoska)”, „Jungseong (samogłoska)” i „Jongseong (spółgłoska na końcu sylaby: może być pusta)”, i trzeba to rozdzielić.

Na szczęście jest na to sposób.

Jak oddzielić

Jest 19 Choseong, 21 Jungseong i 28 Jongseong (z pustym miejscem), a 0xAC00 to „가”, pierwszy znak koreańskich znaków. Korzystając z tego, możemy podzielić koreańskie znaki na trzy części. Oto kolejność każdego z nich i jego pozycja na dwuczęściowej klawiaturze.

wybierz zamówienie:

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

zamówienie jungseong:

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

zamówienie 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

Powiedzmy Chodźmy (unicode value of some character) - 0xAC00jest Korean_code, a indeks CHOSEONG, Jungseong, Jongseong jest Cho, Jung, Jong.

Więc Korean_codejest(Cho * 21 * 28) + Jung * 28 + Jong

Oto kod javascript, który oddziela koreański znak od tej koreańskiej witryny, dla Twojej wygody.

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

Po zmontowaniu

  1. Należy zauważyć, że , , , , , , jest kombinacją innych jungseongs.
ㅗ+ㅏ=ㅘ, ㅗ+ㅐ=ㅙ, ㅗ+ㅣ=ㅚ, ㅜ+ㅓ=ㅝ, ㅜ+ㅔ=ㅞ, ㅜ+ㅣ=ㅟ, ㅡ+ㅣ=ㅢ
  1. Choseong jest konieczny. Oznacza to, że jeśli frkzostanie podany, to ㄹㄱㅏznaczy może się zmienić na dwa sposoby: ㄺㅏi ㄹ가. Następnie musisz przekształcić go w sposób, który wybrał. Jeśli jjjrjrpodano, to znaczy ㅓㅓㅓㄱㅓㄱ, że wiodący nie mają niczego, co można by wybrać, ale czwarty ma to, co można wybrać, więc zostało zmienione na ㅓㅓㅓ걱.

Kolejny przykład: 세계( tprP). Można go zmienić na 섹ㅖ( (ㅅㅔㄱ)(ㅖ)), ale ponieważ wybranie opcji jest konieczne, zmieniono na 세계( (ㅅㅔ)(ㄱㅖ))

Przykłady

wejście 1

안녕하세요

wyjście 1

dkssudgktpdy

wejście 2

input 2

wyjście 2

ㅑㅞㅕㅅ 2

wejście 3

힘ㄴㄴ

wyjście 3

glass

wejście 4

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

wyjście 4

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

wejście 5

dkssud, tprP!

wyjście 5

안녕, 세계!

wejście 6

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

wyjście 6

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

Najkrótszy kod wygrywa. (w bajtach)

Nowa zasada dla Twojej wygody

Możesz odrzucić znaki, Aktóre nie mają swojego odpowiednika na dwuczęściowej klawiaturze. tak Aheuiaby Aㅗ뎌ㅑjest OK. Ale jeśli zmienisz Aheuina 모뎌ㅑ, możesz uzyskać -5 punktów, dzięki czemu możesz zarobić 5 bajtów.

Możesz oddzielić dwa jungseongi (lubię to ㅗ+ㅏ). jak rhkdo 고ㅏ, lub howdo ㅗㅐㅈ. Ale jeśli połączyć je (jak rhkna lub howdo ㅙㅈ), można zarobić dodatkowe -5 punktów.

LegenDUST
źródło
W sekcji zamówień jungseong brakuje jednej z liter. Widzę 21 koreańskich symboli, ale tylko 20 liter (-par). EDYCJA: Wydaje się, że brakuje próby lpo mlkoreańskim symbolu .
Kevin Cruijssen
Edytowano @KevinCruijssen. l dla ㅣ.
LegenDUST
1
Czasami może istnieć więcej niż jedna interpretacja. Na przykład fjfaumoże być interpretowany jako 럶ㅕlub 럴며. Jak to rozwiązać?
Nick Kennedy
1
@LegenDUST Cóż, nie mogę odczytać ani jednego słowa po koreańsku, więc muszę iść z twoim wyjaśnieniem. ; p Jak tprPw przypadku testowym 5: przekształca się w ㅅㅔㄱㅖ, gdzie jest choseong, jest jungseong i jest jongseong. Czy to nie powinno przekształcić się w 섷ㅖ(zgrupowane jak (ㅅㅔㄱ)(ㅖ)) zamiast 세계(zgrupowane jak (ㅅㅔ)(ㄱㅖ))? We wcześniejszym komentarzu stwierdzasz, że jest on interpretowany przez pisanie na klawiaturze, więc spodziewałbym ㅅㅔㄱsię, że przekształcę się w . A może koreański pisze od prawej do lewej zamiast od lewej do prawej?
Kevin Cruijssen
1
@KevinCruijssen plik PDF z Unicode.org. AC00 ( ) do D7AF ( ).
LegenDUST

Odpowiedzi:

6

Galaretka , 296 264 bajtów

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

Wypróbuj online!

Pełny program, który pobiera ciąg znaków jako argument i zwraca ciąg znaków (który jest domyślnie drukowany). Działa to w trzech przebiegach: najpierw konwertuje wszystkie koreańskie znaki na listy punktów kodowych dla liter łacińskich. Następnie identyfikuje i buduje złożone znaki koreańskie. Na koniec zamienia wszystkie pozostałe zbłąkane litery łacińskie na koreański odpowiednik. Zauważ, że inne znaki i litery łacińskie, które nie pojawiają się w specyfikacji (np. A) Są pozostawione same sobie.

Jeśli konieczna jest konwersja na małe litery wielkich liter poza specyfikacją, można to zrobić kosztem dodatkowych 10 bajtów .

Wyjaśnienie

Łącze pomocnicze 1 : ogniwo diademowe z argumentami x i y. x to lista par wyszukiwania i zamień listy podrzędne. y będzie zamieniać każdą podlistę wyszukiwania na odpowiednią podlistę zastępczą

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

Łącze pomocnicze 2 : Lista znaków łacińskich / par znaków w kolejności odpowiadającej kolejności znaków koreańskich w Unicode

“Ȯ..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)

Łącze pomocnicze 3 : Listy znaków łacińskich używanych w Choseong, Jungseong i 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

Łącze pomocnicze 4 : Powyższe listy znaków łacińskich wyliczone i posortowane w kolejności malejącej długości

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

Główny link : Monada, która przyjmuje argument Jelly jako argument i zwraca przetłumaczony ciąg Jelly

Część 1 : Konwertuj bloki morfemiczne na punkty kodowe Unicode odpowiednich znaków łacińskich

Sekcja 1.1 : Uzyskaj listę łacińskich znaków potrzebnych do wykonania bloków

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)

Sekcja 1.2 : Utwórz wszystkie kombinacje tych liter (19 × 21 × 28 = 11172 kombinacji w odpowiedniej kolejności leksykalnej)

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

Sekcja 1.3 : Sparuj punkty kodu Unicode bloków z odpowiednią listą znaków łacińskich i użyj ich do przetłumaczenia bloków morfemicznych w ciągu wejściowym

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

Część 2 : Konwertuj poszczególne znaki koreańskie w danych wyjściowych z sekcji 1 na punkty kodowe odpowiednika łacińskiego

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

Część 3 : Uporządkuj nieprzetłumaczone znaki w danych wyjściowych z sekcji 2 (działa, ponieważ wszystko przetłumaczone z języka koreańskiego będzie teraz na liście podrzędnej, a zatem będzie miało głębokość 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

Część 4 : Konwertuj morfemiczne bloki znaków łacińskich na koreański

Sekcja 4.1 : Uzyskaj wszystkie możliwe kombinacje Choseong i Jungseong

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

Sekcja 4.2 : Oznacz każdą kombinację punktem kodu Unicode dla podstawowego bloku morfemicznego (tj. Bez 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]

Sekcja 4.3 : Zamień te ciągi znaków łacińskich w danych wyjściowych z sekcji 3 na punkty kodu Unicode podstawowego bloku morfemicznego

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

Sekcja 4.4: Ustal, czy istnieje Jongseong jako część każdego bloku morfemicznego

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

Część 5 : Postępuj z pozostałymi znakami łacińskimi, które pasują do koreańskich, ale nie są częścią bloku 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
źródło
1
Wyjście jest złe: kiedy wstawiłem cor, wyjątek , ale dał cBor. I nie zmienia się cna . canmusiał przekształcić się w ㅊ무, ale przekształcił się w c무. I poza tym duże litery, które nie pojawiają się w specyfikacji, zostałyby zdekapitalizowane, ale może być w porządku.
LegenDUST
@ LegenDUST problem c został naprawiony. Użyłem Ajako symbolu zastępczego dla drugiej postaci pojedynczych znaków iz jakiegoś powodu cnastępny pojawił się jako B. Można zamienić małe litery na inne litery, ale wydaje się to niepotrzebną komplikacją tego, co już jest trudnym wyzwaniem.
Nick Kennedy
Rozumiem, że to trudne. Dodałem więc nową zasadę: jeśli zdekapitalizujesz, możesz zarobić 5 bajtów. Ale to dobrze.
LegenDUST,
3

JavaScript (Node.js) , 587 582 575 569 557 554 550 549 bajtów

nie wiedziałeś tego 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):"")

Wypróbuj online!

547, jeśli znaki spoza alfabetu i koreańskiego jamos można zignorować.

Ok, tak długo walczyłem, żeby to napisać, ale to powinno zadziałać. Nie używa się koreańskiego jamo / sylaby, ponieważ są one zbyt drogie (3 bajty na użycie). Używany w wyrażeniu regularnym do zapisywania bajtów.

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
źródło
2

Wolfram Language (Mathematica) , 405 401 400 bajtów

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&

Wypróbuj online!

Nieco golfa

Aby przetestować ten w Mathematica prostu zastąpić alphabetz Alphabet; jednak TIO nie obsługuje chmury Wolfram, więc zdefiniowałem toAlphabet["Korean"] w nagłówku.

Najpierw rozkładamy wszystkie sylaby Hangul na alfabet Hangul, następnie zamieniamy znaki łacińskie i Hangul, a następnie ponownie komponujemy sylaby.

lirtosiast
źródło
1
input 2Wyniki przypadku testowego ㅑㅜㅔㅕㅅ 2zamiast ㅑㅞㅕㅅ 2w TIO. Mimo, że to samo ma miejsce w roztworze ja w pracy, ponieważ zarówno i są Jungseong, i wrażenie, tylko CHOSEONG + Jungseong + jongseong lub CHOSEONG + Jungseong + pusty będzie osobno. Poprosiłem OP o weryfikację, dlaczego się ㅜㅔstało .
Kevin Cruijssen
@KevinCruijssen ㅞ (np) jest samodzielnym jungseongiem
Nick Kennedy
1
Wydaje się, że nie działa to poprawnie w przypadku spółgłosek spółgłosek lub samogłosek dwóch znaków. Na przykład fnpfapowinna być pojedyncza postać, ale zamiast tego kończy się jako루ㅔㄹㅁ
Nick Kennedy
Naprawiono w toku. Nie powinno to kosztować zbyt wiele.
lirtosiast
2

Java 19, 1133 1126 1133 bajtów

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;}

Wyjścia z wielkimi literami ASDFGHJKLZXCVBNMbez zmian, ponieważ.toLowerCase() kosztują więcej niż premia -5.

Wstecz +7 bajtów jako poprawka błędu dla znaków innych niż koreańskie powyżej wartości Unicode powyżej 20 000 (podziękowania @NickKennedy za zauważenie).

Wypróbuj online.

Wyjaśnienie:

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
źródło
1
są od 44032 do 55203. Masz już zakodowaną lokalizację początkową. Koniec jest po prostu44032 + 19×21×28 - 1
Nick Kennedy
Działa dobrze teraz. Myślałem, że już cię głosowałem, ale nie zrobiłem tego, więc proszę bardzo!
Nick Kennedy