Algoritmo para inventar palabras

Jugando con el lenguaje vamos a crear un algoritmo que invente palabras. Pero no el típico algoritmo que elige letras al azar. La idea es que genere palabras que parezcan españolas o al menos que se puedan leer sin problemas. Lo que se conocen como jitanjáforas . Para eso hay que seguir una reglas, empezaremos creando sílabas “válidas”. Una forma de hacer esto es usa ngram de letras. Ya vimos su uso para generar textos. El principio es el mismo pero usando letras en lugar de palabras. Como ya hemos visto ese método, en esta entrada usaremos una técnica diferente que permite mayor personalización (y así no me repito).

Inventando sílabas

Las sílabas que construyamos tienen que ser habituales en el español. Para facilitar nuestra tarea vamos a evitar generar sílabas que nos puedan dar problemas.

Seguiremos las siguientes reglas:

  • Omitiremos los caracteres raros en el español: k, x, w
  • Las vocales sueltas, solo las permitiremos cuando sea la primera silaba de la palabra: a, e, i, o, u
  • Las sílabas serán consonante + vocal
  • Hay consonantes que pueden ir acompañadas de una segunda consonante antes de la vocal:
b[r,l]
c[h,r,l]
f [r,l]
g[r]
p[r]
r[r]
t[r]
  • Tras la vocal pueden llevar las consonantes n,s. 
  • Un caso especial, la ‘q’ que prácticamente siempre va seguida de ‘u’ de hecho nosotros solo permitiremos dos formas: que, qui
  • Otro caso especial es la ‘g‘ cuando va seguida de la ‘u‘ dando lugar a ‘gu‘ que puede ir seguida de otra vocal. Solo contemplaremos la posibilidad de las formas: gua, gue, gui

Expresiones regulares

Vamos a usar un generador de textos aleatorios a partir de expresiones regulares. Para ello usa una expresión regular como plantilla para generar un texto. La librería que usaremos es esta, se puede probar directamente desde la web sin instalar nada.

Todas las regla de arriba se codifican en forma de una expresión regular como:

([aeiuo]|[])(((b[rl]?([aeiuo]|[ae]))|(c[rhl]?([aeiuo]|[ae]))|(d[r]?([aeiuo]|[ae]))|(f[r]?([aeiuo]|[ae]))|(p[r]?([aeiuo]|[ae]))|(r[r]?([aeiuo]|[ae]))|(t[r]?([aeiuo]|[ae]))|(s([aeiuo]|[ae]))|([vhjkñz]([aeiuo]|[ae]))|(l([aeiuo]|[ae]))|(m([aeiuo]|[ae]))|(n([aeiuo]|[ae]))|(qu[ei])|((gu[ae])|(g([aeiuo]|[ae]))))([nrs]|[]|[])){2,5}

Así toda de una vez y sin explicar se puede atragantar un poquito

([aeiuo]|[]) – empieza por vocal o no

((b[rl]?([aeiuo]|[ae]))|(c[rhl]?([aeiuo]|[ae]))|… – puede ser b o c (o d o e….)

((b[rl]?([aeiuo]|[ae])) – b puede ir seguido o no de r, seguido de una vocal

([nrs]|[]|[]) – la silaba va seguida de n,r,s o nada

{2,5} – de 2 a 5 silabas

Ajustar las probabilidades

La a y la e son mucho más probables que la i,o,u. Sin embargo la expresión regular aplica la misma probabilidad para todas las letras El truco está en como funciona el operador ‘|‘ y el ‘[]’.

Por ejemplo: [ae]|[aeiou]

Lo que hay a cada lado del | tiene un 50% de probabilidades. En el lado de la derecha la ‘a‘ aparece con un 50% de probabilidades y en el de la izquierda con un 20%. Dando para la ‘a‘ una probabilidad del (0.5*0.5)+(0.5*0.2)=0.35

Para todas las vocales las probabilidades son:

a (35%) , e (35%) , i (10%), o (10%), u (10%)

El mismo truco se usa en otras expresiones como: ([nrs]|[]|[])

Correcciones

Tras generar las palabras hay que aplicar algunas correcciones:

  • Si empieza por ‘rr’ se cambia a ‘r’
  • Si tiene ‘nb‘ o ‘np‘ se cambian por ‘mb‘ y ‘mp