Adivina cómo pronunciar palabras alemanas


37

Introducción

A diferencia del inglés, se considera que el alemán tiene un sistema de escritura bastante fonémico . Eso significa que la correspondencia entre la ortografía y la pronunciación es cercana. Dada cualquier palabra con la que no estés familiarizado, aún sabrías cómo pronunciarla debido al sistema de ortografía. Esto significa que una computadora también debería poder hacerlo, ¿verdad?

Reto

Escriba un programa o función que tome como entrada una cadena que represente una palabra alemana, e imprima o devuelva su pronunciación en el alfabeto fonético internacional (IPA) .

Por supuesto, no voy a hacerte aprender alemán o el IPA completo . Esta sección de Wikipedia proporciona casi todas las reglas de alemán a IPA que necesita, y he codificado una implementación de referencia de C # sin golf .

También se proporciona en ese enlace una lista de 400 palabras comunes en alemán y su pronunciación IPA (necesaria para la validación). Tomando un ejemplo de esa lista, si la entrada es solltest, la salida correcta es ˈzɔltəst.

La implementación de referencia agrega dos reglas útiles que no se mencionan en la sección de Wikipedia: supone que el énfasis de la palabra está en la primera sílaba (muy probablemente en alemán), y utiliza una mejor heurística para determinar cuándo la letra "e" representa el sonido schwa / ə /. También implementa un procesamiento especial para prefijos, pero eso no mejoró los resultados tanto como pensé que lo haría.

Detalles

Para ser considerado una entrada válida, su programa debe cumplir con los siguientes requisitos:

  • Su salida IPA debe ser una coincidencia exacta para al menos 300 de las 400 palabras en la lista de palabras de referencia (la implementación de referencia obtiene 333 correctas)
  • Su programa debe adivinar cualquier palabra plausiblemente alemana. Por lo tanto, tenemos un requisito técnico, esto significa que para cualquier entrada que coincida con la expresión regular [a-zA-ZäÄöÖüÜ][a-zäöüß]*y tenga al menos una vocal (aeiouyäöü), debe producir una salida que no sea solo espacios en blanco y no eliminar errores.
  • El programa debe ser determinista (siempre produce la misma salida dada la misma entrada)
  • De lo contrario, las lagunas estándar están prohibidas (especialmente la que se refiere a la obtención de recursos fuera del sitio)

Cosas varias que puedes hacer:

  • Tenga espacios en blanco iniciales y finales en su salida si es necesario
  • Use cualquier codificación de caracteres preexistente en la salida (no puedo imaginar que otra cosa que Unicode funcione bien, pero si puede, felicidades)
  • Suponga que la entrada está en alguna forma normalizada, como las formas de normalización Unicode NFD, NFC, etc. Por ejemplo, ¿se escribe ä como un solo carácter o un carácter base + un carácter de combinación?
  • Utilice métodos de entrada y salida estándar.

Puntuación y caracteres de IPA

La puntuación está en bytes. Tenga en cuenta que los caracteres alemanes y los caracteres IPA son de 2 bytes en UTF-8. Además, el carácter IPA U + 0327 COMBINANDO BREVE INVERTIDA ABAJO (̯) es un carácter de combinación Unicode y es un carácter UTF-8 de 2 bytes por sí solo. Eso significa que algo como ɐ̯ contaría como 4 bytes en UTF-8. Para los curiosos, este símbolo significa que la vocal no forma el núcleo de la sílaba (el anterior sí lo hace).

Además, tenga cuidado con estos caracteres IPA que en algunas fuentes se parecen a otros caracteres ASCII: ɡ, ɪ, ʏ, ː (marca una vocal larga), ˈ (marca qué sílaba tiene el énfasis en una palabra multisilábica).

Cómo se creó la lista de palabras de referencia

Esta sección es información adicional no necesaria para el desafío.

