Eres un romanizador, bebé

38

La romanización del japonés está convirtiendo el texto japonés en caracteres latinos. En este desafío, se le dará una cadena de caracteres japoneses como entrada y se espera que los convierta a la cadena ASCII correcta.

Lo que necesita saber

El idioma japonés tiene tres sistemas de escritura: hiragana (el curvilíneo usado para palabras cortas), katakana (el ángulo-y usado para sonidos y palabras tomadas de otros idiomas) y kanji (los caracteres densos originalmente del chino). En este desafío solo nos preocuparemos por hiragana.

Hay 46 caracteres en el silabario hiragana. Cada personaje representa una sílaba. Los caracteres están organizados por primer sonido (consonante) y segundo sonido (vocal). Las columnas en orden son aiueo.

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

(si copia y pega esta tabla, tenga en cuenta que he usado espacios ideográficos U + 3000 para espaciar y y w)

Entonces, por ejemplo, あ と め debería producir una salida de atome. El primer personaje es a, el segundo es toy el tercero es me.

Excepciones

Como cualquier buen idioma, el japonés tiene excepciones a sus reglas, y la tabla hiragana tiene varias. Estos caracteres se pronuncian de forma ligeramente diferente de lo que su ubicación en la tabla implicaría:

し: shino si
ち: chino ti
つ: tsuno tu
ふ: funohu

Dakuten ゛

La palabra 'dakuten' significa 'marca fangosa': el dakuten convierte los sonidos en sus equivalentes sonoros (generalmente); por ejemplo, か se kaconvierte en か ゛ga. Una lista completa de los cambios:

kg
sz
td
hb

Las excepciones también cambian: し ゛: ji(o zhi), no zi
ち ゛: ji, no di
つ ゛: dzu, no du
(ふ ゛ actúa como cabría esperar; no es una excepción)

El handakuten es un carácter adicional゜ que se aplica a la hfila. Si se coloca después de un personaje, cambia el sonido del personaje en plugar de hacerlo b.

Tanto el dakuten como el handakuten se darán como personajes individuales. No necesitará lidiar con las formas precompuestas o los caracteres combinados.

Pequeños personajes

Finalmente, hay versiones pequeñas de algunos de los personajes. Modifican los caracteres que vienen antes o después de ellos.

ゃ ゅ ょ

Estas son las pequeñas formas de ya, yuy yo. Solo se colocan después de los sonidos en la icolumna; quitan el iy agregan su sonido. Entonces, き や se convierte en kiya; き ゃ se convierte en kya.

Si se coloca después de chio shi(o sus formas dakuten-ED), el yse elimina también. し ゆ es shiyu; ゅ ゅ es shu.

Lo último con lo que tendrá que lidiar es con lo pequeño tsu. っ duplica la consonante que le sigue, pase lo que pase; No hace nada más. Por ejemplo, き た es kita; き っ た es kitta.

Resumen, entrada y salida

Su programa debe ser capaz de transcribir: los 46 hiragana básicos, sus formas dakuten y handakuten, y sus combinaciones con caracteres pequeños.

El comportamiento indefinido incluye: pequeño ya, yuy yono después de un carácter con i, pequeño tsual final de una cadena, dakuten en un carácter no afectado, handakuten en un no pcarácter y cualquier otra cosa no mencionada en la especificación / introducción anterior.

Puede suponer que todas las entradas son válidas y contienen solo los caracteres japoneses mencionados anteriormente.

El caso no importa en la salida; También puede reemplazar rcon lo solo ncon m. La salida puede tener un espacio entre cada sílaba o ningún espacio en absoluto.

Esto es : el código más corto en bytes gana.

Casos de prueba

Muchos casos de prueba para cada parte individual se dan en la especificación. Algunos casos adicionales:

ひ ら か ゛ な → hiragana

か た か な → katakana

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

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

か ゛ ん ほ ゛ っ て → ganbatte

Notas

  • No sé mucho japonés además de lo que he escrito aquí. Avísame si he cometido algún error.

  • Originalmente planeaba incluir katakana también (por lo que mi caso de prueba de transliteración en inglés podría ser un poco más preciso), pero eso sería demasiado para un desafío de golf de código.

  • Los nombres Unicode incluyen la transcripción de cada carácter individualmente, pero sin las excepciones. Esto puede o no ser útil para usted.

  • ¡Gracias a squeamishossifrage por corregir dos errores tipográficos!

  • Lo siento si esto es demasiado largo; Intenté adaptar la mayoría de las peculiaridades de hiragana al desafío, pero algunas cosas (como hiragana de solo vocal pequeña, cambiar de n a m frente a algunas consonantes y la marca de repetición) tuvieron que cortarse para mantener el desafío manejable.

  • No siento nada por el título. Es una obra de arte.

