diff --git a/2024/18-la-agenda-magica-de-santa/README.md b/2024/18-la-agenda-magica-de-santa/README.md new file mode 100644 index 0000000..4a6c27e --- /dev/null +++ b/2024/18-la-agenda-magica-de-santa/README.md @@ -0,0 +1,206 @@ +# Reto 18: La-agenda-magica-de-santa + +Santa Claus tiene una agenda mágica 📇 donde guarda las direcciones de los niños para entregar los regalos. El problema: **la información de la agenda está mezclada y malformateada**. Las líneas contienen un número de teléfono mágico, el nombre de un niño y su dirección, pero todo está rodeado de caracteres extraños. + +Santa necesita tu ayuda para encontrar información específica de la agenda. Escribe una función que, **dado el contenido de la agenda y un número de teléfono, devuelva el nombre del niño y su dirección.** + +Ten en cuenta que en la agenda: + +- Los números de teléfono están formateados como +X-YYY-YYY-YYY (donde X es uno o dos dígitos, e Y es un dígito). +- El nombre de cada niño está siempre entre < y > + +La idea es que escribas una funcióna que, pasándole el teléfono completo o una parte, devuelva el nombre y dirección del niño. **Si no encuentra nada o hay más de un resultado**, debes devolver `null`. + +```js +const agenda = `+34-600-123-456 Calle Gran Via 12 +Plaza Mayor 45 Madrid 28013 +34-600-987-654 + +1-800-555-0199 Fifth Ave New York` + +findInAgenda(agenda, '34-600-123-456') +// { name: "Juan Perez", address: "Calle Gran Via 12" } + +findInAgenda(agenda, '600-987') +// { name: "Maria Gomez", address: "Plaza Mayor 45 Madrid 28013" } + +findInAgenda(agenda, '111') +// null +// Explicación: No hay resultados + +findInAgenda(agenda, '1') +// null +// Explicación: Demasiados resultados +``` + +## Mi solución explicada + +```js +function findInAgenda(agenda, phone) { + const kidsList = agenda.split('\n'); + const foundKids = kidsList.filter((kid) => kid.includes(phone)); + + const matchingCount = foundKids?.length; + + if (matchingCount === 1) { + const [firstKid] = foundKids; + const name = firstKid.split('<')[1].split('>')[0]; + const address = firstKid + .split(' ') + .slice(1, -1) + .join(' ') + .split('<')[0] + .trim(); + + return { name, address }; + } + + return null; +} +``` + +Para resolver este reto, primero dividí la agenda en una lista de niños por cada salto de línea. + +Luego, filtré la lista de niños para encontrar aquellos que contienen el número de teléfono que se busca y guardé el resultado en `foundKids`. + +Después, conté cuántos niños coinciden con el número de teléfono buscado y guardé el resultado en `matchingCount`. + +Em este caso si no hay resultados o hay más de uno, devuelvo `null` porque como dice el enunciado, si no hay resultados o hay más de un resultado, debes devolver `null`. + +Si hay un solo resultado, extraigo el nombre y la dirección del niño y los devuelvo en un objeto. + +Para obtener el nombre del niño, busco el texto que está entre los caracteres `<` y `>`. + +Para obtener la dirección del niño, elimino el número de teléfono y el nombre del niño de la cadena, y luego elimino los espacios en blanco al principio y al final de la cadena. + +Finalmente, devuelvo un objeto con el nombre y la dirección del niño. + +**Veamos con un ejemplo cómo funciona**: + +Supongamos que tenemos la siguiente agenda: + +```js +const agenda = `+34-600-123-456 Calle Gran Via 12 +Plaza Mayor 45 Madrid 28013 +34-600-987-654 + +1-800-555-0199 Fifth Ave New York` +``` + +y queremos buscar el número de teléfono `34-600-123-456`. + +Primero, dividimos la agenda en una lista de niños: + +```js +const kidsList = agenda.split('\n'); + +// kidsList = [ +// '+34-600-123-456 Calle Gran Via 12 ', +// 'Plaza Mayor 45 Madrid 28013 +34-600-987-654', +// ' +1-800-555-0199 Fifth Ave New York' +// ] +``` + +Despues filtramos la lista de niños para encontrar aquellos que contienen el número de teléfono que buscamos: + +Al utilizar el método `filter` con la condición `kid.includes('34-600-123-456')`, obtenemos un nuevo array con los niños que contienen el número de teléfono buscado. Ya que la cadena `'+34-600-123-456 Calle Gran Via 12 '` contiene el número de teléfono `34-600-123-456`. + +```js +const foundKids = kidsList.filter((kid) => kid.includes('34-600-123-456')); + +// foundKids = [ +// '+34-600-123-456 Calle Gran Via 12 ' +// ] +``` + +Luego, contamos cuántos niños coinciden con el número de teléfono buscado: + +```js +const matchingCount = foundKids?.length; +const matchingCount = 1; +``` + +Ahora validamos la condición que nos dice que si no hay resultados o hay más de uno, debemos devolver `null`. En este caso, como hay un solo resultado, extraemos el nombre y la dirección del niño y los devolvemos en un objeto: + +```js +const [firstKid] = foundKids; +const name = firstKid.split('<')[1].split('>')[0]; + +// const name = '+34-600-123-456 Calle Gran Via 12 '.split('<')[1].split('>')[0]; +// const name = ['+34-600-123-456 Calle Gran Via 12 ', 'Juan Perez>'][1].split('>')[0]; +// const name = ['Juan Perez>'].split('>')[0]; +// const name = ['Juan Perez', ''][0]; +const name = 'Juan Perez'; + +const address = firstKid + .split(' ') + .slice(1, -1) + .join(' ') + .split('<')[0] + .trim(); + +// const address = '+34-600-123-456 Calle Gran Via 12 '.split(' ').slice(1, -1).join(' ').split('<')[0].trim(); +// const address = ['+34-600-123-456', 'Calle', 'Gran', 'Via', '12', ''].slice(1, -1).join(' ').split('<')[0].trim(); +// const address = ['Calle', 'Gran', 'Via', '12', '', +// 'Plaza Mayor 45 Madrid 28013 +34-600-987-654', +// ' +1-800-555-0199 Fifth Ave New York' +// ] +``` + +Despues filtramos la lista de niños para encontrar aquellos que contienen el número de teléfono que buscamos: + +Al utilizar el método `filter` con la condición `kid.includes('1')`, obtenemos un nuevo array con los niños que contienen el número de teléfono buscado. Ya que las cadenas `' +1-800-555-0199 Fifth Ave New York'` y `' +1-800-555-0199 Fifth Ave New York'` contienen el número de teléfono `1`. + +```js +const foundKids = kidsList.filter((kid) => kid.includes('1')); + +// kidsFound: [ +// '+34-600-123-456 Calle Gran Via 12 ', +// 'Plaza Mayor 45 Madrid 28013 +34-600-987-654', +// ' +1-800-555-0199 Fifth Ave New York' +// ] +``` + +Luego, contamos cuántos niños coinciden con el número de teléfono buscado: + +```js +const matchingCount = foundKids?.length; +const matchingCount = 3; +``` + +Ahora validamos la condición que nos dice que si no hay resultados o hay más de uno, debemos devolver `null`. En este caso, como hay más de un resultado, devolvemos `null`. + +```js +if (matchingCount === 1) {...} +if (3 === 1) {...} +if (false) {...} // No se cumple la condición + +return null; +``` + +Finalmente, devolvemos `null` porque hay más de un resultado. + +```js +return null; +``` + +Y eso es todo. Esa es la solución al reto 🎉 diff --git a/2024/18-la-agenda-magica-de-santa/index.js b/2024/18-la-agenda-magica-de-santa/index.js new file mode 100644 index 0000000..5c56d07 --- /dev/null +++ b/2024/18-la-agenda-magica-de-santa/index.js @@ -0,0 +1,23 @@ +function findInAgenda(agenda, phone) { + const kidsList = agenda.split('\n'); + const foundKids = kidsList.filter((kid) => kid.includes(phone)); + + const matchingCount = foundKids?.length; + + if (matchingCount === 1) { + const [firstKid] = foundKids; + const name = firstKid.split('<')[1].split('>')[0]; + const address = firstKid + .split(' ') + .slice(1, -1) + .join(' ') + .split('<')[0] + .trim(); + + return { name, address }; + } + + return null; +} + +module.exports = findInAgenda; diff --git a/2024/18-la-agenda-magica-de-santa/index.test.js b/2024/18-la-agenda-magica-de-santa/index.test.js new file mode 100644 index 0000000..d059002 --- /dev/null +++ b/2024/18-la-agenda-magica-de-santa/index.test.js @@ -0,0 +1,42 @@ +const findInAgenda = require('./index'); + +describe('18 => La-agenda-magica-de-santa', () => { + const agenda = `+34-600-123-456 Calle Gran Via 12 +Plaza Mayor 45 Madrid 28013 +34-600-987-654 + +1-800-555-0199 Fifth Ave New York`; + + const testCases = [ + { + input: [agenda, '34-600-123-456'], + output: { name: 'Juan Perez', address: 'Calle Gran Via 12' }, + }, + { + input: [agenda, '600-987'], + output: { + name: 'Maria Gomez', + address: 'Mayor 45 Madrid 28013', + }, + }, + { + input: [agenda, '111'], + output: null, + }, + { + input: [agenda, '1'], + output: null, + }, + ]; + + it('should return an object', () => { + const result = findInAgenda(agenda, '34-600-123-456'); + expect(typeof result).toBe('object'); + }); + + it.each(testCases)( + 'should return the correct name and address', + (testCase) => { + const result = findInAgenda(...testCase.input); + expect(result).toEqual(testCase.output); + }, + ); +}); diff --git a/README.md b/README.md index 635b107..fba5093 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,7 @@ npm run test 'year'/'challenge'/index.test.js | 15 | [✏️ Dibujando tablas](https://adventjs.dev/es/challenges/2024/15) | 🟢 | [here](./2024/15-dibujando-tablas/index.js) | [here](./2024/15-dibujando-tablas/README.md#mi-solución-explicada) | ⭐⭐⭐⭐⭐ | | 16 | [❄️ Limpiando la nieve del camino](https://adventjs.dev/es/challenges/2024/16) | 🟢 | [here](./2024/16-limpiando-la-nieve-del-camino/index.js) | [here](./2024/16-limpiando-la-nieve-del-camino/README.md#mi-solución-explicada) | ⭐⭐⭐⭐⭐ | | 17 | [💣 Busca las bombas del Grinch](https://adventjs.dev/es/challenges/2024/17) | 🟡 | [here](./2024/17-busca-las-bombas-del-grinch/index.js) | [here](./2024/17-busca-las-bombas-del-grinch/README.md#mi-solución-explicada) | ⭐⭐⭐⭐⭐ | +| 18 | [💾 La agenda mágica de santa](https://adventjs.dev/es/challenges/2024/18) | 🔴 | [here](./2024/18-la-agenda-magica-de-santa/index.js) | [here](./2024/18-la-agenda-magica-de-santa/README.md#mi-solución-explicada) | ⭐⭐⭐⭐⭐ | | 19 | [📦 Apila cajas mágicas para repartir regalos](https://adventjs.dev/es/challenges/2024/19) | 🔴 | [here](./2024/19-apila-cajas-magicas-para-repartir-regalos/index.js) | [here](./2024/19-apila-cajas-magicas-para-repartir-regalos/README.md#mi-solución-explicada) | ⭐⭐⭐⭐⭐ | | 20 | [🎁 Encuentra los regalos faltantes y duplicados](https://adventjs.dev/es/challenges/2024/20) | 🟢 | [here](./2024/20-encuentra-los-regalos-faltantes-y-duplicados/index.js) | [here](./2024/20-encuentra-los-regalos-faltantes-y-duplicados/README.md#mi-solución-explicada) | ⭐⭐⭐⭐⭐ | | 21 | [🎄 Calcula la altura del árbol de Navidad](https://adventjs.dev/es/challenges/2024/21) | 🟢 | [here](./2024/21-calcula-la-altura-del-arbol-de-navidad/index.js) | [here](./2024/21-calcula-la-altura-del-arbol-de-navidad/README.md#mi-solución-explicada) | ⭐⭐⭐⭐⭐ |