Tu es un romaniseur, bébé

38

La romanisation du japonais consiste à convertir du texte japonais en caractères latins. Dans ce défi, vous recevrez une chaîne de caractères japonais en entrée et vous demanderez de les convertir en chaîne ASCII correcte.

Ce que vous aurez besoin de savoir

Le japonais a trois systèmes d'écriture: hiragana (le curvy utilisé pour les mots courts), katakana (l'angle utilisé pour les sons et les mots empruntés à d'autres langues), et le kanji (les caractères denses d'origine chinoise). Dans ce défi, nous ne nous préoccuperons que de l'hiragana.

Le syllabaire hiragana comporte 46 caractères. Chaque caractère représente une syllabe. Les caractères sont organisés par premier son (consonne) et second son (voyelle). Les colonnes dans l'ordre sont aiueo.

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

(si vous copiez et collez ce tableau, notez que j'ai utilisé des espaces idéographiques U + 3000 pour espacer y et w)

Ainsi, par exemple, と め devrait produire une sortie de atome. Le premier caractère est a, le second est toet le troisième estme .

Exceptions

Comme toute bonne langue, le japonais a des exceptions à ses règles, et la table hiragana en a plusieurs. Ces caractères sont prononcés légèrement différemment que leur emplacement dans le tableau impliquerait:

: shi, Pas si
ち: chi, pas ti
つ: tsu, pas tu
ふ: fu, pashu

Dakuten

Le mot «dakuten» signifie «marque boueuse»: le dakuten transforme les sons en leurs équivalents exprimés (généralement); par exemple, かkase transforme en かga. Une liste complète des changements:

kg
sz
td
hb

Les exceptions changent aussi: し ゛: ji(ou zhi), pas zi
ち ゛: ji, pas di
:, dzunotdu
(゛ agit comme vous le voudriez; ce n'est pas une exception)

Le handakuten est un caractère supplémentaire qui s'applique à la hligne. Si placé après un caractère, il change le son du caractère pplutôt queb .

Le dakuten et le handakuten seront donnés individuellement. Vous n'aurez pas besoin de vous occuper des formes précomposées ni des caractères combinés.

Petits personnages

Enfin, il existe des versions réduites de certains personnages. Ils modifient les caractères qui viennent avant ou après eux.

ゅ ょ

Ce sont les petites formes de ya, yuet yo. Ils sont seulement placés après les sons dans la icolonne; ils enlèvent le iet ajoutent leur son. Alors, や や se transforme en kiya; ゃ se transforme enkya .

Si placé après chiou shi(ou leurs formes dakuten-ed), le yest également supprimé. ゆ est shiyu; ゅ estshu .

La dernière chose à laquelle vous devez faire face est la petite tsu. っ double la consonne qui vient après, quoi qu'il arrive; ça ne fait rien d'autre. Par exemple, est kita; っ た estkitta .

Résumé, entrée et sortie

Votre programme doit être capable de translittérer: les 46 hiragana de base, leurs formes dakuten et handakuten et leurs combinaisons avec des petits caractères.

Le comportement non défini inclut: petit ya, yuet yopas après un caractère avec i, petit tsuà la fin d'une chaîne, dakuten sur un caractère non affecté, handakuten sur un nonp caractère et tout autre élément non mentionné dans les spécifications / introduction ci-dessus.

Vous pouvez supposer que toutes les entrées sont valides et ne contiennent que les caractères japonais mentionnés ci-dessus.

La casse n'a pas d'importance en sortie; vous pouvez également remplacer ravec lou un seul navec m. La sortie peut avoir un espace entre chaque syllabe ou aucun espace.

C'est : le code le plus court en octets gagne.

Cas de test

De nombreux cas de test pour chaque pièce individuelle sont donnés dans la spécification. Quelques cas supplémentaires:

か ゛ な → hiragana

た か な → katakana

ん ん ん → daigyakutensaiban

ろ → puroguramingupazurucoudogorufu

ん て → ganbatte

Remarques

  • Je ne connais pas beaucoup de japonais à part ce que j'ai écrit ici. S'il vous plaît laissez-moi savoir si j'ai commis des erreurs.

  • Au départ, je comptais aussi inclure katakana (mon cas de test de translittération en anglais pourrait être légèrement plus précis), mais ce serait trop pour un défi de golf de code.

  • Les noms Unicode incluent la translittération de chaque caractère individuellement, mais sans les exceptions. Cela peut ou peut ne pas vous être utile.

  • Merci à squeamishossifrage pour avoir corrigé deux fautes de frappe!

  • Je suis désolé si c'est trop long. J’ai essayé d’intégrer la plupart des bizarreries de hiragana au défi, mais certaines choses (comme une petite hiragana réservée aux voyelles, changer n en m devant certaines consonnes et la marque de répétition) ont dû être supprimées pour que le défi reste gérable.

  • Je ne suis pas du tout désolé pour le titre. C'est un chef d'oeuvre.

Deusovi
la source
1
A quoi devrait servir la sortie きっった?
lirtosiast
@Thomas: C'est une entrée invalide. La sortie peut être ce que vous voulez.
Deusovi
1
devrait っしêtre sshiou shshi?
lirtosiast
2
I'm not at all sorry for the title. It's a masterpiece.Downvoted
Fatalize
3
@Fatalize Pas besoin d'apporter votre parti pris anti-Britney ici. Même si, personnellement, je suis plus fan de J-Lo, je ne vais pas voter pour un excellent casse-tête à ce sujet.
semi-extrinsèque

Réponses:

7

Python 2, 638 octets

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)

Prend l'entrée en tant que chaîne unicode.

Testez-le sur Ideone

TFeld
la source
1
Vous pouvez sauver un misérable au revoir en changeant print ''.join(R)deprint''.join(R)
Zacharý
6

Python 2, 447 octets

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

Cela prend directement l'entrée Unicode, ce qui m'a fait perdre quelques octets à cause de la decode('utf-8') mais je pense que c'est plus dans l'esprit du défi.

J'ai commencé par remplacer chaque caractère par les deux derniers caractères de son nom unicode, comme suggéré dans les notes du puzzle. Malheureusement, cela ne fait pas la différence entre les versions alternatives du même personnage, j'ai donc dû faire un bidouillage laid pour ajouter un 'x' avant les petits caractères et le handakuten.

Les autres boucles for ne sont que des corrections d’exceptions, dans l’ordre:

  1. la première pour loop transforme dakutens et handakutens en consonnes correctes;
  2. la seconde pour la boucle traite des exceptions hiragana de shi, chi, tsu et fu;
  3. la troisième boucle for traite les exceptions précédant un petit caractère y (comme sha, jo);
  4. la quatrième pour la boucle traite du fait de doubler les consonnes après un petit tsu.
  5. La dernière ligne traite des petits y-.

J'aurais aimé pouvoir combiner plus d'étapes, mais dans certains cas, ces étapes doivent être exécutées afin d'éviter les conflits.

Essayez-le en ligne! (une version multiligne avec plus d'exemples peut être trouvée ici ).

ffao
la source
1
Lien TIO
boboquack
Bienvenue chez PPCG. Très belle première solution :)
Shaggy
Transformez vos quatre espaces devant for b in'AEIOU'en un onglet ou un seul espace pour économiser 3 octets. Vous pourrez peut-être aussi utiliser from unicodedata import*pour sauvegarder des octets - pas sûr.
Stephen
4

Swift 3, 67 64 caractères

Soit r = {(s: String) dans s.applyingTransform (.toLatin, reverse: false)}

let r={(s:String)in s.applyingTransform(.toLatin,reverse:false)}
idrougge
la source
3
A construit, vraiment, Swift a un BUILTIN POUR CELA?
Zacharý
Je ne connais pas du tout Swift, mais pouvez-vous découper les espaces après s:String)et .toLatin,?
Yytsi
@TuukkaX, bien repéré!
Idrougge
@ Zacharý, bien Foundationa.
Idrougge
3

Python 3 , 259 octets

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)

Essayez-le en ligne!

Explication

Nous avons de la chance avec ce format d'entrée! Regardez ce qui se passe si je passe l'entrée via la normalisation 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']

Le dakuten est remplacé par un espace et un dakuten combinant. Maintenant, cet espace est tout ce qui sépare le de son dakuten. Donc nous nous en débarrassons et normalisons à nouveau :

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

Bingo La cinquième ligne transforme l’entrée en quelque chose comme

KONOSUBARASIISEKAINISISMALL YUKUHUKUWO

Ensuite, nous appliquons 9 substitutions ennuyeuses de regex entassées ret nous avons terminé:

KONOSUBARASHIISEKAINISHUKUFUKUWO

(Jonathan French a sauvegardé 4 octets, en écrivant import re,unicodedata as u place de import re;from unicodedata import*. Merci!)

Lynn
la source
Abuser de la normalisation pour le plaisir et le profit. C'est beau.
Tim Pederick
2
import re,unicodedata as ucomme dans Kirill L. répondre à un défi connexe économise 4 octets .
Jonathan Frech