Skip to content

✨ Add challenge-22 solution #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions 2024/22-genera-combinaciones-de-regalos/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Reto 22: Genera-combinaciones-de-regalos

Santa Claus 🎅 está revisando una **lista de juguetes únicos que podría incluir en su bolsa mágica de regalos.** Quiere explorar todas las combinaciones posibles de juguetes. Quiere ver todas las combinaciones que realmente contengan al menos un juguete.

Tu tarea es escribir una función que, dado un array de juguetes, **devuelva todas las combinaciones posibles.**

Importante: Debes devolverlo en el orden que aparecen los juguetes y de combinaciones de 1 a n juguetes.

```js
generateGiftSets(['car', 'doll', 'puzzle'])
// [
// ['car'],
// ['doll'],
// ['puzzle'],
// ['car', 'doll'],
// ['car', 'puzzle'],
// ['doll', 'puzzle'],
// ['car', 'doll', 'puzzle']
// ]

generateGiftSets(['ball'])
// [
// ['ball']
// ]

generateGiftSets(['game', 'pc'])
// [
// ['game'],
// ['pc'],
// ['game', 'pc']
// ]
```

**Nota: En el array de entrada siempre habrá al menos un juguete y nunca habrá juguetes duplicados.**

**Consejo**: Hay muchas formas de solucionar este problema, pero el backtracking puede ser una buena opción. 😉

## Mi solución explicada

```js
/* eslint-disable no-inner-declarations */
function generateGiftSets(gifts) {
const results = [];
function backtracking(start, currentSet) {
if (currentSet.length > 0) {
results.push([...currentSet]);
}

for (let i = start; i < gifts.length; i++) {
currentSet.push(gifts[i]);
backtracking(i + 1, currentSet);
currentSet.pop();
}
}

backtracking(0, []);

return results.sort((a, b) => a.length - b.length);
}
```

Para poder resolver este problema, utilizaremos un enfoque de backtracking. A grandes rasgos, el backtracking es una técnica que consiste en probar todas las posibles combinaciones de una solución, y si en algún momento nos damos cuenta de que no es posible llegar a una solución válida, retrocedemos y probamos otra combinación.

En este caso, la función `generateGiftSets` recibe un array de juguetes y devuelve todas las combinaciones posibles. Para ello, creamos un array `results` que almacenará todas las combinaciones válidas.

Dentro de la función `generateGiftSets`, definimos una función interna llamada `backtracking` que se encargará de generar las combinaciones. Esta función recibe dos parámetros: `start` (que indica la posición inicial desde la que se deben considerar los juguetes) y `currentSet` (que es el conjunto actual de juguetes que estamos evaluando).

En la función `backtracking`, primero verificamos si el conjunto actual `currentSet` tiene al menos un juguete, y si es así, lo agregamos al array `results`. Luego, recorremos los juguetes a partir de la posición `start` y vamos generando las combinaciones de forma recursiva. Para ello, agregamos un juguete al conjunto actual, llamamos a la función `backtracking` con la siguiente posición y el conjunto actual, y luego eliminamos el último juguete agregado para probar con el siguiente. De esta forma, vamos generando todas las combinaciones posibles.

Finalmente, retornamos el array `results` ordenado por la longitud de cada combinación, de menor a mayor.
19 changes: 19 additions & 0 deletions 2024/22-genera-combinaciones-de-regalos/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
function generateGiftSets(gifts) {
const results = [];
function backtracking(start, currentSet) {
if (currentSet.length > 0) {
results.push([...currentSet]);
}

for (let i = start; i < gifts.length; i++) {
currentSet.push(gifts[i]);
backtracking(i + 1, currentSet);
currentSet.pop();
}
}

backtracking(0, []);

return results.sort((a, b) => a.length - b.length);
}
module.exports = generateGiftSets;
99 changes: 99 additions & 0 deletions 2024/22-genera-combinaciones-de-regalos/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
const generateGiftSets = require('./index');

describe('22 => Genera-combinaciones-de-regalos', () => {
const TEST_CASES = [
{
input: ['car'],
output: [['car']],
},
{
input: ['car', 'doll', 'puzzle'],
output: [
['car'],
['doll'],
['puzzle'],
['car', 'doll'],
['car', 'puzzle'],
['doll', 'puzzle'],
['car', 'doll', 'puzzle'],
],
},
{
input: ['car', 'doll'],
output: [['car'], ['doll'], ['car', 'doll']],
},
{
input: ['apple', 'banana', 'cherry', 'date'],
output: [
['apple'],
['banana'],
['cherry'],
['date'],
['apple', 'banana'],
['apple', 'cherry'],
['apple', 'date'],
['banana', 'cherry'],
['banana', 'date'],
['cherry', 'date'],
['apple', 'banana', 'cherry'],
['apple', 'banana', 'date'],
['apple', 'cherry', 'date'],
['banana', 'cherry', 'date'],
['apple', 'banana', 'cherry', 'date'],
],
},
{
input: ['pen', 'notebook', 'eraser', 'pencil', 'marker'],
output: [
['pen'],
['notebook'],
['eraser'],
['pencil'],
['marker'],
['pen', 'notebook'],
['pen', 'eraser'],
['pen', 'pencil'],
['pen', 'marker'],
['notebook', 'eraser'],
['notebook', 'pencil'],
['notebook', 'marker'],
['eraser', 'pencil'],
['eraser', 'marker'],
['pencil', 'marker'],
['pen', 'notebook', 'eraser'],
['pen', 'notebook', 'pencil'],
['pen', 'notebook', 'marker'],
['pen', 'eraser', 'pencil'],
['pen', 'eraser', 'marker'],
['pen', 'pencil', 'marker'],
['notebook', 'eraser', 'pencil'],
['notebook', 'eraser', 'marker'],
['notebook', 'pencil', 'marker'],
['eraser', 'pencil', 'marker'],
['pen', 'notebook', 'eraser', 'pencil'],
['pen', 'notebook', 'eraser', 'marker'],
['pen', 'notebook', 'pencil', 'marker'],
['pen', 'eraser', 'pencil', 'marker'],
['notebook', 'eraser', 'pencil', 'marker'],
['pen', 'notebook', 'eraser', 'pencil', 'marker'],
],
},
{
input: [],
output: [],
},
];

it('should return array type', () => {
const result = generateGiftSets(['car']);
expect(Array.isArray(result)).toBe(true);
});

it.each(TEST_CASES)(
'should return an array with $output.length elements',
({ input, output }) => {
const result = generateGiftSets(input);
expect(result).toHaveLength(output.length);
},
);
});
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ npm run test 'year'/'challenge'/index.test.js
| 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) | ⭐⭐⭐⭐⭐ |
| 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) | ⭐⭐⭐⭐⭐ |
| 22 | [🎁 Genera combinaciones de regalos](https://adventjs.dev/es/challenges/2024/22) | 🟡 | [here](./2024/22-genera-combinaciones-de-regalos/index.js) | [here](./2024/22-genera-combinaciones-de-regalos/README.md#mi-solución-explicada) | ⭐⭐⭐⭐⭐ |

Difficulties legend:
🟢 Easy 🟡 Medium 🔴 Hard
Expand Down
Loading