Romanize Korean


12

Sim, é basicamente você é um romanizador, querida , mas mais difícil . tipo, muito mais difícil.

Aprender coreano é DURO. pelo menos para uma pessoa fora da Ásia. Mas eles pelo menos têm a chance de aprender, certo?

O que você deve fazer

Você receberá uma declaração em coreano. Por exemplo 안녕하세요,. Você deve converter a entrada em sua pronúncia romana. Para o exemplo dado, a saída pode ser annyeonghaseyo.

Agora fica técnico

Um caractere coreano possui três partes: consoante inicial, vogal e consoante final. A consoante final pode não existir no personagem.

Por exemplo, é (consoante inicial) e (vogal) e é (consoante inicial), (vogal) e (consoante final).

Evitar consoante e vogal tem sua pronúncia. A pronúncia para cada consoante é a seguinte.

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

(- significa sem pronúncia ou não usado. você não precisa lidar com elas.)

e Pronúncia para cada vogal é a seguinte.

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

Agora é a verdadeira parte difícil

A pronúncia da consoante é alterada pela consoante Final antes. A pronúncia para cada consoante inicial / final é a seguinte imagem. Obrigado, Wikipedia.  Se não houvesse isso, eu teria que escrever tudo isso. (Você não precisa fazer o hífen entre as pronúncias. Não é necessário. Se uma célula tiver duas ou mais pronúncias, escolha uma. Se não houver consoante final, use a pronúncia original.)

Exemplos

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

Sugestão de exemplo bem-vinda. Você pode obter respostas para suas próprias entradas aqui . (Aquele em "Texto geral", Revisado, é o que estou pedindo)


A entrada sempre consistirá em caracteres Unicode espaço AC00-D7AF +?
Arnauld

1
Existem várias combinações especiais ㅎ + X que não são destacadas em amarelo (por exemplo, ㅎ + ㅈ = ch). Isso significa que não precisamos apoiá-los? (Além disso, é ㅎ 'romanizado' como t , em vez de h no quadro, que é um pouco confusa.)
Arnauld

1
Casos de teste: gist.github.com/perey/563282f8d62c2292d11aabcde0b94d2d Como o @Arnauld diz, existem algumas esquisitices nas combinações especiais; isso tem testes para todos os que encontrei na tabela, destacados ou não. Onde existem várias opções, elas são separadas por espaço. Nenhum hífen é usado, pois espero que as pessoas os joguem fora.
Tim Pederick

1
Não vejo "Texto geral" no seu link sugerido de verificação de saída; você quer dizer "coisas gerais"? Em caso afirmativo, qual dos três devemos usar (Revised, McCune, Yale)? Nenhum parece corresponder à sua mesa; por exemplo, ㅈ seguido de ㄹ deve ser "nn" de acordo com você, mas é "tr" ou "cl" nesse link. (Note que os meus casos de teste no comentário anterior são baseados em transliterações em questão!)
Tim Pederick

seguidos por ㄱ, ㄷ, ㅈtambém são casos especiais (eles aspiram a ㅋ, ㅌ, ㅈ(k, t, j)) também devem destacá-los.
JungHwan Min

Respostas:


8

Python 3.6, 400 394 bytes

Edit: Graças ao RootTwo por -6 bytes.

Esta é a minha primeira submissão ao CodeGolf, por isso tenho certeza de que existem maneiras melhores de jogar golfe, mas pensei em publicá-la, pois ninguém mencionou a ideia principal ainda, e isso ainda é significativamente mais curto do que outras soluções .

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)

Como funciona

A solução tenta explorar o fato (que aprendi com o desafio original da romanização em japonês) de que nomes de caracteres romanizados são acessíveis através do módulo unicodedata do Python. Para o idioma coreano, eles assumem a forma de HANGUL SYLLABLE <NAME>. Infelizmente, o processamento desses nomes para atender às especificações fornecidas e para cobrir todos os cenários de combinação de sílabas ainda requer bastante esforço (e bytes).

Os nomes dos caracteres obtidos listam todas as consoantes em sua forma sonora em qualquer lugar da sílaba, por exemplo, GGAGGpara , R/Lsão transcritas conforme pretendido (início R, final L) e CHsão dadas como C(isso realmente nos deixa um pouco de dor de cabeça).

Primeiro, removemos a HANGUL SYLLABLEpeça (primeiros 16 caracteres), marcamos os limites da sílaba -e, em seguida, aplicamos uma série de expressões regulares para fazer as conversões.

