Романизировать корейский


12

Да, это в основном ты романизатор, детка , но сложнее . как, намного сложнее.

Изучение корейского языка трудна. по крайней мере, для человека за пределами Азии. Но у них по крайней мере есть шанс учиться, верно?

Что ты должен сделать

Вы получите корейское заявление. Например, 안녕하세요. Вы должны преобразовать ввод в его римское произношение. Для данного примера вывод может быть annyeonghaseyo.

Теперь это становится техническим

Корейский символ состоит из трех частей: начальная согласная, гласная и конечная согласная. Конечная согласная может не существовать в символе.

Например, есть (Начальная согласная) и (Гласный), и есть (Начальная согласная), (Гласная) и (Конечная согласная).

Эверт согласный и гласный имеет свое произношение. Произношение для каждого согласного является следующим.

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

(- означает отсутствие произношения или не используется. Вы не должны обращаться с ними.)

Произношение для каждой гласной звучит следующим образом.

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

Теперь это самая сложная часть

Произношение согласного изменяется перед согласным в конце. Произношение для каждого начального / конечного согласного выглядит следующим образом. Спасибо, Википедия.  Если бы не было этого, я бы написал все это. (Вам не нужно вводить дефис между произношениями. Это не нужно. Если в ячейке есть два или более произношения, выберите одно. Если нет конечного согласного, используйте оригинальное произношение.)

Примеры

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

Пример предложения приветствуется. Вы можете получить ответы на свои вопросы здесь . (То, что в «Общем тексте», пересмотрено - это то, что я прошу)


Будет ли ввод всегда состоять из символов Юникода AC00-D7AF + пробел?
Арно

1
Существует несколько специальных комбинаций ㅎ + X, которые не выделены желтым цветом (например, ㅎ + ㅈ = ch). Значит ли это, что мы не должны их поддерживать? (Кроме того , ㅎ является «латинизируется» , как т вместо часов в картине, которая немного запутанным.)
Arnauld

1
Тестовые случаи: gist.github.com/perey/563282f8d62c2292d11aabcde0b94d2d Как говорит @Arnauld, в особых комбинациях есть некоторые странности; здесь есть тесты для всех тех, что я нашел в таблице, выделены они или нет. Там, где существует несколько вариантов, они разделены пробелами. Никаких дефисов не используется, так как я ожидаю, что люди будут играть в них.
Тим Педерик

1
Я не вижу "Общий текст" в предложенной вами ссылке для проверки вывода; ты имеешь в виду "общие вещи"? Если да, то какой из трех мы должны использовать (Revised, McCune, Yale)? Ни один, кажется, не соответствует вашему столу; например, ㅈ, за которым следует ㄹ, должно быть «nn» в соответствии с вами, но «tr» или «cl» в этой ссылке. (Обратите внимание, что мои тесты в предыдущем комментарии основаны на транслитерации в вопросе!)
Тим Педерик

за ними ㄱ, ㄷ, ㅈследуют также особые случаи (они обозначаются как ㅋ, ㅌ, ㅈ(k, t, j)), которые также должны быть выделены.
JungHwan Мин

Ответы:


8

Python 3.6, 400 394 байта

Изменить: Спасибо RootTwo за -6 байт.

Это моя первая заявка на CodeGolf, так что я уверен, что есть лучшие способы сыграть в гольф, но я подумал, что все же опубликую ее, так как никто еще не упомянул ключевую идею, и она все еще значительно короче, чем другие решения. ,

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)

Как это устроено

Решение пытается использовать тот факт (который я узнал из оригинальной японской задачи латинизации), что имена латиноамериканских символов доступны через модуль unicodedata Python. Для корейского языка они принимают форму HANGUL SYLLABLE <NAME>. К сожалению, обработка этих имен для соответствия предоставленной спецификации и для охвата всех сценариев комбинации слогов все еще требует немалых усилий (и байтов).

Полученные имена символов перечисляют все согласные в их озвученной форме в любом месте слога, например, GGAGGдля , R/Lтранскрибируются как предназначено (начало R, конец L), и CHзадается как C(это на самом деле избавляет нас от головной боли).

Прежде всего, мы снимаем HANGUL SYLLABLEчасть (первые 16 символов), помечаем границы слогов -, а затем применяем серию регулярных выражений для выполнения преобразований.

