Jesteś romanizerem, skarbie

38

Romanizacja języka japońskiego polega na konwersji japońskiego tekstu na znaki łacińskie. W tym wyzwaniu otrzymasz ciąg znaków japońskich jako dane wejściowe i będziesz musiał przekonwertować je na prawidłowy ciąg ASCII.

Co musisz wiedzieć

Język japoński ma trzy systemy pisania: hiragana (krzywoliniowy używany do krótkich słów), katakana (kąt-y używany do dźwięków i słów zapożyczonych z innych języków) oraz kanji (gęste postacie pierwotnie z chińskiego). W tym wyzwaniu będziemy się martwić tylko hiraganą.

W sylabie hiragana jest 46 znaków. Każda postać reprezentuje sylabę. Znaki są uporządkowane według pierwszego dźwięku (spółgłoski) i drugiego dźwięku (samogłoski). Kolumny w kolejności są aiueo.

 : あいうえお
k: かきくけこ
s: さしすせそ
t: たちつてと
n: なにぬねの
h: はひふへほ
m: まみむめも
y: や ゆ よ
r: らりるれろ
w: わ   を
N: ん

(jeśli skopiujesz i wkleisz tę tabelę, zauważ, że użyłem spacji ideograficznych U + 3000 do spacji y i w)

Na przykład あ と め powinien dać wynik atome. Pierwszym znakiem jest a, drugim jest to, a trzecim jest me.

Wyjątki

Jak każdy dobry język, japoński ma wyjątki od swoich zasad, a tabela hiragana ma kilka. Te znaki są wymawiane nieco inaczej niż ich położenie w tabeli oznaczałoby:

し: shi, nie si
ち: chi, nie ti
つ: tsu, nie tu
ふ: fu, niehu

Dakuten ゛

Słowo „dakuten” oznacza „zabłocony znak”: dakuten zamienia dźwięki w ich dźwięczne odpowiedniki (zwykle); na przykład かkazmienia się w か ゛ga. Pełna lista zmian:

kg
sz
td
hb

Zmieniają się także wyjątki: し ゛: ji(lub zhi), nie zi
ち ゛: ji, nie di
つ ゛: dzu, nie du
(ふ ゛ działa tak, jak można się spodziewać; nie jest wyjątkiem)

Handakuten to dodatkowy znak ゜, który dotyczy hwiersza. Umieszczony za postacią zmienia dźwięk postaci na pzamiast b.

Zarówno dakuten, jak i handakuten zostaną podane jako indywidualne postacie. Nie będziesz musiał radzić sobie ze wstępnie złożonymi formami lub łączącymi się postaciami.

Małe postacie

Wreszcie istnieją małe wersje niektórych postaci. Modyfikują postacie, które pojawiają się przed nimi lub po nich.

ゃ ゅ ょ

Są to małe formy ya, yuoraz yo. Są one umieszczane tylko po dźwiękach w ikolumnie -kolumna; usuwają ii dodają dźwięk. Tak więc き や zamienia się w kiya; き ゃ zamienia się w kya.

Jeśli zostanie umieszczony po chilub shi(lub w ich postaciach dakutenowych), również yzostanie usunięty. し ゆ oznacza shiyu; し ゅ jest shu.

Ostatnią rzeczą, z którą musisz się zmierzyć, jest mała tsu. っ podwaja spółgłoskę, która następuje po nim, bez względu na wszystko; nic więcej nie robi. Na przykład き た jest kita; き っ た jest kitta.

Podsumowanie, dane wejściowe i dane wyjściowe

Twój program musi mieć umiejętność transliteracji: 46 podstawowych hiraganów, ich formy dakuten i handakuten oraz kombinacje z małymi postaciami.

Nieokreślone zachowanie obejmuje: mały ya, yua yonie po znaku z i, mały tsuna końcu łańcucha, dakuten na nietkniętym znaku, handakuten na niebędącym ppostacią i wszystko inne nie wymienione w powyższej specyfikacji / wprowadzeniu.

Możesz założyć, że wszystkie dane wejściowe są prawidłowe i zawierają tylko znaki japońskie wymienione powyżej.

Wielkość liter nie ma znaczenia; można również wymienić rsię llub samotny nz m. Dane wyjściowe mogą zawierać jedną spację między każdą sylabą lub nie zawierać spacji.

To jest : wygrywa najkrótszy kod w bajtach.

