Koreanisch romanisieren

12

Ja, im Grunde bist du ein Romanizer, Baby , aber härter . wie viel schwieriger.

Koreanisch lernen ist hart. Zumindest für eine Person außerhalb Asiens. Aber sie haben wenigstens die Chance zu lernen, oder?

Was müssen Sie tun?

Sie erhalten eine koreanische Erklärung. Zum Beispiel 안녕하세요. Sie müssen die Eingabe in die römische Aussprache konvertieren. Für das gegebene Beispiel kann die Ausgabe sein annyeonghaseyo.

Jetzt wird es technisch

Ein koreanisches Zeichen besteht aus drei Teilen: Startkonsonant, Vokal und Endkonsonant. Der Endkonsonant darf im Charakter nicht vorhanden sein.

Zum Beispiel ist (Startkonsonant) und (Vokal) und ist (Startkonsonant), (Vokal) und (Endkonsonant).

Evert Konsonant und Vokal hat seine Aussprache. Die Aussprache für jeden Konsonanten ist wie folgt.

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

(- bedeutet keine Aussprache oder nicht verwendet. Sie müssen nicht damit umgehen.)

und Aussprache für jeden Vokal ist wie folgt.

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

Jetzt ist es der wirklich schwierige Teil

Die Aussprache des Konsonanten ändert sich durch den Endkonsonanten in vor. Die Aussprache für jeden Start- / Endkonsonanten ist wie folgt. Vielen Dank, Wikipedia.  Wenn es das nicht gäbe, müsste ich das alles SCHREIBEN. (Zwischen den Aussprachen muss kein Bindestrich eingefügt werden. Dies ist nicht erforderlich. Wenn eine Zelle zwei oder mehr Aussprachen enthält, wählen Sie eine aus. Wenn es keinen Endkonsonanten gibt, verwenden Sie die ursprüngliche Aussprache.)

Beispiele

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

Beispielvorschlag begrüßt. Sie können Antworten auf Ihre eigene Eingänge bekommen hier . (Der in "Allgemeiner Text", Überarbeitet ist das, wonach ich bitte)

Matthew Roh
quelle
Besteht die Eingabe immer aus Unicode-Zeichen AC00-D7AF + Leerzeichen?
Arnauld
1
Es gibt mehrere spezielle ㅎ + X-Kombinationen, die nicht gelb hervorgehoben sind (z. B. ㅎ + ㅈ = ch). Bedeutet das, dass wir sie nicht unterstützen müssen? (Außerdem ist ㅎ als t anstelle von h im Bild 'romanisiert' , was ein bisschen verwirrend ist.)
Arnauld
1
Testfälle: gist.github.com/perey/563282f8d62c2292d11aabcde0b94d2d Wie @Arnauld sagt, gibt es einige Merkwürdigkeiten in den speziellen Kombinationen; Dies hat Tests für alle, die ich in der Tabelle gefunden habe, ob hervorgehoben oder nicht. Wenn mehrere Optionen vorhanden sind, werden sie durch Leerzeichen getrennt. Es werden keine Bindestriche verwendet, da ich davon ausgehe, dass die Leute sie herausspielen.
Tim Pederick
1
In Ihrem vorgeschlagenen Link zur Ausgabeüberprüfung wird "Allgemeiner Text" nicht angezeigt. meinst du "allgemeine sachen" Wenn ja, welches der drei sollten wir verwenden (Revised, McCune, Yale)? Keiner scheint zu Ihrem Tisch zu passen; Beispiel: ㅈ gefolgt von ㄹ sollte Ihrer Meinung nach "nn" sein, ist aber an dieser Stelle "tr" oder "cl". (Beachten Sie, dass meine Testfälle im vorherigen Kommentar auf Transliterationen in der Frage basieren!)
Tim Pederick
gefolgt von ㄱ, ㄷ, ㅈsind auch Sonderfälle (sie werden angesaugt ㅋ, ㅌ, ㅈ(k, t, j)) sollten diese auch hervorheben.
JungHwan Min

Antworten:

8

Python 3.6, 400 394 Bytes

Edit: Danke an RootTwo für -6 Bytes.

Dies ist meine erste Einsendung bei CodeGolf, daher bin ich mir ziemlich sicher, dass es bessere Möglichkeiten zum Golfen gibt, aber ich dachte, ich würde sie trotzdem posten, da noch niemand die Schlüsselidee erwähnt hat und diese immer noch deutlich kürzer ist als bei anderen Lösungen .

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)

Wie es funktioniert

Die Lösung versucht, die Tatsache auszunutzen (die ich aus der ursprünglichen japanischen Romanisierung gelernt habe), dass romanisierte Zeichennamen über Pythons Unicode-Datenmodul zugänglich sind. Für die koreanische Sprache haben sie die Form vonHANGUL SYLLABLE <NAME> . Leider erfordert die Verarbeitung dieser Namen, um die angegebene Spezifikation zu erfüllen und alle Silbenkombinationsszenarien abzudecken, immer noch einiges an Aufwand (und Bytes).

Die erhaltenen Charakternamen listen alle Konsonanten in ihrer stimmhaften Form irgendwo in der Silbe auf, zB GGAGGfür , R/Lwerden wie beabsichtigt transkribiert (Anfang R, Ende L) und CHwie angegeben C(dies erspart uns tatsächlich ein bisschen Kopfschmerzen).

Zuerst HANGUL SYLLABLEentfernen wir den Teil (die ersten 16 Zeichen) und markieren die Silbengrenzen mit- entfernen und wenden dann eine Reihe von RegEx'es an, um die Konvertierungen durchzuführen.

