Sei un romanilizzatore, piccola


38

La romanizzazione del giapponese sta convertendo il testo giapponese in caratteri latini. In questa sfida, ti verrà data una stringa di caratteri giapponesi come input e dovrai convertirli nella stringa ASCII corretta.

Cosa devi sapere

La lingua giapponese ha tre sistemi di scrittura: hiragana (quello sinuoso usato per le parole brevi), katakana (quello angolare usato per i suoni e le parole presi in prestito da altri linguaggi) e kanji (i caratteri densi originari del cinese). In questa sfida ci preoccuperemo solo degli hiragana.

Ci sono 46 personaggi nel sillabario hiragana. Ogni personaggio rappresenta una sillaba. I personaggi sono organizzati per primo suono (consonante) e secondo suono (vocale). Le colonne in ordine sono aiueo.

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

(se copi e incolli questa tabella, nota che ho usato gli spazi ideografici U + 3000 per spaziare y ew)

Quindi, per esempio, あ と め dovrebbe produrre un output di atome. Il primo personaggio è a, il secondo è toe il terzo lo è me.

eccezioni

Come ogni buona lingua, il giapponese ha delle eccezioni alle sue regole e la tabella hiragana ne ha diverse. Questi personaggi sono pronunciati in modo leggermente diverso rispetto alla loro posizione nella tabella:

し: shi, non si
ち: chi, non ti
つ: tsu, non tu
ふ: fu, nonhu

Dakuten ゛

La parola "dakuten" significa "marchio fangoso": i dakuten trasformano i suoni nei loro equivalenti espressi (di solito); ad esempio, かkasi trasforma in か ゛ga. Un elenco completo delle modifiche:

kg
sz
td
hb

Anche le eccezioni cambiano: し ゛: ji(o zhi), non zi
ち ゛: ji, non di
つ ゛: dzu, non du
(ふ ゛ agisce come ti aspetteresti; non è un'eccezione)

Il handakuten è un carattere aggiuntivo゜ che si applica alla hriga. Se posto dopo un personaggio, cambia il suono del personaggio in ppiuttosto che b.

Sia il dakuten che il handakuten verranno dati come singoli personaggi. Non dovrai occuparti delle forme precomposte o dei personaggi combinati.

Piccoli personaggi

Infine, ci sono piccole versioni di alcuni dei personaggi. Modificano i personaggi che li precedono o li seguono.

ゃ ゅ ょ

Queste sono le piccole forme di ya, yue yo. Sono posizionati solo dopo i suoni nella icolonna-; rimuovono ie aggiungono il loro suono. Quindi, き や si trasforma in kiya; き ゃ si trasforma in kya.

Se posizionato dopo chio shi(o le loro forme modificate), yviene rimosso anche. し ゆ è shiyu; し ゅ è shu.

L'ultima cosa che dovrai affrontare è la piccola tsu. っ raddoppia la consonante che lo segue, qualunque cosa accada; non fa nient'altro. Ad esempio, き た è kita; き っ た è kitta.

Riepilogo, input e output

Il tuo programma deve essere in grado di traslitterare: i 46 hiragana di base, le loro forme dakuten e handakuten e le loro combinazioni con caratteri piccoli.

Il comportamento indefinito include: piccolo ya, yue yonon dopo un carattere con i, piccolo tsualla fine di una stringa, dakuten su un personaggio non interessato, handakuten su un non pcarattere e qualsiasi altra cosa non menzionata nella specifica / introduzione di cui sopra.

Puoi presumere che tutti gli input siano validi e contengano solo i caratteri giapponesi sopra menzionati.

Il caso non ha importanza in uscita; puoi anche sostituire rcon lo solo ncon m. L'output può avere uno spazio tra ogni sillaba o nessuno spazio.

Questo è : vince il codice più corto in byte.

Casi test

Nella specifica sono riportati molti casi di test per ogni singola parte. Alcuni casi aggiuntivi:

ひ ら か ゛ な → hiragana

か た か な → katakana

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

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

か ゛ ん ほ ゛ っ て → ganbatte

Gli appunti

  • Non conosco molto il giapponese oltre a quello che ho scritto qui. Per favore fatemi sapere se ho commesso degli errori.

  • Inizialmente avevo intenzione di includere anche il katakana (quindi il mio caso di test di traslitterazione in inglese potrebbe essere leggermente più accurato), ma sarebbe troppo per una sfida di golf del codice.

  • I nomi Unicode includono la traslitterazione di ciascun carattere singolarmente, ma senza eccezioni. Questo può o non può esserti utile.

  • Grazie a squeamishossifrage per aver corretto due errori di battitura!

  • Mi dispiace se è troppo lungo; Ho cercato di inserire la maggior parte delle stranezze di Hiragana nella sfida, ma alcune cose (come il piccolo Hiragana solo vocale, cambiando n in m davanti ad alcune consonanti e il segno di ripetizione) hanno dovuto essere tagliate per mantenere gestibile la sfida.

  • Non mi dispiace per il titolo. È un capolavoro.


1
Quale dovrebbe essere l'output per きっった?
lirtosiast

@Thomas: questo è un input non valido. L'output può essere quello che vuoi.
Deusovi,

1
dovrebbe っしessere sshio shshi?
lirtosiast

2
I'm not at all sorry for the title. It's a masterpiece.Downvoted
fatalizza il

3
@Fatalize Non c'è bisogno di portare il tuo pregiudizio anti-britney qui. Anche se personalmente potrei essere più un fan di J-Lo, non voterò un enigma eccellente su questo.
semi-estrinseco il

Risposte:


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)

