Adivinha como pronunciar palavras em alemão

37

Introdução

Ao contrário do inglês, o alemão é considerado como tendo um sistema de escrita fonêmica . Isso significa que a correspondência entre ortografia e pronúncia está próxima. Dada qualquer palavra com a qual você não esteja familiarizado, você ainda saberia pronunciá-la por causa do sistema de ortografia. Isso significa que um computador deve ser capaz de fazê-lo também, certo?

Desafio

Escreva um programa ou função que tenha como entrada uma string que representa uma palavra alemã e imprima ou retorne sua pronúncia no Alfabeto Fonético Internacional (IPA) .

É claro que não vou fazer você aprender alemão ou o IPA completo . Esta seção da Wikipedia fornece quase todas as regras de alemão para IPA que você precisa, e eu codifiquei uma implementação de referência C # não-destruída .

Também é fornecida nesse link uma lista de 400 palavras comuns em alemão e sua pronúncia do IPA (necessária para validação). Tomando um exemplo dessa lista, se a entrada for solltest, a saída correta é ˈzɔltəst.

A implementação de referência adiciona duas regras úteis não mencionadas na seção da Wikipedia: Pressupõe que o estresse das palavras esteja na primeira sílaba (provavelmente em alemão) e usa uma heurística melhor para determinar quando a letra "e" representa o som schwa / ə /. Também implementa processamento especial para prefixos, mas isso não melhorou os resultados tanto quanto eu pensava.

Detalhes

Para ser considerada uma entrada válida, seu programa deve atender aos seguintes requisitos:

  • Sua saída IPA deve corresponder exatamente a pelo menos 300 das 400 palavras na lista de palavras de referência (a implementação de referência fica 333 correta)
  • Seu programa deve adivinhar qualquer palavra plausivelmente alemã. Portanto, temos um requisito técnico, isso significa que, para qualquer entrada que corresponda ao regex [a-zA-ZäÄöÖüÜ][a-zäöüß]*e tenha pelo menos uma vogal (aeiouyäöü), você deve produzir uma saída que não seja somente em espaço em branco e não com erros.
  • O programa deve ser determinístico (sempre produza a mesma saída com a mesma entrada)
  • Caso contrário, as brechas padrão são proibidas (especialmente a que consiste em buscar recursos externos)

Coisas diversas que você pode fazer:

  • Tenha um espaço em branco à esquerda e à esquerda na sua saída, se necessário
  • Use qualquer codificação de caracteres pré-existente na saída (não consigo imaginar nada além de Unicode funcionando bem, mas, se puder, parabéns)
  • Suponha que a entrada esteja em alguma forma normalizada, como as formas de normalização Unicode NFD, NFC, etc. Por exemplo, ä é escrito como um único caractere ou um caractere base + um caractere combinado?
  • Use métodos padrão de entrada e saída

Pontuação e caracteres IPA

A pontuação está em bytes. Esteja avisado de que os caracteres alemães e IPA têm 2 bytes em UTF-8. Além disso, o caractere IPA U + 0327 COMBINANDO INFERNO ABAIXO (̯) é um caractere de combinação Unicode e é um caractere UTF-8 de 2 bytes por si só. Isso significa que algo como ɐ̯ contaria como 4 bytes em UTF-8. Para os curiosos, esse símbolo significa que a vogal não forma o núcleo da sílaba (o anterior forma).

Além disso, tenha cuidado com esses caracteres IPA que, em algumas fontes, se parecem com outros caracteres ASCII: ɡ, ɪ, ʏ, ː (marca uma vogal longa), ˈ (marca a sílaba que tem o estresse em uma palavra multissílaba).

Como a lista de palavras de referência foi criada

Esta seção é uma informação extra não necessária para o desafio.

A lista de palavras foi retirada desta lista de frequência de palavras do Wikcionário , removendo repetições por causa da diferença de maiúsculas e minúsculas e duas palavras que não tinham entradas em alemão no Wikcionário em inglês (oh, ei). O IPA foi analisando os Wikcionários inglês e alemão. Onde várias pronúncias eram oferecidas, eu escolhi a mais formal e padrão. Se isso não estava claro, escolhi aquele que mais se encaixava nas regras gerais.

Eu também tive que padronizar como a letra "r" é pronunciada. É fortemente dependente da região como esta carta se pronunciou, e o Wikcionário não foi de modo algum consistente em qual delas escolheu. Eu senti que tendia ao seguinte: "r" é pronunciado / ɐ̯ / quando seguido por uma vogal longa e uma vogal não segue, caso contrário, é ʁ. Então, mudei todos eles para seguir essa regra, exceto os prefixos ver e er que eram consistentemente consistentes / (f) ɛɐ̯ /. Da mesma forma, eu padronizei "eu" como / ɔʏ̯ /.

DPenner1
fonte
16
O Mathematica possui um built-in para isso ( #~WordData~"PhoneticForm"&), mas funciona apenas para palavras em inglês.
JungHwan Min
29
@JungHwanMin Eu li o seu comentário da seguinte forma: ataque cardíaco imediato, suspiro de alívio.
DPenner1
11
Como devo saber "gestern" é pronunciado "GHES-tern" em vez de "ge-SHTERN"? "bester" como "BEST-er" e não "be-SHTER"?
Leaky Nun
@LeakyNun Não existe um algoritmo 100% para isso, mas sua implementação precisa obter apenas 75%. Minha implementação de referência também errou essas palavras.
DPenner1
@LeakyNun Bem, seu programa também poderá lidar com dialetos alemães, por isso é mais poderoso.
P. Siehr 22/06

Respostas:

9

PHP, 3311 2988 2916 2845 2759 2671 2667 2509 2484 bytes, passando 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ɐ"
);

Uma observação: três prefixos e 33 palavras são codificados e um pouco do código é levemente otimizado para a lista de testes.

O código de teste está aqui , embora dependa desse arquivo .

Testar:

php test.php all

Alimentado pelas lágrimas de declarações ternárias.

EDIT 7 : Espremido ~ 170 bytes, escrevendo um pré-processador no programa. Como conseqüência, o programa atual (tudo depois __halt_compiler();) é meio difícil de ler. Se você deseja o programa não processado, alterne evalcom printna terceira instrução.

Élektra
fonte
Isto é, na verdade, 2667 bytes, não 2671 (assumindo UTF-8)
caird coinheringaahing