Ты романизатор, детка

38

Романизация японского языка - это преобразование японского текста в латинские символы. В этом вызове вам будет предоставлена ​​строка японских символов в качестве входных данных, и ожидается, что они будут преобразованы в правильную строку ASCII.

Что нужно знать

В японском языке есть три системы письма: хирагана (соблазнительная, используемая для коротких слов), катакана (угловая, используемая для звуков и слов, заимствованных из других языков) и кандзи (плотные символы, первоначально взятые из китайского языка). В этом вызове мы будем беспокоиться только о хирагане.

В программе хирагана 46 символов. Каждый символ представляет собой слог. Символы организованы по первому звуку (согласный) и второму звуку (гласный). Столбцы в порядке aiueo.

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

(если вы скопируете и вставите эту таблицу, обратите внимание, что я использовал идеографические пробелы U + 3000 для разнесения y и w)

Так, например, あ と め должен выдавать результат atome. Первый символ есть a, второй есть to, а третий есть me.

Исключения

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

し: shi, не si
ち: chi, не ti
つ: tsu, не tu
ふ: fu, неhu

Дакутен ゛

Слово «дакутен» означает «грязный знак»: дакутен превращает звуки в их озвученные эквиваленты (обычно); например, かkaпревращается в か ゛ga. Полный список изменений:

kg
sz
td
hb

Меняются и исключения: し ゛: ji(или zhi), а не zi
ち ゛: ji, не di
つ ゛: dzu, не du
(ふ ふ действует так, как вы ожидаете; это не исключение)

Handakuten является дополнительным символом ゜, который применяется к hстроке. Если поместить после персонажа, он меняет звук персонажа на, pа не b.

И дакутен, и хандакутен будут даны как отдельные персонажи. Вам не нужно иметь дело с заранее составленными формами или комбинирующими символами.

Маленькие персонажи

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

ゃ ゅ ょ

Это небольшие формы ya, yuи yo. Они помещаются только после звуков в iколонке; они удаляют iи добавляют свой звук. Итак, や や превращается в kiya; ゃ ゃ превращается в kya.

Если поместить после chiили shi(или их dakuten-ed формы), yтоже удаляется. ゆ ゆ есть shiyu; ゅ ゅ есть shu.

Последнее, с чем вам придется иметь дело, это маленький tsu. っ удваивает согласный, который следует за ним, несмотря ни на что; больше ничего не делает Например, た た есть kita; た っ た есть kitta.

Сводка, ввод и вывод

Ваша программа должна быть способна транслитерировать: 46 основных хирагана, их формы дакутен и хандакутен и их комбинации с маленькими символами.

Неопределенное поведение включает в себя: small ya, yuа yoне после символа с ismall tsuв конце строки, dakuten для незатронутого символа, handakuten для не pсимвольного и все остальное, не упомянутое в приведенной выше спецификации / введении.

Вы можете предположить, что все входные данные верны и содержат только японские символы, упомянутые выше.

Дело не имеет значения в выводе; Вы можете также заменить rс lили одиночкой nс m. Вывод может иметь либо один пробел между каждым слогом, либо не иметь пробелов вообще.

Это : выигрывает самый короткий код в байтах.

Тестовые случаи

Многие тестовые случаи для каждой отдельной части приведены в спецификации. Некоторые дополнительные случаи:

ひ ら か ゛ な → hiragana

な た か な → katakana

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

ふ ゜ ろ く ゛ ら ん ん ゛ は ゜ ゜ る る と ゛ ゛ ふ ふ ふ → puroguramingupazurucoudogorufu

て ゛ ん ほ ゛ っ て → ganbatte

Заметки

  • Я не знаю много японского, кроме того, что я здесь написал. Пожалуйста, дайте мне знать, если я сделал какие-либо ошибки.

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

  • Имена Unicode включают транслитерацию каждого символа в отдельности, но без исключений. Это может или не может быть полезным для вас.

  • Спасибо squeamishossifrage за исправление двух опечаток!

  • Извините, если это слишком долго; Я попытался вписать большинство пристрастий хираганы в вызов, но некоторые вещи (например, маленькая хирагана, состоящая только из гласных, изменение n на m перед некоторыми согласными и знак повторения) пришлось сократить, чтобы сохранить управляемость задачи.

  • Я совсем не сожалею о названии. Это шедевр.