La lista de palabras se tomó de esta lista de frecuencia de palabras de Wiktionary , eliminando repeticiones debido a la diferencia de mayúsculas y dos palabras que no tenían entradas en alemán en el Wiktionary en inglés (oh y hey). La IPA fue de mirar los diccionarios de inglés y alemán. Cuando se ofrecieron múltiples pronunciaciones, elegí la más formal y estándar. Si esto no estaba claro, elegí el que más se ajustaba a las reglas generales.

También tuve que estandarizar cómo se pronuncia la letra "r". Depende en gran medida de la región cómo se pronunció esta letra, y Wiktionary no fue del todo consistente en cuál eligió. Sentí que tendía a lo siguiente: "r" se pronuncia / ɐ̯ / cuando es seguido por una vocal larga y una vocal no sigue, de lo contrario, es ʁ. Entonces, los cambié a todos para seguir esa regla, excepto los prefijos ver y er que eran bastante consistentes / (f) ɛɐ̯ /. Del mismo modo, estandaricé "eu" como / ɔʏ̯ /.


16
Mathematica tiene una función incorporada para esto ( #~WordData~"PhoneticForm"&), pero solo funciona para palabras en inglés.
JungHwan Min

29
@JungHwanMin Leí tu comentario de la siguiente manera: Ataque cardíaco inmediato, suspiro de alivio.
DPenner1

1
¿Cómo debo saber que "gestern" se pronuncia "GHES-tern" en lugar de "ge-SHTERN"? "bester" como "BEST-er" no "be-SHTER"?
Leaky Nun

@LeakyNun No hay un algoritmo del 100% para esto, pero su implementación solo necesita obtener el 75%. Mi implementación de referencia también entiende mal esas palabras.
DPenner1

@LeakyNun Bueno, tu programa también podrá manejar dialectos alemanes, por lo que es más poderoso.
P. Siehr

Respuestas:


9

PHP, 3311 2988 2916 2845 2759 2671 2667 2509 2484 bytes, pasando 301/400

<?$f=fopen(__FILE__,r);fseek($f,__COMPILER_HALT_OFFSET__);eval(strtr(stream_get_contents($f),[F=>'=>',M=>'==','&'=>'&&',H=>'function ',A_=>'array',G=>'if',4=>'for','|'=>'||','~'=>'))','%'=>str,7=>'=$',8=>'[]',9=>'!$','@'=>'count(','#'=>';$',5=>'return ',3=>':(']));__halt_compiler();define(J,[ieh,ah,aa,Ah,eh,ee,ie,ih,oh,oo,Oh,uh,Uh,au,eu,Au,ei,ai,ey,ay,a,e,i,o,u,A,O,U,y])#b7e=8;Hv($a){5in_A_($a,J);}Hn($a){5!v($a);}Hpronounce($w){global$b,$e#w=%tr(%tolower(%tr($w,[ßF1,ÄF2,äF2,ÖF0,öF0,ÜF6,üF6]~,[1FS,2FA,0FO,6FU])#W=8#L7w;while($L)4each(A__merge([tzsch,dsch,tsch,zsch,sch,chs,ch,ck,dt,ng,nk,pf,ph,qu,ss,th,tz,b,c,d,f,g,h,j,k,l,m,n,p,r,s,S,t,v,w,x,z],J)as$c){$l=%len($c);G(sub%($L,0,$l)M$c){$W87c#L=sub%($L,$l);break;}}$s=8#l=@$W);4($o7t7i=0#i<$l#i++){$c7W[$i]#p7i?$W[$i-1]:0#n7iM$l-1?0:$W[$i+1];G(9n|!(n($c)&$cM$n&n($W[$i+2]~)$s[$o]87c;G($p&((9n&v($c)&n($p~|(n($n)&v($W[$i+2]~~$s[++$o]=8;}$s[@$s)-1]|A__pop($s);4each($s as$z){$b87t#t+=@$z)#e87t;}$o=[sieFziQ,duFduQ,'die'FdiQ,derFdeQT,zuFtsuQ,wirFviQT,mirFmiQT,denFdeQn,dassFdas,erFeQT,soFzoQ,warFvaQT,fürFfyQT,jaFjaQ,wieFviQ,dirFdiQT,nurFnuQT,demFdeQm,ihnFiQn,auchFaUBx,ihrFiQT,daFdaQ,schonFʃoQn,wennFvEn,malFmaQl,gutFguQt,nachFnaQx,willFvIl,mussFmUs,habFhaQp,vorFfoQT,ihmFmiQm,tunFtuQn][$w]?:'';G($o)goto x#P7B7S7V7Z=0;@$s)>1&$o=[verFfET,daFda,geFgC][join($s[0])]#o&$P=1&A__shGt($s);(($P|@$s)M2)&$o.=W)|(@$s)>2&$d=1&$h=(int)@$s)/2)#w=A__merge(...$s);4each($w as$l){G(0<$S--)continue#n7w[$B+1]#p7w[$B-1]#f=''#Z+=in_A_($B,$b)#f7lMd&9n?t3$lMb&(9n|$nMt)?p3$lMg&(9n|$nMt)?((9n&$pMi)?K:k)3$lMc?(($nMA|$nMe|$nMi)?ts:k)3$lMch?(($pMa|$pMo|$pMu)?x:K)3$lMchs|$lMx?ks3$lMck?k3$lMdsch?dZ3$lMdt|$lMth?t3$lMph|$lMv?f39f&$lMg?g3$lMh?(v($n)?h:'')3$lMng?N3$lMnk?Nk3$lMqu?kv3$lMr?((!v($n)&9nMt)?T:R)3$lMsch?S3$lMss|$lMS?s3$lMtsch|$lMtzsch|$lMzsch?tS3$lMtz|$lMz?ts3$lMw?v3$lMs?(9p&($nMp|$nMt~?S3v($n)?z:s):$f~~~~~~~~~~)#U=0;G(v($l~{G(%len($l)>1)($f=[auFaUB,euFcYB,eiFaIB][$l])|$U=1;else{G(n($n)&((9w[$B+2]&$n!=n)|v($w[$B+2]~)$U=1;G($lMe){$U=9n?:$U;G(9w[$B+2]){G($nMr)($f=A)&$U=9S=1;G($nMm|$nMl)$f=C;}}elseG($nMch)$U=0;G(in_A_($B,$e~$U=0;}$f=($U|9Z)&9f?($l[0]MO?D3$l[0]MU?y3$l[0]MA?E:$l[0]~).Q39f?($lMe?((9n|(9w[$B+2]&($nMn|$nMs~)?C:E)3$lMA?E3$lMi?I3$lMo?c3$lMu?U3($lMU|$lMy)?Y:$l~~~:$f)#V++;}$f7f?:$l;G($d&$ZM$h)$f.=W#o.7f#B++;}G(%pos($o,W)M=false&$V>1)$o=W.$o;4(#j++<%len($o);)G($o[$j]M$o[$j+1])$o=sub%($o,0,$j).sub%($o,$j+1);x:5%tr($o,[SFʃ,ZFʒ,KFç,gFɡ,NFŋ,QF'ː',WFˈ,TFɐ̯,BF'̯',RFʁ,AFɐ,EFɛ,OFœ,IFɪ,YFʏ,UFʊ,cFɔ,CFə,DFø]);}

Define pronounce(string $word).

Uso:

assert(
    pronounce('darüber') == "daˈʁyːbɐ"
);

Una nota: 3 prefijos y 33 palabras están codificadas, y parte del código está ligeramente optimizado para la lista de pruebas.

El código de prueba está aquí , aunque depende de este archivo .

Probar:

php test.php all

Alimentado por las lágrimas de las declaraciones ternarias.

EDITAR 7 : Exprimido ~ 170 bytes escribiendo un preprocesador en el programa. Como consecuencia, el programa real (todo después __halt_compiler();) es un poco difícil de leer. Si desea que el programa no procesada, cambiar evalcon printel tercer comunicado.


Esto es en realidad 2667 bytes, no 2671 (suponiendo UTF-8)
caird coinheringaahing
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.