Der erste RegEx sieht besonders böse aus. Was es im Grunde tut, ist die Umwandlung von Anfangskonsonanten in ihre Endäquivalente (auch das Entfernen des zusätzlichen Buchstabens im Falle von Doppelkonsonanten), wenn ihnen kein Vokal folgt oder für einige Buchstaben - wenn ihnen ein vorangestellt ist h. Das (?<!n)Lookbehind verhindert das Matching, gdas Teil von ist ng, und (?!\\1)Lookahead stellt sicher, dass wir nicht konvertieren, z . B. ssanach tsa.

Die nächsten RegEx konvertieren ausgehende Doppelkonsonanten in ihre stimmlosen Äquivalente. Hier -bieten sich auch Trennzeichen an, um Grenzkollisionen ( g-g) von Doppelkonsonanten ( gg) zu unterscheiden. Jetzt können sie auch entfernt werden.

Als nächstes behandeln wir die verbleibenden h+consonantKombinationen, l->rvor Vokalen und anderen Sonderfällen.

Schließlich restaurieren wir cauf ch, und einige andere Besonderheiten unserer eingehenden char Namen auflösen, wie yistatt uiund weostatt wo.

Ich bin kein Experte für Koreanisch und kann nicht viel mehr dazu sagen, aber dies scheint alle Tests zu bestehen, die in der Aufgabe und auf Github veröffentlicht wurden. Offensichtlich könnten ein paar Bytes mehr abgeschnitten werden, wenn die Ausgabe in Großbuchstaben akzeptabel ist, da wir dies von der Namensfunktion erhalten.

Kirill L.
quelle
Willkommen bei PPCG! Tolle erste Antwort.
FantaC
1
Gute Antwort. Ab Python 3.6 m[0]ist es dasselbe wie m.group(0); Einsparung von 6 Bytes.
RootTwo
5

JavaScript (ES6), 480 Byte (WIP)

Dies ist ein früher Versuch, der auf den aktuellen Spezifikationen basiert, um den Ball ins Rollen zu bringen. Möglicherweise ist eine Korrektur erforderlich, wenn die Fragen in den Kommentaren beantwortet werden.

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

Testfälle

Wie?

Nach dem Dekomprimieren enthält das Array V die folgenden Daten:

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

Wir teilen jeden Hangul-Charakter in Anfangskonsonanten, Vokale und Endkonsonanten auf. Wir hängen an das Ergebnis an:

  • V[80 + substitution] + V[vowel] wenn es einen austausch gibt
  • V[40 + previousEndingConsonant] + V[21 + startingConsonant] + V[vowel] Andernfalls
Arnauld
quelle
Kann '!'nicht sein 33?
Jonathan Frech
@ JonathanFrech cist kein Byte. Es ist eine 1-stellige Zeichenfolge. Das heißt , wenn eine arithmetische Operation angewendet wird, wird ein Leerzeichen gezwungen, 0während andere nicht-stellige Zeichen gezwungen werden NaN. Was bedeutet, dass c<1das eigentlich wie erwartet funktionieren sollte. (Und c<33würde auch für nicht-stellige Zeichen funktionieren, obwohl dies irgendwie zufällig ist.)
Arnauld
@ JonathanFrech Nachtrag: c<1wäre auch wahr "0"(was wahrscheinlich in Ordnung ist, wenn die Eingabe garantiert keine arabische Ziffer enthält.)
Arnauld
Vielen Dank. Ich hätte nicht gedacht, dass JavaScript Zeichen als einzelnes Byte implementieren würde, obwohl es trotzdem versucht wurde. Es schien jedoch zu funktionieren. Freut mich jetzt zu wissen warum.
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]]

Algorithmus

  1. Zerlegung in Blei, Vokal und Schwanzindizes
  2. Erste Suche zur alphabetischen Zwischendarstellung
  3. Wenden Sie einen ersten Durchgang für alle xn → nn / xm → nm-Transformationen an
  4. Wenden Sie einen letzten Durchgang für die verbleibenden Transformationen an

Dieser Algorithmus wird zum Zweck der Herausforderung zerkleinert. der Kompromiss ist , dass der Eingang angenommen wird , nicht enthalten keine lateinischen Buchstaben, noch Zeichen außerhalb des U + AC00 Hangul - Block zu verwenden , wie in der Herausforderung beschrieben. Wäre dies der richtige Code, würde ich alle Transformationen in Jamo bis zum letzten Durchgang beibehalten.

Ich nehme an, ich könnte noch ein bisschen mehr Geisteskraft aufbringen, um diese Vokale und einige der Wiederholungen in der Nachschlagetabelle zu knacken, aber das ist so gut, wie es heute von mir kommt.

Testen

Stellen Sie sicher, dass Sie den Tcl-Interpreter mit UTF-8-Eingaben versorgen können. Dies wird am einfachsten mit einer einfachen UTF-8-Textdatei erreicht. Leider ist Tcl immer noch nicht standardmäßig auf UTF-8 eingestellt. das hat mich 33 bytes gekostet.

Hier ist meine (derzeit erbärmliche) Testdatei:

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

Anmerkungen

Ich weiß nichts über die koreanische Sprache (außer dem, was ich hier noch nicht gelernt habe). Dies ist ein erster Versuch, der aufgrund von Aktualisierungen in der Fragenspezifikation möglicherweise überarbeitet werden muss.

Darüber sind einige zusätzliche Informationen hilfreich. Insbesondere gibt es keine 1: 1-Entsprechung zwischen Lead- und Tail-Konsonanten, wie dies in der Herausforderung nahegelegt wird. Die folgenden beiden Websites halfen dabei, das immens herauszufinden:
Wikipedia: Koreanische Sprache, Hangul
Wikipedia: Hangul Jamo (Unicode-Block)

Dúthomhas
quelle