Anda seorang Romanizer, Sayang

38

Romanisasi bahasa Jepang mengubah teks bahasa Jepang menjadi karakter Latin. Dalam tantangan ini, Anda akan diberikan string karakter Jepang sebagai input dan diharapkan untuk mengubahnya menjadi string ASCII yang benar.

Yang Perlu Anda Ketahui

Bahasa Jepang memiliki tiga sistem penulisan: hiragana (kurva yang digunakan untuk kata-kata pendek), katakana (sudut-y yang digunakan untuk bunyi dan kata-kata yang dipinjam dari bahasa lain), dan kanji (karakter padat yang berasal dari bahasa Cina). Dalam tantangan ini kita hanya akan mengkhawatirkan hiragana.

Ada 46 karakter di suku kata hiragana. Setiap karakter mewakili suku kata. Karakter diatur oleh bunyi pertama (konsonan) dan bunyi kedua (vokal). Kolom secara berurutan adalah aiueo.

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

(jika Anda menyalin dan menempel tabel ini, perhatikan bahwa saya telah menggunakan spasi ideografi U + 3000 untuk menghapus y dan w)

Jadi, misalnya, あ と め harus menghasilkan output atome. Karakter pertama adalah a, yang kedua adalah to, dan yang ketiga adalah me.

Pengecualian

Seperti bahasa yang bagus, bahasa Jepang memiliki pengecualian terhadap aturannya, dan tabel hiragana memiliki beberapa. Karakter-karakter ini diucapkan sedikit berbeda dari yang ditunjukkan oleh lokasinya dalam tabel:

し: shi, bukan si
ち: chi, bukan ti
つ: tsu, bukan tu
ふ: fu, tidakhu

Dakuten ゛

Kata 'dakuten' berarti 'tanda berlumpur': sang dakuten mengubah suara menjadi padanan suaranya (biasanya); misalnya, かkaberubah menjadi か ゛ga. Daftar lengkap perubahan:

kg
sz
td
hb

Pengecualian juga berubah: し ゛: ji(atau zhi), bukan zi
ち ゛: ji, bukan di
つ ゛: dzu, tidak du
(ふ ゛ bertindak seperti yang Anda harapkan; ini bukan pengecualian)

Handakuten adalah karakter tambahan゜ yang berlaku untuk hbaris. Jika ditempatkan setelah karakter, itu mengubah suara karakter menjadi pdaripada b.

Baik dakuten dan handakuten akan diberikan sebagai karakter individu. Anda tidak perlu berurusan dengan formulir yang dikomposisi sebelumnya atau karakter yang menggabungkan.

Karakter kecil

Akhirnya, ada versi kecil dari beberapa karakter. Mereka memodifikasi karakter yang datang sebelum atau sesudahnya.

ゃ ゅ ょ

Ini adalah bentuk kecil ya, yudan yo. Mereka hanya ditempatkan setelah suara di ikolom; mereka menghapus idan menambahkan suara mereka. Jadi, き や berubah menjadi kiya; き ゃ berubah menjadi kya.

Jika ditempatkan setelah chiatau shi(atau bentuk dakuten-ed mereka), yitu dihapus juga. し ゆ adalah shiyu; し ゅ adalah shu.

Hal terakhir yang harus Anda tangani adalah hal kecil tsu. っ menggandakan konsonan yang datang setelah itu, tidak peduli apa; tidak melakukan apa-apa lagi. Misalnya, き た adalah kita; き っ た adalah kitta.

Ringkasan, Input, dan Output

Program Anda harus bisa transliterasi: 46 hiragana dasar, bentuk dakuten dan handakuten mereka, dan kombinasinya dengan karakter kecil.

Perilaku tidak terdefinisi meliputi: kecil ya, yudan yotidak setelah karakter dengan i, kecil tsudi akhir string, dakuten pada karakter yang tidak terpengaruh, handakuten pada pkarakter non- , dan apa pun yang tidak disebutkan dalam spesifikasi / pengantar di atas.

Anda dapat menganggap semua input valid dan hanya berisi karakter Jepang yang disebutkan di atas.

Kasus tidak menjadi masalah dalam output; Anda juga dapat mengganti rdengan latau sendirian ndengan m. Output dapat memiliki satu ruang antara setiap suku kata atau tanpa spasi sama sekali.

Ini adalah : kode terpendek dalam byte menang.

Uji Kasus

Banyak kasus uji untuk masing-masing bagian diberikan dalam spesifikasi. Beberapa kasus tambahan:

ひ ら か ゛ な → hiragana

か た か な → katakana

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

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

か ゛ ん ほ ゛ っ て → ganbatte

