Advent JS 2021 - Dias 1 a 5

Este año se ha realizado por primera vez el AdventJS: “25 días de retos con JavaScript”, cortesía de @mimdudev, en el que desde el día 1 de Diciembre hasta el 25 del mismo mes se debe resolver un nuevo problema cada día, afrontando todo tipo de problemas desde estructuras de datos hasta recursión siempre desde un punto de vista de un desarrollador Javascript.

Una vez finalizado me gustaría hacer un repaso de los diferentes problemas y destacar los que creo que son los conceptos más importante de cada día, hoy para empezar los cinco primeros.

Todas las soluciones están disponibles aquí

Día 1: “Contando ovejas para dormir”

Dificultad: Facíl

El primer problema ponía a prueba nuestro control sobre como filtrar un array de entrada y devolver solamente aquellos elementos del mismo que cumplian ciertas condiciones.

Para ello teníamos que hacer uso del método filter, dentro del mismo yo aposté por aplicar regex para detectar ciertos caracteres en el texto de cada elemento del array.

function contarOvejas(ovejas) {
  return ovejas
    .filter(({ color }) => color === 'rojo')
    .filter(({ name }) => name.match(/a/gi) && name.match(/n/gi));
}

Como apunte final comentar que mi web de referencia cuando necesito trabajar con expresiones regulares es RegExr, ella podremos probar de una forma mas rapida la expresion que necesitamos. Algunos ejemplos basicos que siempre viene bien tener a mano son:

[abc]	 => any of 'a', 'b', or 'c'.
[^abc] => not 'a', 'b', or 'c'.
[a-z]	 => character between 'a' and 'z'.
[0-9]	 => number between 0 and 9.

Día 2: “¡Ayuda al elfo a listar los regalos!"

Dificultad: Facíl

La principal dificultad del día era ser capaces de parsear un string de entrada basándose en una serie de normas y devolver un mapa clave valor con el número de ocurrencias de cada palabra del string.

Para parsear el string lo mejor era hacer un split por los espacios en blanco, a continuación filtrar los elementos no válidos y finalmente con un reduce generar el mapa de salida.

El método reduce será uno de los métodos más utilizados por mi durante todo el Advent ya que permite generar de forma muy limpia y sin variables intermedias el objeto de salida deseado.

function listGifts(letter) {
  return letter
    .split(' ')
    .filter((item) => (item !== '') & !item.startsWith('_'))
    .reduce((acc, item) => {
      acc[item] = (acc[item] ?? 0) + 1;
      return acc;
    }, {});
}

Día 3: “El Grinch quiere fastidiar la Navidad”

Dificultad: Normal

El problema de hoy era el momento perfecto para pelearse un poco con las regex. Cuando se trata de validar si ciertos caracteres existen dentro de un string tener cierta experiencia con el uso de expresiones regulares es fundamental, en este caso además fueron muy útiles para hacer replace.

function isValid(letter) {
  // contains { } [ or ].
  if (letter.match(/[\{|\}|\[|\]]/g)) return false;
  // contains ().
  if (letter.match(/\(\)/g)) return false;
  // has even number of ( or ).
  if (letter.replace(/[^\(|^\)]/g, '').length % 2 !== 0) return false;

  return true;
}

En el ultimo if se puede ver como aunque habitualmente metodos como split o replace se suelen utilizar con los caracteres habituales '-', ' ', '.', ':', '\n' es posible aplicar expresiones regulares algo mas complejas.

Día 4: “¡Es hora de poner la navidad en casa!"

Dificultad: Normal

El problema de hoy nos pedía crear un árbol de navidad dentro de string multilinea (representado como un array de strings), para ello era necesario hacer uso del comando repeat aplicado a un string y jugando un poco con las matemáticas para saber el número de repeticiones por nivel dentro del árbol.

function createXmasTree(height) {
  return `${createTree(height)}${createBottom(height)}`;
}

function createTree(height) {
  let tree = '';
  for (let index = 1; index <= height; index++) {
    tree +=
      '_'.repeat(height - index) +
      '*'.repeat(2 * index - 1) +
      '_'.repeat(height - index) +
      '\n';
  }
  return tree;
}

function createBottom(height) {
  const bottom =
    '_'.repeat((2 * height) / 2 - 1) + '#' + '_'.repeat((2 * height) / 2 - 1);
  return `${bottom}\n${bottom}`;
}

Día 5: “Contando los días para los regalos”

Dificultad: Facíl

¿Qué tal te llevas con Date? Pues el problema de hoy es la prueba de fuego perfecta para demostrarlo!

Para la resolución del problema de hoy hace falta un poco de matemáticas y saber manejar fechas en Javascript. Respecto al método Date debemos crear una nueva instancia con un formato Month Day, Year hours:minutes:seconds y restarselo a la fecha que recibimos como parámetro.

Ya solo quedaría hacer el cálculo de milisegundos a horas.

function daysToXmas(date) {
  const xMas = new Date('Dec 25, 2021 00:00:00');
  return Math.ceil((xMas - date) / (1000 * 60 * 60 * 24));
}

…Continua aquí