Deusovi
fuente
1
¿Para qué debería ser la salida きっった?
lirtosiast
@Thomas: Esa es una entrada no válida. La salida puede ser lo que quieras.
Deusovi
1
debe っしser sshio shshi?
lirtosiast
2
I'm not at all sorry for the title. It's a masterpiece.Votación negativa
Fatalize
3
@Fatalize No es necesario que traigas tu parcialidad anti-Britney aquí. Aunque personalmente puedo ser más fanático de J-Lo, no voy a rechazar un excelente acertijo sobre eso.
semi-extrínseco

Respuestas:

7

Python 2, 638 bytes

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)

Toma la entrada como cadena unicode.

Pruébalo en Ideone

TFeld
fuente
1
Puede guardar un adiós miserable cambiando print ''.join(R)aprint''.join(R)
Zacharý
6

Python 2, 447 bytes

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

Esto toma la entrada de Unicode directamente, lo que me hizo perder algunos bytes debido al, decode('utf-8')pero creo que está más en el espíritu del desafío.

Comencé reemplazando cada personaje por los dos últimos caracteres de su nombre Unicode, como se sugiere en las notas del rompecabezas. Desafortunadamente, esto no distingue entre versiones alternativas del mismo personaje, así que tuve que hacer un truco feo para agregar una 'x' antes de los personajes pequeños y el handakuten.

El resto de los bucles for solo están arreglando excepciones, en orden:

  1. el primer bucle for convierte dakutens y handakutens en las consonantes correctas;
  2. el segundo para el bucle trata con las excepciones hiragana de shi, chi, tsu y fu;
  3. tercero para ofertas de bucle con las excepciones antes de un pequeño carácter y (como sha, jo);
  4. cuarto para ofertas de bucle con duplicación de consonantes después de un pequeño tsu.
  5. La línea final se ocupa de pequeños y-.

Desearía haber combinado más pasos, pero en algunos casos los pasos deben realizarse para evitar conflictos.

Pruébalo en línea! (una versión de varias líneas con más ejemplos se puede encontrar aquí ).

ffao
fuente
1
Enlace TIO
boboquack
Bienvenido a PPCG. Muy buena primera solución :)
Shaggy
Convierta sus cuatro espacios al frente for b in'AEIOU'en una pestaña o un solo espacio para ahorrar 3 bytes. También puede usarlo from unicodedata import*para guardar algunos bytes, no estoy seguro.
Stephen
4

Swift 3, 67 64 caracteres

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

let r={(s:String)in s.applyingTransform(.toLatin,reverse:false)}
idrougge
fuente
3
Un constructor, realmente, Swift tiene un CONSEJO PARA ESTO?
Zacharý
No conozco a Swift en absoluto, pero ¿puedes cortar los espacios en blanco después s:String)y .toLatin,?
Yytsi
@ TuukkaX, bien visto!
idrougge
@ Zacharý, bien Foundationtiene.
idrougge
3

Python 3 , 259 bytes

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)

Pruébalo en línea!

Explicación

¡Estamos de suerte con este formato de entrada! Mira lo que sucede si paso la entrada a través de la normalización 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']

El dakuten se reemplaza por un espacio y una combinación de dakuten. Ahora ese espacio es todo lo que separa el は de su dakuten. Entonces nos deshacemos de él y normalizamos nuevamente :

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

Bingo. La quinta línea convierte la entrada en algo como

KONOSUBARASIISEKAINISISMALL YUKUHUKUWO

Luego aplicamos 9 sustituciones aburridas de expresiones regulares encerradas r, y listo:

KONOSUBARASHIISEKAINISHUKUFUKUWO

(Jonathan French guardó 4 bytes, escribiendo en import re,unicodedata as ulugar de import re;from unicodedata import*. ¡Gracias!)

Lynn
fuente
Abusando de la normalización por diversión y ganancias. Eso es hermoso.
Tim Pederick
2
import re,unicodedata as ucomo en Kirill L., la respuesta a un desafío relacionado ahorra 4 bytes .
Jonathan Frech