宝贝,你是古罗马作家


38

日语的罗马化将日语文本转换为拉丁字符。在此挑战中,将为您提供一串日文字符作为输入,并期望将其转换为正确的ASCII字符串。

您需要知道什么

日语有三种书写系统:平假名(弯曲的用于简短单词),片假名(用于从其他语言借来的声音和单词的角形)和汉字(最初来自中文的密集字符)。在这个挑战中,我们将只担心平假名。

平假名音节中有46个字符。每个字符代表一个音节。字符按第一声音(辅音)和第二声音(元音)组织。按顺序排列的列是aiueo

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

(如果复制并粘贴此表,请注意,我已使用表意空格U + 3000来分隔y和w)

因此,例如あとめ应该产生的输出atome。第一个是a,第二个是to,第三个是me

例外情况

像任何一种好的语言一样,日语也有其规则的例外,而平假名表也有几种例外。这些字符的发音与其在表中的位置所暗示的略有不同:

し:shi,not si
ち:chi,not ti
つ:tsu,not tu
ふ:fu,nothu

达库ten

“ dakuten”一词的意思是“泥泞的印记”:dakuten将声音转换成它们的浊音(通常);例如,かka变成か゛ga。更改的完整列表:

k→交通g
s→交通z
t→交通d
h→交通b

例外也会发生变化:し゛:(jizhi),不是zi
ち゛:ji,不是di
つ゛:dzu,而不是du
(ふ゛的行为符合您的预期;这不是例外)

handakuten是适用于该行的附加字符゜h。如果放置在角色后面,则会将角色的声音更改为,p而不是b

dakuten和handakuten都将作为单个字符给出。您将不需要处理预先组成的表格或组合字符。

小字

最后,有些字符有一些小版本。他们修改在其之前或之后的字符。

ゃゅょ

这些都是小的形式yayuyo。仅将它们放在- i列中的声音之后;他们删除i并添加声音。因此,きや变成kiya;きゃ变成kya

如果放在chishi(或以其作废的形式)之后,则y也会被删除。しゆ是shiyu; しゅ是shu

您需要处理的最后一件事是小事务tsu。っ无论如何,将其后的辅音加倍;它什么也没做。例如,きた是kita; きった是kitta

摘要,输入和输出

您的程序必须能够音译:46种基本的平假名,其dakuten和handakuten形式以及它们与小字符的组合。

未定义行为包括:小yayuyo没有后一个字i,小的tsu在一个字符串的结尾,浊音标志上不受影响的人物,半浊音上非p字符,和其他任何不在上述规格/介绍中提到。

您可以假定所有输入均有效,并且仅包含上述日语字符。

输出大小写无关紧要;您也可以替换rl或单独n使用m。输出在每个音节之间可以有一个空格,也可以根本没有空格。

这是:以字节为单位的最短代码获胜。

测试用例

规范中为每个单独的部分提供了许多测试用例。其他一些情况:

ひらか゛な→ hiragana

かたかな→ katakana

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

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

か゛んほ゛って→ ganbatte

笔记

  • 除了我在这里写的东西外,我对日语也不太了解。如果我有任何错误,请告诉我。

  • 我原本也打算将片假名也包含在内(因此我的英语音译测试用例可能会稍微准确一些),但这对于高尔夫编程挑战来说实在太多了。

  • Unicode名称分别包括每个字符的音译,但没有例外。这可能对您没有帮助。

  • 感谢squeamishossifrage纠正了两个错别字!

  • 如果时间太长,我感到抱歉。我试图使平假名的大多数怪癖适应挑战,但必须切掉某些事物(例如,仅元音的小平假名,在某些辅音之前将n更改为m,以及重复标记)以使挑战易于处理。

  • 我完全不为这个标题感到抱歉。这是杰作。


1
输出应该是什么きっった
lirtosiast,2015年

@Thomas:这是无效的输入。输出可以是任何您想要的。
Deusovi

1
应该っしsshi还是shshi
lirtosiast,2015年

2
I'm not at all sorry for the title. It's a masterpiece.不赞成投票
Fatalize

3
@Fatalize无需在这里提出您的反布兰妮偏见。即使我个人可能更喜欢J-Lo迷,但我不会为此而拒绝一个很好的难题。
2015年

Answers:


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测试


1
您可以通过更改保存进账再见print ''.join(R)print''.join(R)
扎卡里

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')但是我认为这更多是本着挑战的精神。

首先,按照谜题注释中的建议,将每个字符替换为其Unicode名称的最后两个字符。不幸的是,这不能区分相同字符的替代版本,因此我不得不做出丑陋的修改,在小字符和handakuten之前添加“ x”。

其余的for循环仅按顺序修复异常:

  1. 第一个for循环将dakutens和handakutens转换为正确的辅音;
  2. 第二个for循环处理shi,chi,tsu和fu的平假名例外;
  3. 第三个for循环处理小y字符之前的异常(如sha,jo);
  4. 第四次for loop处理小tsu之后加倍的辅音。
  5. 最后一行处理小y-。

我希望我可以合并更多的步骤,但是在某些情况下,必须执行这些步骤以避免冲突。

在线尝试!(可在此处找到包含更多示例的多行版本)。



欢迎来到PPCG。非常好的第一个解决方案:)
毛茸茸的

将您前面的四个空格for b in'AEIOU'变成制表符或单个空格以节省3个字节。您可能还可以from unicodedata import*用来保存一些字节-不确定。
斯蒂芬,

4

Swift 3,67 64个字符

让r = {(s:String)在s.applyingTransform(.toLatin中,反向:false)}

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

3
一个内置的,真的,Swift有这个功能吗?
扎卡里

根本不了解Swift,但是您可以在s:String)和之后砍掉空白.toLatin,吗?
Yytsi '17

@TuukkaX,发现得很好!
idrougge '17

@Zacharý,很好Foundation
idrougge '17

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

dakuten被替换为空格和组合的dakuten。现在,空间已将は和dakuten隔开了。因此,我们摆脱了它并再次规范化:

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

答对了。第五行将输入变成类似

KONOSUBARASIISEKAINISISMALL YUKUHUKUWO

然后,我们应用填入的9个无聊的正则表达式替换r,我们完成了:

KONOSUBARASHIISEKAINISHUKUFUKUWO

(Jonathan French保存了4个字节,import re,unicodedata as u而不是写了import re;from unicodedata import*。谢谢!)


滥用规范化来获取乐趣和利润。那好美丽。
蒂姆·佩德里克

2
import re,unicodedata as uKirill L.回答相关挑战节省4个字节
乔纳森·弗雷希
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.