Accetta l'input come stringa unicode.

Provalo su Ideone


1
Puoi salvare un misero ciao cambiando print ''.join(R)inprint''.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','')

Questo prende direttamente l'input Unicode, il che mi ha fatto perdere qualche byte a causa del decode('utf-8')ma penso che sia più nello spirito della sfida.

Ho iniziato sostituendo ogni personaggio con gli ultimi due caratteri del suo nome unicode, come suggerito nelle note del puzzle. Sfortunatamente, questo non distingue tra versioni alternative dello stesso personaggio, quindi ho dovuto fare un brutto hack per aggiungere una "x" prima dei piccoli personaggi e del handakuten.

Il resto dei cicli for sta solo riparando le eccezioni, nell'ordine:

  1. il primo per loop trasforma dakutens e handakutens nelle consonanti corrette;
  2. il secondo per loop riguarda le eccezioni hiragana di shi, chi, tsu e fu;
  3. il terzo per loop si occupa delle eccezioni prima di un piccolo carattere y (come sha, jo);
  4. il quarto per loop riguarda il raddoppio delle consonanti dopo un piccolo tsu.
  5. la riga finale si occupa di piccoli y-.

Vorrei poter aver combinato più passaggi, ma in alcuni casi è necessario eseguire i passaggi per evitare conflitti.

Provalo online! (una versione multilinea con più esempi è disponibile qui ).



Benvenuti in PPCG. Prima soluzione molto bella :)
Shaggy,

Trasforma i tuoi quattro spazi davanti for b in'AEIOU'in una scheda o in un singolo spazio per salvare 3 byte. Potresti anche essere in grado di utilizzare from unicodedata import*per salvare alcuni byte - non sono sicuro.
Stephen,

4

Swift 3, 67 64 caratteri

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

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

3
Un built-in, davvero, Swift ha un BUILTIN PER QUESTO?
Zacharý,

Non conosco affatto Swift, ma puoi tagliare gli spazi bianchi dopo s:String)e .toLatin,?
Yytsi,

@TuukkaX, ben individuato!
idrougge,

@ Zacharý, bene Foundation.
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)

Provalo online!

Spiegazione

Siamo fortunati con questo formato di input! Guarda cosa succede se passo l'input attraverso la normalizzazione 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']

Il dakuten viene sostituito da uno spazio e un dakuten combinato. Ora quello spazio è tutto ciò che separa は dal suo dakuten. Quindi ci liberiamo di esso e normalizziamo di nuovo :

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

Bingo. La quinta riga trasforma l'input in qualcosa di simile

KONOSUBARASIISEKAINISISMALL YUKUHUKUWO

Quindi applichiamo 9 sostituzioni regex noiose stipate re abbiamo finito:

KONOSUBARASHIISEKAINISHUKUFUKUWO

(Jonathan French ha salvato 4 byte, scrivendo import re,unicodedata as uinvece di import re;from unicodedata import*. Grazie!)


Abusare della normalizzazione per divertimento e profitto. Questo è bello.
Tim Pederick,

2
import re,unicodedata as ucome in Kirill L. la risposta a una sfida correlata consente di risparmiare 4 byte .
Jonathan Frech,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.