Catatan

  • Saya tidak tahu banyak bahasa Jepang selain apa yang saya tulis di sini. Tolong beri tahu saya jika saya melakukan kesalahan.

  • Saya awalnya berencana untuk memasukkan katakana juga (jadi kasus tes transliterasi bahasa Inggris saya bisa sedikit lebih akurat), tetapi itu akan terlalu banyak untuk tantangan kode golf.

  • Nama-nama Unicode termasuk transliterasi setiap karakter secara individual, tetapi tanpa pengecualian. Ini mungkin atau mungkin tidak bermanfaat bagi Anda.

  • Berkat squeamishossifrage untuk mengoreksi dua kesalahan ketik!

  • Maaf jika ini terlalu panjang; Saya berusaha memasukkan sebagian besar keanehan hiragana ke dalam tantangan, tetapi beberapa hal (seperti hiragana yang hanya menggunakan vokal kecil, ganti n ke m di depan beberapa konsonan, dan tanda pengulangan) harus dipotong untuk menjaga agar tantangan dapat dikelola.

  • Saya sama sekali tidak menyesal dengan judulnya. Itu adalah sebuah mahakarya.

Deusovi
sumber
1
Untuk apa outputnya きっった?
lirtosiast
@ Thomas: Itu input yang tidak valid. Output dapat berupa apa pun yang Anda inginkan.
Deusovi
1
harus っしmenjadi sshiatau shshi?
lirtosiast
2
I'm not at all sorry for the title. It's a masterpiece.Downvoted
Fatalize
3
@Fatalize Tidak perlu membawa bias anti-Britney Anda di sini. Meskipun saya pribadi mungkin lebih dari penggemar J-Lo, saya tidak akan menurunkan puzzle yang bagus tentang itu.
semi-ekstrinsik

Jawaban:

7

Python 2, 638 byte

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)

Mengambil input sebagai string unicode.

Uji di Ideone

TFeld
sumber
1
Anda dapat menyimpan sedikit bye dengan mengubah print ''.join(R)keprint''.join(R)
Zacharý
6

Python 2, 447 byte

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

Ini mengambil input Unicode secara langsung, yang membuat saya kehilangan beberapa byte karena decode('utf-8')tapi saya pikir lebih dalam semangat tantangan.

Saya mulai dengan mengganti setiap karakter dengan dua karakter terakhir dari nama unicode-nya, seperti yang disarankan dalam catatan puzzle. Sayangnya, ini tidak membedakan antara versi alternatif dari karakter yang sama, jadi saya harus membuat retas jelek untuk menambahkan 'x' sebelum karakter kecil dan handakuten.

Sisa loop for hanya memperbaiki pengecualian, dalam rangka:

  1. yang pertama untuk loop mengubah dakutens dan handakutens menjadi konsonan yang benar;
  2. yang kedua untuk penawaran loop dengan pengecualian hiragana dari shi, chi, tsu dan fu;
  3. ketiga untuk perulangan berhubungan dengan pengecualian sebelum karakter y kecil (seperti sha, jo);
  4. keempat untuk kesepakatan loop dengan menggandakan konsonan setelah tsu kecil.
  5. penawaran baris terakhir dengan y- kecil.

Saya berharap saya bisa menggabungkan lebih banyak langkah, tetapi dalam beberapa kasus langkah-langkah harus dilakukan untuk menghindari konflik.

Cobalah online! (versi multisaluran dengan lebih banyak contoh dapat ditemukan di sini ).

teman
sumber
1
TIO link
boboquack
Selamat datang di PPCG. Solusi pertama yang sangat bagus :)
Shaggy
Ubah empat spasi Anda di depan for b in'AEIOU'menjadi tab atau satu ruang untuk menghemat 3 byte. Anda juga dapat menggunakan from unicodedata import*untuk menyimpan beberapa byte - tidak yakin.
Stephen
4

Cepat 3, 67 64 karakter

biarkan r = {(s: String) di s.applyingTransform (.toLatin, membalikkan: false)}

let r={(s:String)in s.applyingTransform(.toLatin,reverse:false)}
idrougge
sumber
3
Sebenarnya, Swift punya BUILTIN UNTUK INI?
Zacharý
Tidak tahu Swift sama sekali, tetapi bisakah Anda memotong spasi putih setelah s:String)dan .toLatin,?
Yytsi
@ TuukkaX, terlihat dengan baik!
idrougge
@ Zacharý, Foundationsudah.
idrougge
3

Python 3 , 259 byte

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)

Cobalah online!

Penjelasan

Kami beruntung dengan format input ini! Lihat apa yang terjadi jika saya meneruskan input melalui normalisasi 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 digantikan oleh spasi dan dakuten gabungan. Sekarang hanya ruang yang memisahkan は dari dakutennya. Jadi kita menyingkirkannya dan menormalkan lagi :

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

Bingo. Baris kelima mengubah input menjadi sesuatu seperti

KONOSUBARASIISEKAINISISMALL YUKUHUKUWO

Lalu kami menerapkan 9 penggantian membosankan membosankan dijejalkan r, dan kami selesai:

KONOSUBARASHIISEKAINISHUKUFUKUWO

(Jonathan French menyimpan 4 byte, import re,unicodedata as ualih-alih menulis import re;from unicodedata import*. Terima kasih!)

Lynn
sumber
Menyalahgunakan normalisasi untuk kesenangan dan keuntungan. Itu indah.
Tim Pederick
2
import re,unicodedata as useperti pada Kirill L. jawaban untuk tantangan terkait menghemat 4 byte .
Jonathan Frech