Первый RegEx выглядит особенно противно. По сути, это преобразование начальных согласных в их конечные эквиваленты (также удаление лишних букв в случае двойных согласных), когда за ними не следует гласная, или для некоторых букв - когда им предшествует h. (?<!n)Назад ' предотвращает соответствия , gкоторый является частью ng, и (?!\\1)касательно последующего гарантирует , что мы не конвертировать, например, ssaк tsa.

Следующие несколько RegEx'ов конвертируют начальные двойные согласные в их невокализованные эквиваленты. Вот где -разделители также пригодятся, поскольку они помогают отличить граничные столкновения ( g-g) от двойных согласных ( gg). Теперь они также могут быть удалены.

Далее мы обрабатываем оставшиеся h+consonantкомбинации l->rперед гласными и другими частными случаями.

Наконец, мы восстанавливаем cк ch, и решить некоторые другие особенности наших входящих имен полукокса, например, yiвместо того , чтобы uiи weoвместо wo.

Я не специалист по корейскому языку и не могу комментировать намного больше, но, похоже, он прошел все тесты, опубликованные в задании и на Github. Очевидно, что еще несколько байтов могут быть сброшены, если выходные данные допустимы в верхнем регистре, поскольку это то, что мы получаем из функции name.


Добро пожаловать в PPCG! Отличный первый ответ.
FantaC

1
Хороший ответ. Начиная с Python 3.6, m[0]это то же самое, что и m.group(0); экономия 6 байт.
RootTwo

5

JavaScript (ES6), 480 байт (WIP)

Это ранняя попытка, основанная на текущих спецификациях, чтобы запустить мяч. Это может потребовать некоторого исправления при рассмотрении вопросов в комментариях.

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

Контрольные примеры

Как?

После распаковки массив V содержит следующие данные:

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

Мы разделяем каждого персонажа хангул на начальный согласный, гласный и конечный согласный. Добавляем к результату:

  • V[80 + substitution] + V[vowel] если есть замена
  • V[40 + previousEndingConsonant] + V[21 + startingConsonant] + V[vowel] в противном случае

Не '!'может быть 33?
Джонатан Фрех

@JonathanFrech c- это не байт. Это строка из 1 символа. Тем не менее , при применении арифметической операции вводится пробел, 0а другие нецифровые символы приводятся к NaN. Что означает, что на c<1самом деле должно работать как ожидалось. (И c<33также будет работать для нецифровых символов, хотя это довольно случайно.)
Арно

@JonathanFrech Addendum: c<1также будет правдой для "0"(что, вероятно, нормально, если входные данные гарантированно не содержат арабских цифр.)
Арно

Благодарю. Я не думал, что в JavaScript будут символы, реализованные в виде одного байта, хотя, тем не менее, пробовал. Это, однако, казалось, работает. Рад теперь знать почему.
Джонатан Фрех

2

Tcl, 529 байт

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

Алгоритм

  1. Разложение на свинцовые, гласные и хвостовые индексы
  2. Первый поиск в промежуточном алфавитном представлении
  3. Применить начальный проход для всех преобразований xn → nn / xm → nm
  4. Примените последний проход для оставшихся преобразований

Этот алгоритм хруст для целей задачи; компромисс заключается в том, что предполагается, что входные данные не содержат латинских буквенных символов и не используют символы вне блока Hangul U + AC00, как описано в задании. Если бы это был настоящий код, я бы сохранил все преобразования в Jamo до последнего прохода.

Полагаю, я мог бы потратить немного больше сил на то, чтобы разбить эти гласные и некоторые повторения в справочной таблице, но это так же хорошо, как это получается от меня сегодня.

тестирование

Убедитесь, что вы можете предоставить UTF-8 вход для интерпретатора Tcl. Это легче всего сделать с помощью простого текстового файла UTF-8. Увы, Tcl по-прежнему не использует UTF-8 по умолчанию; это стоило мне 33 байта.

Вот мой (в настоящее время жалкий) тестовый файл:

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

Примечания

Я ничего не знаю о корейском языке (кроме того, что мало я выучил здесь). Это первая попытка, ожидающая возможного пересмотра из-за обновлений в спецификации вопроса.

И, об этом, некоторая дополнительная информация полезна. В частности, нет соответствия 1: 1 между ведущими и хвостовыми согласными, как кажется, предлагается в задаче. Следующие два сайта помогли мне во многом это выяснить:
Википедия: корейский язык, хангыль
Википедия: хангыль джамо (блок Unicode)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.