Przypadki testowe

Wiele przypadków testowych dla każdej części podano w specyfikacji. Niektóre dodatkowe przypadki:

ひ ら か ゛ な → hiragana

か た か な → katakana

た ゛ い き ゛ ゃ く て ん さ い は ゛ ん → daigyakutensaiban

ふ ゜ ろ く ゛ ら み ん く ゛ は ゜ す ゛ る こ う と ゛ こ ゛ る ふ → puroguramingupazurucoudogorufu

か ゛ ん ほ ゛ っ て → ganbatte

Notatki

  • Poza tym, co tu napisałem, niewiele znam japońskiego. Daj mi znać, jeśli popełniłem jakieś błędy.

  • Początkowo planowałem również dołączyć katakana (więc mój test na angielską transliterację może być nieco dokładniejszy), ale byłoby to zbyt wiele dla wyzwania golfowego.

  • Nazwy Unicode obejmują transliterację każdego znaku osobno, ale bez wyjątków. To może, ale nie musi być pomocne.

  • Dziękujemy za pisanie o poprawianiu dwóch literówek!

  • Przepraszam, jeśli to jest za długie; Próbowałem dopasować większość dziwactw hiragana do wyzwania, ale niektóre rzeczy (takie jak mała hiragana tylko samogłoska, zmiana n na m przed niektórymi spółgłosek i znak powtórzenia) musiały zostać wycięte, aby wyzwanie było wykonalne.

  • W ogóle nie jest mi przykro z powodu tytułu. To arcydzieło.

Deusovi
źródło
1
Jaka powinna być wydajność きっった?
lirtosiast
@ Thomas: To nieprawidłowe dane wejściowe. Wynik może być dowolny.
Deusovi
1
powinien っしbyć sshilub shshi?
lirtosiast
2
I'm not at all sorry for the title. It's a masterpiece.Downvoted
Fatalize
3
@Fatalize Nie musisz tutaj wprowadzać swojego nastawienia anty-Britney. Chociaż osobiście jestem fanem J-Lo, nie będę głosować nad tym doskonałą łamigłówką.
pół-zewnętrzny zewnętrzny

Odpowiedzi:

7

Python 2, 638 bajtów

import unicodedata
s=input()
k=[0x309B,0x309C,0x3063]
m=[0x3083,0x3085,0x3087]
e={0x3057:'shi',0x3061:'chi',0x3064:'tsu',0x3075:'fu'}
d={0x3057:'ji',0x3061:'ji',0x3064:'dzu'}
D=dict(zip('ksth','gzdb'))
f=lambda c:unicodedata.name(c).split()[-1].lower()if ord(c)not in e else e[ord(c)]
g=lambda c:d[c]if c in d else D[f(c)[0]]+f(c)[1:]
R=[]
r=[]
t=[]
i=0
while i<len(s):
 c=ord(s[i])
 if c==k[0]:R[-1]=g(s[i-1])
 elif c==k[1]:R[-1]='p'+R[-1][1:]
 elif c in m:R[-1]=R[-1][:-1];n=f(s[i]);R+=[n[1:]]if r[-1]in[0x3057,0x3061]else[n];r+=[c]
 elif c==k[2]:t+=[len(R)]
 else:R+=[f(s[i])];r+=[c]
 i+=1
for i in t:R[i]=R[i][0]+R[i]
print ''.join(R)

Pobiera dane wejściowe jako ciąg znaków Unicode.

Przetestuj na Ideone

TFeld
źródło
1
Możesz uratować marne pa, zmieniając print ''.join(R)naprint''.join(R)
Zacharý
6

Python 2, 447 bajtów

import unicodedata as u
r=str.replace
i=''.join('x'*('SM'in u.name(x)or ord(x)==12444)+u.name(x)[-2:].strip()for x in raw_input().decode('utf-8'))
for a,o in zip('KSTH','GZDB'):
    for b in'AEIOU':i=r(r(i,a+b+'xRK','P'+b),a+b+'RK',o+b)
for a,b,c,d in zip('STDZ',('SH','CH','J','J'),'TDHH',('TS','DZ','F','F')):i=r(r(i,a+'I',b+'I'),c+'U',d+'U')
for a in'CH','SH','J':i=r(i,a+'IxY',a)
for a in'BCDFGHJKMNPRSTWYZ':i=r(i,'xTSU'+a,a+a)
print r(i,'Ix','')