O primeiro RegEx parece particularmente desagradável. O que basicamente faz é a conversão de consoantes iniciais em seus equivalentes finais (também removendo a letra extra no caso de consoantes duplas), quando elas não são seguidas por uma vogal ou para algumas letras - quando são precedidas por h. O (?<!n)lookbehind impede a correspondência da gqual faz parte ng, e o (?!\\1)lookahead garante que não convertemos, por exemplo, ssaem tsa.

Os próximos RegEx convertem consoantes duplas iniciais em seus equivalentes não sonoros. Aqui é onde os -separadores também são úteis, pois ajudam a discernir colisões de limites ( g-g) de consoantes duplas ( gg). Agora eles também podem ser removidos.

Em seguida, lidamos com as h+consonantcombinações restantes , l->rantes das vogais e outros casos especiais.

Finalmente, restaurar ca ch, e resolver algumas outras peculiaridades dos nossos nomes de char de entrada, como yiem vez de uie weoem vez de wo.

Eu não sou especialista em coreano e não posso comentar muito mais, mas isso parece passar em todos os testes publicados na tarefa e no Github. Obviamente, mais alguns bytes podem ser eliminados, se a saída for aceitável em maiúsculas, pois é isso que obtemos da função name.


Bem-vindo ao PPCG! Ótima primeira resposta.
FantaC 15/0218

1
Boa resposta. A partir do python 3.6, m[0]é o mesmo que m.group(0); economizando 6 bytes.
RootTwo

5

JavaScript (ES6), 480 bytes (WIP)

Esta é uma tentativa inicial, com base nas especificações atuais, de fazer a bola rolar. Pode exigir alguma correção quando as perguntas nos comentários forem abordadas.

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

Casos de teste

Quão?

Uma vez descompactado, a matriz V contém os seguintes dados:

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

Dividimos cada caractere Hangul em consoante inicial, vogal e consoante final. Anexamos ao resultado:

  • V[80 + substitution] + V[vowel] se houver uma substituição
  • V[40 + previousEndingConsonant] + V[21 + startingConsonant] + V[vowel] de outra forma

Não pode '!'ser 33?
Jonathan Frech

@JonathanFrech cnão é um byte. É uma cadeia de 1 caractere. Dito isto , ao aplicar uma operação aritmética, um espaço é coagido 0enquanto outros caracteres que não são dígitos são coagidos NaN. O que significa que c<1deve realmente funcionar como esperado. (E c<33também funcionaria para caracteres não-dígito, embora isto é uma espécie de fortuito.)
Arnauld

@JonathanFrech Adenda: c<1Também seria truthy para "0"(que é provavelmente OK se a entrada é a garantia de não conter qualquer algarismo arábico.)
Arnauld

Obrigado. Eu não achava que o JavaScript tivesse caracteres implementados como um byte único, embora tentado mesmo assim. No entanto, parecia funcionar. Fico feliz em saber agora o porquê.
Jonathan Frech

2

Tcl, 529 bytes

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

Algoritmo

  1. Decomposição em índices de chumbo, vogal e cauda
  2. Primeira pesquisa para representação alfabética intermediária
  3. Aplique um passe inicial para todas as transformações xn → nn / xm → nm
  4. Aplique um passe final para as transformações restantes

Esse algoritmo é triturado para fins do desafio; o trade-off é que se supõe que a entrada não contenha caracteres alfabéticos latinos, nem use caracteres fora do bloco Hangul do U + AC00, conforme descrito no desafio. Se esse código fosse real, eu manteria todas as transformações em Jamo até a passagem final.

Suponho que eu poderia ter um pouco mais de capacidade de raciocinar sobre as vogais e algumas das repetições na tabela de pesquisa, mas isso é tão bom quanto é possível hoje.

Teste

Certifique-se de fornecer entrada UTF-8 ao interpretador Tcl. Isso é realizado com mais facilidade com um simples arquivo de texto UTF-8. Infelizmente, Tcl ainda não é o padrão para UTF-8 por padrão; isso me custou 33 bytes.

Aqui está o meu arquivo de teste (atualmente patético):

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

Notas

Não sei nada sobre o idioma coreano (exceto o pouco que aprendi aqui). Esta é uma primeira tentativa, com revisão potencial pendente devido a atualizações na especificação da pergunta.

E, sobre isso, algumas informações adicionais são úteis. Em particular, não há uma correspondência 1: 1 entre consoantes de chumbo e cauda, ​​como parece sugerido no desafio. Os dois sites a seguir ajudaram bastante a descobrir isso:
Wikipedia: idioma coreano, Hangul
Wikipedia: Hangul Jamo (bloco Unicode)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.