Romanize Korean


12

Tak, w zasadzie jesteś romanizerem, skarbie , ale trudniejszym . jak, sposób trudniej.

Nauka koreańskiego jest trudna. przynajmniej dla osoby spoza Azji. Ale przynajmniej mają szansę się uczyć, prawda?

Co musisz zrobić

Otrzymasz koreańskie oświadczenie. Na przykład 안녕하세요. Musisz przekonwertować dane wejściowe na wymowę rzymską. W podanym przykładzie wynikiem może być annyeonghaseyo.

Teraz robi się techniczny

Koreańska postać składa się z trzech części: początkowej spółgłoski, samogłoski i końcowej spółgłoski. Spółgłoska Ending może nie istnieć w postaci.

Na przykład jest (Początkowa spółgłoska) i (Samogłoska), a jest (Początkowa spółgłoska), (Samogłoska) i (Końcowa spółgłoska).

Evert spółgłoska i samogłoska ma swoją wymowę. Wymowa każdej spółgłoski jest następująca.

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

(- oznacza brak wymowy lub nieużywanie. nie musisz sobie z nimi radzić.)

Wymowa dla każdej samogłosek jest następująca.

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

Teraz jest to naprawdę trudna część

Wymowa spółgłosek zmienia się wcześniej przez spółgłoskę Ending. Wymowa każdej spółgłoski początkowej / końcowej jest następująca. Dziękuję Wikipedii.  Gdyby tego nie było, musiałbym NAPISAĆ to wszystko. (Nie musisz robić łącznika między wymowy. Jest to niepotrzebne. Jeśli komórka ma dwie lub więcej wymowy, wybierz jedną. Jeśli nie ma końcowej spółgłoski, użyj oryginalnej wymowy.)

Przykłady

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

Przykładowa sugestia mile widziana. Można uzyskać odpowiedzi na własnych wejść tutaj . (O to w „Ogólnym tekście”, poprawionym, o to proszę)


Czy dane wejściowe zawsze będą się składały ze znaków Unicode AC00-D7AF + spacja?
Arnauld,

1
Istnieje kilka specjalnych kombinacji ㅎ + X, które nie są podświetlone na żółto (np. ㅎ + ㅈ = ch). Czy to oznacza, że ​​nie musimy ich wspierać? (Również ㅎ jest „romanizowane” jako t zamiast h na zdjęciu, co jest nieco mylące.)
Arnauld

1
Przypadki testowe: gist.github.com/perey/563282f8d62c2292d11aabcde0b94d2d Jak mówi @Arnauld, w specjalnych kombinacjach występują pewne osobliwości; zawiera testy dla wszystkich tych, które znalazłem w tabeli, niezależnie od tego, czy zostały wyróżnione, czy nie. Tam, gdzie istnieje wiele opcji, są one rozdzielone spacjami. Nie są używane łączniki, ponieważ spodziewam się, że ludzie je rozegrają.
Tim Pederick,

1
Nie widzę „Ogólnego tekstu” w sugerowanym linku do sprawdzania wyników; masz na myśli „rzeczy ogólne”? Jeśli tak, to który z trzech powinniśmy zastosować (zmieniony, McCune, Yale)? Żaden wydaje się nie pasować do twojego stołu; na przykład ㅈ, po której następuje ㄹ, powinno być według ciebie „nn”, ale w tym linku jest „tr” lub „cl”. (Zauważ, że moje przypadki testowe w poprzednim komentarzu oparte są na transliteracjach w pytaniu!)
Tim Pederick

następnie ㄱ, ㄷ, ㅈsą też przypadki szczególne (aspirują do ㅋ, ㅌ, ㅈ(k, t, j)) również powinny je uwypuklić.
JungHwan Min

Odpowiedzi:


8

Python 3.6, 400 394 bajtów

Edycja: Dzięki RootTwo za -6 bajtów.

To moje pierwsze zgłoszenie do CodeGolf, więc jestem prawie pewien, że istnieją lepsze sposoby na grę w golfa, ale pomyślałem, że nadal będę go publikować, ponieważ nikt jeszcze nie wspomniał o kluczowym pomyśle, a to wciąż znacznie krótsze niż w przypadku innych rozwiązań .

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)

Jak to działa

Rozwiązanie próbuje wykorzystać fakt (którego dowiedziałem się z oryginalnego japońskiego wyzwania romanizacji), że romanizowane nazwy postaci są dostępne poprzez moduł Unicodeedata Pythona. W przypadku języka koreańskiego mają one postać HANGUL SYLLABLE <NAME>. Niestety przetwarzanie tych nazw w celu spełnienia podanej specyfikacji i uwzględnienia wszystkich scenariuszy kombinacji sylaby nadal wymaga sporo wysiłku (i bajtów).

W uzyskanych nazwach znaków wszystkie spółgłoski w formie dźwięcznej w dowolnym miejscu w sylabie, np. GGAGGDla , R/Lsą transkrybowane zgodnie z przeznaczeniem (początek R, koniec L) i CHsą podawane jako C(to faktycznie oszczędza nam trochę bólu głowy).

Przede wszystkim usuwamy HANGUL SYLLABLEczęść (pierwsze 16 znaków), zaznaczamy granicami sylaby za pomocą -, a następnie stosujemy serię RegEx'ów w celu wykonania konwersji.

