Expresiones regulares de adolescentes (JS version)

Webcu • November 19, 2019

exercism regex js

En Exercism podemos encontrar muchos ejercicios interesantes. Uno que resulta muy atractivo para practicar nuestras habilidades con expresiones regulares, es el de modelar un conjunto de respuestas de un adolescente en función de las acciones de los adultos. El conjunto de respuestas es el siguiente:

Acción Respuesta
Le preguntan algo Seguro
Le gritan Relájate
Le preguntan algo gritando Calmate, yo sé lo que estoy haciendo
Si lo miran sin decirle nada Muy bien, sigue así
Cualquier otra acción Lo que digas

La primera tarea fue encontrar las expresiones regulares que me ayudaran a modelar las distintas acciones.

Veamos una por una, como podemos modelar las diferentes acciones: - Preguntar algo:

Para saber que estamos preguntando en el idioma inglés la oración debe terminar con el signo de interrogación (?). Esta es la expresión regular que nos permite modelar una pregunta en ingles: /\?+\s*$/.
* /.../ son los delimitadores de la expresión regular * La primera parte \?+ nos permite verificar que la oración contiene al menos un signo de interrogación.

\ Cuando la barra invertida se encuentra delante de un carácter especial lo trata como un carácter simple. Cuando se encuentra delante de un carácter simple lo trata como un carácter especial.
\? Para buscar por signos de interrogación.
+ Busca el carácter precedente 1 o más veces.
\s Coincide con un carácter de espacio, entre ellos incluidos espacio, tab, salto de página, salto de línea y retorno de carro.
* Busca el carácter precedente cero o más veces.
$ Busca el final de la entrada.
^ Busca la inicio de la entrada
\s Coincide con un carácter de espacio, entre ellos incluidos espacio, tab, salto de página, salto de línea y retorno de carro.
* Busca el carácter precedente cero o más veces.
$ Busca el final de la entrada.

Solución inicial

export const hey = (message) => {
  if (/^\s*$/.test(message)) {
    return 'Fine. Be that way!';
  }

  if (/[A-Z]/.test(message)) {
    if (/^[^a-z]*\?+\s*$/.test(message)) {
      return 'Calm down, I know what I\'m doing!';
    }

    if (/^[^a-z]*$/.test(message)) {
      return 'Whoa, chill out!';
    }
  }

  if (/(\?+)\s*$/.test(message)) {
    return 'Sure.';
  }

  return 'Whatever.';
};

Esta solución resuelve el problema, pero se puede mejorar, sobretodo desde el punto de legibilidad. Siempre es importante recordad que el código que escribimos no será solamente interpretado por la computadora, sino que será leído por otros programadores y por nosotros mismos en el futuro. Lo más probable es que si en seis meses miro otra vez este código, no entienda mucho del mismo, porque en general no trabajo muy a menudo con expresiones regulares.

Solución final

export const hey = (message) => {
  if (isYelling(message)) {
    return isAsking(message) ? 'Calm down, I know what I\'m doing!' : 'Whoa, chill out!';
  }

  if (isAsking(message)) {
    return 'Sure.';
  }

  return isNotSayingNothing(message) ? 'Fine. Be that way!' : 'Whatever.';
};

const isNotSayingNothing = message => /^\s*$/.test(message);
const isAsking = message => /\?+\s*$/.test(message);
const isYelling = message => containsUppercase(message) && !containsLowercase(message);
const containsUppercase = message => /[A-Z]/.test(message);
const containsLowercase = message => /[a-z]/.test(message);

Ahora es muy diferente. Incluso si no recordamos muy bien como funcionan las expresiones regulares, con solo leer el nombre de las funciones podemos tener una idea de lo que estamos intentando modelar.

La milla extra

Hasta ahora estamos modelando oraciones que contienen palabras del idioma inglés. ¿Pero qué sucede cuando tenemos que tener en cuenta caracteres no latinos? Bueno ese es un problema un poco complicado, sobretodo porque JavaScript no soporta totalmente el standard Unicode. Aquí les dejo este artículo: What every JavaScript developer should know about unicode, que pienso les resultará muy interesante.

Referencias