To bezpośrednio pobiera dane Unicode, co spowodowało, że straciłem kilka bajtów, decode('utf-8')ale myślę, że jest bardziej w duchu wyzwania.

Zacząłem od zastąpienia każdej postaci dwoma ostatnimi znakami o jej nazwie Unicode, jak sugerowano w notatkach do układanki. Niestety, to nie rozróżnia alternatywnych wersji tej samej postaci, więc musiałem zrobić brzydki hack, aby dodać „x” przed małymi postaciami i handakutenem.

Reszta pętli for tylko naprawia wyjątki, w celu:

  1. pierwsza pętla for zamienia dakutens i handakutens we właściwe spółgłosek;
  2. druga dla pętli dotyczy wyjątków hiragana shi, chi, tsu i fu;
  3. trzecia dla pętli dotyczy wyjątków przed małą literą y (jak sha, jo);
  4. czwarty dla pętli dotyczy podwojenia spółgłosek po małym tsu.
  5. ostatnia linia zajmuje się małym y-.

Chciałbym móc połączyć więcej kroków, ale w niektórych przypadkach kroki muszą być wykonane, aby uniknąć konfliktów.

Wypróbuj online! (wersja wieloliniowa z większą liczbą przykładów można znaleźć tutaj ).

ffao
źródło
1
Link TIO
boboquack
Witamy w PPCG. Bardzo fajne pierwsze rozwiązanie :)
Kudłaty
Zamień cztery spacje przed for b in'AEIOU'tabulatorem lub pojedynczym spacją, aby zaoszczędzić 3 bajty. Możesz także użyć from unicodedata import*do zapisania niektórych bajtów - nie jestem pewien.
Stephen
4

Swift 3, 67 64 znaków

niech r = {(s: String) w s.applyingTransform (.toLatin, reverse: false)}

let r={(s:String)in s.applyingTransform(.toLatin,reverse:false)}
idrougge
źródło
3
Wbudowany, naprawdę, Swift ma W TYM BUDOWĘ?
Zacharý
W ogóle nie znam Swift, ale czy potrafisz przeciąć białe spacje po s:String)i .toLatin,?
Yytsi
@TuukkaX, dobrze zauważony!
idrougge,
@ Zacharý, well Foundationhas.
idrougge,
3

Python 3 , 259 bajtów

import re,unicodedata as u
s=re.sub
n=u.normalize
k,*r=r'NFKC DZU DU TSU TU \1\1 SM.{6}(.) \1 (CH|J|SH)Y \1 ISMALL.(Y.) CHI TI JI [ZD]I SHI SI FU HU'.split()
t=''.join(u.name(c)[16:]for c in n(k,s(' ','',n(k,input()))))
while r:t=s(r.pop(),r.pop(),t)
print(t)

Wypróbuj online!

Wyjaśnienie

Mamy szczęście z tym formatem wejściowym! Zobacz, co się stanie, jeśli przekażę dane wejściowe przez normalizację NFKC :

>>> nfkc = lambda x: u.normalize('NFKC', x)
>>> [u.name(c) for c in 'は゛']
['HIRAGANA LETTER HA', 'KATAKANA-HIRAGANA VOICED SOUND MARK']
>>> [u.name(c) for c in nfkc('は゛')]
['HIRAGANA LETTER HA', 'SPACE', 'COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK']

Dakuten zostaje zastąpiony spacją i łączącym dakutenem. Teraz ta przestrzeń oddziela は od dakutenu. Pozbywamy się tego i normalizujemy ponownie :

>>> [u.name(c) for c in nfkc(nfkc('は゛').replace(' ', ''))]
['HIRAGANA LETTER BA']

Bingo Piąta linia zmienia dane wejściowe w coś podobnego

KONOSUBARASIISEKAINISISMALL YUKUHUKUWO

Następnie stosujemy 9 nudnych podstawień wyrażeń regularnych wciśniętych ri gotowe:

KONOSUBARASHIISEKAINISHUKUFUKUWO

(Jonathan French zapisał 4 bajty, import re,unicodedata as uzamiast pisać import re;from unicodedata import*. Dzięki!)

Lynn
źródło
Nadużywanie normalizacji dla zabawy i zysku. To jest piękne.
Tim Pederick
2
import re,unicodedata as utak jak w Kirill L. odpowiedź na powiązane wyzwanie oszczędza 4 bajty .
Jonathan Frech