Pierwszy RegEx wygląda wyjątkowo paskudnie. Zasadniczo robi to konwersja początkowych spółgłosek na ich końcowe odpowiedniki (usuwając również dodatkową literę w przypadku podwójnych spółgłosek), gdy nie następuje po nich samogłoska, lub w przypadku niektórych liter - gdy są poprzedzone h. (?<!n)Zapobiega lookbehind dopasowanie gktóry jest częścią ng, i (?!\\1)uprzedzona zapewnia, że nie konwertować np ssado tsa.

Kolejne kilka RegEx'ów przekształca początkowe podwójne spółgłoski w ich bezdźwięczne odpowiedniki. Tutaj -przydają się również separatory, które pomagają w rozpoznawaniu zderzeń granicznych ( g-g) z podwójnymi spółgłosek ( gg). Teraz można je również usunąć.

Następnie zajmujemy się pozostałymi h+consonantkombinacjami, l->rprzed samogłoskami i innymi specjalnymi przypadkami.

Wreszcie możemy przywrócić cdo ch, i rozwiązać kilka innych osobliwości naszych przychodzących nazw, takich jak char yizamiast uii weozamiast wo.

Nie jestem ekspertem od koreańskiego i nie mogę komentować więcej, ale zdaje się, że pomyślnie przeszedł wszystkie testy opublikowane w zadaniu i na Githubie. Oczywiście kilka dodatkowych bajtów można by ogolić, jeśli dane wyjściowe są dopuszczalne dużymi literami, ponieważ to właśnie otrzymujemy z funkcji name.


Witamy w PPCG! Świetna pierwsza odpowiedź.
FantaC

1
Niezła odpowiedź. W Pythonie 3.6 m[0]jest taki sam jak m.group(0); oszczędzając 6 bajtów.
RootTwo

5

JavaScript (ES6), 480 bajtów (WIP)

Jest to wczesna próba, oparta na aktualnych specyfikacjach, aby uruchomić piłkę. Może to wymagać pewnych poprawek, gdy pytania w komentarzach zostaną rozwiązane.

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

Przypadki testowe

W jaki sposób?

Po zdekompresowaniu tablica V zawiera następujące dane:

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

Dzielimy każdą postać Hangul na początkową spółgłoskę, samogłoskę i końcową spółgłoskę. Do wyniku dołączamy:

  • V[80 + substitution] + V[vowel] jeśli jest zamiana
  • V[40 + previousEndingConsonant] + V[21 + startingConsonant] + V[vowel] Inaczej

Może '!'nie być 33?
Jonathan Frech

@JathanathanFrech cnie jest bajtem. Jest to ciąg 1 znaków. To powiedziawszy , przy stosowaniu operacji arytmetycznej przestrzeń jest wymuszana, 0podczas gdy inne znaki niecyfrowe są wymuszane NaN. Co oznacza, że c<1tak naprawdę powinno działać zgodnie z oczekiwaniami. (I c<33działałoby również w przypadku znaków niecyfrowych, chociaż jest to trochę przypadkowe.)
Arnauld

@JonathanFrech Addendum: c<1byłoby również zgodne z prawdą "0"(co prawdopodobnie jest poprawne, jeśli dane wejściowe nie zawierają cyfr arabskich).
Arnauld

Dzięki. Nie sądziłem, że JavaScript będzie zawierał znaki zaimplementowane jako jeden bajt, ale mimo to próbowałem. Wydawało się jednak, że działa. Cieszę się, że teraz wiesz, dlaczego.
Jonathan Frech

2

Tcl, 529 bajtów

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

Algorytm

  1. Rozkład na wskaźniki ołowiu, samogłoski i ogona
  2. Pierwsze wyszukiwanie do pośredniej reprezentacji alfabetycznej
  3. Zastosuj wstępne przejście dla wszystkich przekształceń xn → nn / xm → nm
  4. Zastosuj końcowe przejście dla pozostałych transformacji

Ten algorytm jest wykorzystywany do celów wyzwania; kompromis polega na tym, że zakłada się, że dane wejściowe nie zawierają żadnych alfabetów łacińskich ani nie używają znaków spoza bloku Hangul U + AC00, jak opisano w wyzwaniu. Gdyby to był prawdziwy kod, zachowałbym wszystkie transformacje w Jamo aż do ostatniego przejścia.

Podejrzewam, że mógłbym rzucić nieco więcej mocy na chrupanie tych samogłosek i niektórych powtórzeń w tabeli odnośników, ale jest to tak dobre, jak się dzisiaj wydaje.

Testowanie

Upewnij się, że możesz podać wejście UTF-8 do interpretera Tcl. Najłatwiej to zrobić za pomocą prostego pliku tekstowego UTF-8. Niestety, Tcl nadal domyślnie nie jest domyślnie ustawiony na UTF-8; kosztowało mnie to 33 bajty.

Oto mój (obecnie żałosny) plik testowy:

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

Notatki

Nic nie wiem o języku koreańskim (z wyjątkiem tego, czego niewiele się tutaj nauczyłem). Jest to pierwsza próba, oczekująca na potencjalną zmianę z powodu aktualizacji specyfikacji pytania.

Poza tym przydatne są dodatkowe informacje. W szczególności nie ma zgodności 1: 1 między spółgłoskami ołowiu i ogona, co wydaje się sugerowane w wyzwaniu. Następujące dwie strony bardzo pomogły w ustaleniu tego:
Wikipedia: język koreański, Hangul
Wikipedia: Hangul Jamo (blok Unicode)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.