あなたはロマナイザー、ベイビー


38

日本語のローマ字化は、日本語のテキストをラテン文字に変換しています。このチャレンジでは、入力として日本語の文字列が与えられ、それらを正しいASCII文字列に変換することが期待されます。

知っておくべきこと

日本語には、ひらがな(短い単語に使用される曲線のある文字)、カタカナ(他の言語から借用した音や単語に使用される角度のある文字)、および漢字(元々は中国語に由来する密集した文字)の3つの表記体系があります。この課題では、ひらがなだけを心配します。

ひらがなの五十音には46文字あります。各文字は音節を表します。キャラクターは、最初の音(子音)と2番目の音(母音)で構成されています。順序の列はaiueoです。

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

(この表をコピーして貼り付ける場合、表意文字スペースU + 3000を使用してyとwの間隔を空けていることに注意してください)

したがって、たとえば、あとめはの出力を生成する必要がありますatome。最初の文字はa、2番目はto、3番目はmeです。

例外

他の優れた言語と同様に、日本語にはその規則の例外があり、ひらがなの表にはいくつかの例外があります。これらの文字の発音は、表内の位置が意味するものとはわずかに異なります。

し:shi、not si
ち:chiti
nottsu:tsu、not tu
ふ:fu、nothu

濁天゛

「濁」という言葉は「泥だらけのマーク」を意味します:濁点は、音声を(通常)有声音に変換します。たとえば、kaかはか゛に変わりgaます。変更の完全なリスト:

kg
sz
td
hb

例外も変わります:しゅ:(jiまたはzhi)、not zi
ち゛:jidi
nottsu゛:dzu、ないdu
(ぶは期待どおりに動作します;それは例外ではありません)

ハンダクテンは、行に適用される追加文字゜ですh。キャラクターの後に置かれた場合、キャラクターのサウンドをpでなくに変更しbます。

濁点と半濁点の両方が個別のキャラクターとして与えられます。事前に構成されたフォームや結合文字を扱う必要はありません。

小さいキャラクター

最後に、いくつかのキャラクターの小さなバージョンがあります。それらは、それらの前後の文字を変更します。

ゃゅょ

これらは、少量の形態であるyayuyo。それらは- i列の音の後にのみ配置されます。削除し、iサウンドを追加します。だから、きやはkiya; きゃがになりkyaます。

chiまたはshi(またはそれらの濁点付きの形式)の後に置かれた場合、yも削除されます。しゆはshiyu; しゅですshu

最後に対処しなければならないことは小さいことtsuです。っは、その後に続く子音を2倍にします。それ以外は何もしません。例えば、きたですkita。きったはkittaです。

要約、入力、および出力

プログラムは、46の基本的なひらがな、濁点と半濁点、および小さな文字との組み合わせを音訳できる必要があります。

未定義の動作が含まれています:小型yayuyoいないと文字の後にi小さな、tsu文字列の最後に、非上handakuten影響を受けていない文字、上濁点p文字、そして何か他のものは、上記のスペック/冒頭で言及されていません。

すべての入力が有効で、上記の日本語文字のみが含まれていると想定できます。

出力では大文字と小文字は区別されません。あなたも交換することができるrとともにl、または単独nm。出力では、すべての音節の間にスペースを1つ入れることも、スペースをまったく入れないこともできます。

これはです。バイト単位の最短コードが優先されます。

テストケース

個々の部品の多くのテストケースが仕様に記載されています。いくつかの追加のケース:

ひらか゛な→ hiragana

かたかな→ katakana

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

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

か゛んほ゛って→ ganbatte

ノート

  • ここで書いたこと以外、日本語はあまり知りません。間違いを犯した場合はお知らせください。

  • 私はもともとカタカナも含めることを計画していました(そのため、英語の音訳テストケースが少し正確になる可能性があります)が、それはコードゴルフチャレンジには多すぎます。

  • Unicode名には、各文字の音訳が個別に含まれますが、例外はありません。これはあなたにとって役に立つかもしれませんし、そうでないかもしれません。

  • 2つのタイプミスを修正してくれたsqueamishossifrageに感謝します!

  • これが長すぎる場合は申し訳ありません。ひらがなの癖のほとんどを課題に当てはめようとしましたが、課題を管理しやすくするために、いくつかのこと(小さな母音のみのひらがな、子音の前でnをmに変更、繰り返しマークなど)をカットする必要がありました。

  • タイトルについては、すみません。それは傑作です。


1
出力は何にすべききっったですか?
リトシアスト

@Thomas:それは無効な入力です。出力は何でも構いません。
デウソビ

1
なければならないっしことsshishshi
リスト管理者

2
I'm not at all sorry for the title. It's a masterpiece.ダウン投票
致命的

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でテストする


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')が、チャレンジの精神のほうが大きいと思います。

パズルのメモで示唆されているように、すべての文字をユニコード名の最後の2文字で置き換えることから始めました。残念ながら、これは同じキャラクターの代替バージョンを区別しないため、小さなキャラクターとハンダクテンの前に「x」を追加するためにいハックをしなければなりませんでした。

残りのforループは、例外を順番に修正するだけです。

  1. 最初のforループはdakutensとhandakutensを正しい子音に変換します。
  2. 2番目のforループは、shi、chi、tsu、およびfuのひらがな例外を処理します。
  3. 3番目のforループは、小さなy文字(sha、joなど)の前の例外を処理します。
  4. 4番目のforループは、小さな津の後の子音の倍増を処理します。
  5. 最後の行は小さなy-を扱います。

さらに多くの手順を組み合わせることを望んでいますが、場合によっては、競合を避けるために手順を実行する必要があります。

オンラインでお試しください!(他の例が含まれる複数行バージョンは、こちらにあります)。



PPCGへようこそ。非常に素晴らしい最初の解決策:)
シャギー

前面の4つのスペースをfor b in'AEIOU'タブまたは1つのスペースに変えて、3バイト節約します。また、使用することができるかもしれfrom unicodedata import*ないことを確認-いくつかのバイトを保存します。
スティーブン

4

Swift 3、67 64文字

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

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

3
組み込みの、本当に、Swiftにはこのためのビルトインがありますか?
ザカリー

Swiftをまったく知りませんが、s:String)との後に空白を切り取ることができます.toLatin,か?
イッツィー

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

ビンゴ。5行目は、入力を次のようなものに変えます

KONOSUBARASIISEKAINISISMALL YUKUHUKUWO

次にr、に詰め込まれた9つの退屈な正規表現の置換を適用し、完了です。

KONOSUBARASHIISEKAINISHUKUFUKUWO

(ジョナサン・フレンチは4バイトを節約し、import re,unicodedata as u代わりに書き込みますimport re;from unicodedata import*。ありがとう!)


楽しさと利益のために正規化を乱用する。美しいです。
ティムペデリック

2
import re,unicodedata as u以下のようにキリル・L.関連の課題への答えはセーブ4バイト
ジョナサンフレッチ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.