Deusovi
источник
1
Для чего должен быть выход きっった?
Lirtosiast
@ Томас: Это неверный ввод. Вывод может быть любым, что вы хотите.
Деусови
1
должно っしбыть sshiили shshi?
lirtosiast
2
I'm not at all sorry for the title. It's a masterpiece.Downvoted
Fatalize
3
@Fatalize Не нужно приводить здесь свой анти-британский уклон. Хотя я лично могу быть большим поклонником J-Lo, я не собираюсь недооценивать превосходную загадку по этому поводу.
Половинное

Ответы:

7

Python 2, 638 байт

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)

Принимает ввод в виде строки Unicode.

Проверьте это на Ideone

TFeld
источник
1
Вы можете сохранить жалкое прощание, перейдя print ''.join(R)наprint''.join(R)
Zacharý
6

Python 2, 447 байт

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','')

Это требует ввода Unicode напрямую, что заставило меня потерять несколько байтов из-за, decode('utf-8')но я думаю, что это больше в духе задачи.

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

Остальные циклы for просто исправляют исключения в следующем порядке:

  1. первый цикл for превращает дакутены и handakutens в правильные согласные;
  2. второй цикл for касается исключений хирагана из ши, ци, цу и фу;
  3. третий цикл for работает с исключениями перед маленьким символом y (например, sha, jo);
  4. Четвёртый для цикла имеет дело с удвоением согласных после небольшой цзу.
  5. Последняя строка имеет дело с маленьким y-.

Я хотел бы объединить больше шагов, но в некоторых случаях шаги должны быть выполнены, чтобы избежать конфликтов.

Попробуйте онлайн! (многострочную версию с большим количеством примеров можно найти здесь ).

ffao
источник
1
Ссылка
TIO
Добро пожаловать в PPCG. Очень хорошее первое решение :)
Shaggy
Превратите четыре пробела перед for b in'AEIOU'собой во вкладку или один пробел, чтобы сохранить 3 байта. Вы также можете использовать from unicodedata import*для сохранения некоторых байтов - не уверен.
Стивен
4

Свифт 3, 67 64 персонажа

let r = {(s: String) в s.applyingTransform (.toLatin, reverse: false)}

let r={(s:String)in s.applyingTransform(.toLatin,reverse:false)}
idrougge
источник
3
Неужели у Свифта есть встроенная система?
Захари
Свифта вообще не знаю, но можно ли разделить пробелы после s:String)и .toLatin,?
Yytsi
@TuukkaX, хорошо заметили!
idrougge
@ Захари, хорошо Foundation.
idrougge
3

Python 3 , 259 байт

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)

Попробуйте онлайн!

объяснение

Нам повезло с этим форматом ввода! Посмотрите, что произойдет, если я пропущу ввод через нормализацию 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']

Дакутен заменяется пробелом и комбинацией дакутен. Теперь это пространство - это все, что отделяет は от своего дакутена. Итак, мы избавляемся от этого и нормализуем снова :

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

Бинго. Пятая строка превращает ввод в нечто вроде

KONOSUBARASIISEKAINISISMALL YUKUHUKUWO

Затем мы применяем 9 скучных замен регулярных выражений r, и все готово:

KONOSUBARASHIISEKAINISHUKUFUKUWO

(Джонатан Френч сэкономил 4 байта, записав import re,unicodedata as uвместо import re;from unicodedata import*. Спасибо!)

Линн
источник
Злоупотребление нормализацией ради удовольствия и наживы. Это красиво.
Тим Педерик
2
import re,unicodedata as uкак и у Кирилла Л., ответ на связанный вызов экономит 4 байта .
Джонатан Фрех