Skip to content

Commit 9de4759

Browse files
authored
Merge pull request #39 from marcode24/2024-19
✨ Add challenge-19 solution
2 parents b2a1217 + e27a583 commit 9de4759

File tree

4 files changed

+350
-0
lines changed

4 files changed

+350
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
# Reto 19: Apila-cajas-magicas-para-repartir-regalos
2+
3+
¡Se acerca el día para repartir regalos! Necesitamos apilar los regalos que transportaremos en el trineo 🛷 y para eso **los vamos a meter en cajas 📦.**
4+
5+
**Los regalos se pueden meter en 4 cajas distintas**, donde cada caja soporta 1, 2, 5, 10 de peso y se representan así:
6+
7+
```txt
8+
_
9+
1: |_|
10+
_____
11+
2: |_____|
12+
_____
13+
5: | |
14+
|_____|
15+
_________
16+
10: | |
17+
|_________|
18+
19+
// Representación en JavaScript:
20+
const boxRepresentations = {
21+
1: [" _ ", "|_|"] ,
22+
2: [" ___ ", "|___|"],
23+
5: [" _____ ", "| |", "|_____|"],
24+
10: [" _________ ", "| |", "|_________|"]
25+
}
26+
```
27+
28+
Tu misión es que al recibir el peso de los regalos, **uses las mínimas cajas posibles** y que, además, las apiles de menos peso (arriba) a más peso (abajo). **Siempre alineadas a la izquierda.**
29+
30+
Además, ten en cuenta que **al apilarlas, se reusa el borde inferior de la caja.**
31+
32+
```js
33+
distributeWeight(1)
34+
// Devuelve:
35+
// _
36+
// |_|
37+
38+
distributeWeight(2)
39+
// Devuelve:
40+
// ___
41+
// |___|
42+
43+
distributeWeight(3)
44+
// Devuelve:
45+
// _
46+
// |_|_
47+
// |___|
48+
49+
distributeWeight(4)
50+
// Devuelve:
51+
// ___
52+
// |___|
53+
// |___|
54+
55+
distributeWeight(5)
56+
// Devuelve:
57+
// _____
58+
// | |
59+
// |_____|
60+
61+
distributeWeight(6)
62+
// Devuelve:
63+
// _
64+
// |_|___
65+
// | |
66+
// |_____|
67+
```
68+
69+
**Nota: ¡Ten cuidado con los espacios en blanco! No añadas espacios en blanco a la derecha de una caja si no son necesarios.**
70+
71+
## Mi solución explicada
72+
73+
```js
74+
function distributeWeight(weight) {
75+
const boxLayouts = {
76+
1: [' _ ', '|_|'],
77+
2: [' ___ ', '|___|'],
78+
5: [' _____ ', '| |', '|_____|'],
79+
10: [' _________ ', '| |', '|_________|'],
80+
};
81+
82+
const stackedBoxes = [];
83+
const numbers = Object.keys(boxLayouts).map(Number).reverse();
84+
85+
function findTheBiggestBox(boxWeight) {
86+
return numbers.find((number) => number <= boxWeight);
87+
}
88+
89+
while (weight > 0) {
90+
const boxWeight = findTheBiggestBox(weight);
91+
const [bottom, ...rest] = boxLayouts[boxWeight].slice().reverse();
92+
const last = stackedBoxes.shift();
93+
const newBottom = `${bottom}${last?.slice(bottom.length, -1) ?? ''}`;
94+
stackedBoxes.unshift(...[newBottom, ...rest].reverse());
95+
96+
weight -= boxWeight;
97+
}
98+
99+
return stackedBoxes.join('\n');
100+
}
101+
```
102+
103+
Para poder resolver este reto, primero definí un objeto llamado `boxLayouts` que contiene los diseños de las cajas con su respectivo peso. Luego, inicialicé un array llamado `stackedBoxes` que almacenará las cajas apiladas. También, creé un array llamado `numbers` que contiene los pesos de las cajas en orden descendente para poder encontrar la caja más grande que pueda soportar el peso de los regalos.
104+
105+
Para encontrar la caja más grande que pueda soportar el peso de los regalos, definí una función llamada `findTheBiggestBox` que recibe el peso de los regalos y devuelve el peso de la caja más grande que pueda soportar ese peso. Para ello, utilicé el método `find` para encontrar el primer número en el array `numbers` que sea menor o igual al peso de los regalos.
106+
107+
Una vez que tengo la función `findTheBiggestBox`, utilicé un bucle `while` para apilar las cajas. En cada iteración, busco la caja más grande que pueda soportar el peso de los regalos y obtengo su diseño. Luego, obtengo la parte inferior de la caja anterior y la parte superior de la caja actual. Después, concateno ambas partes para formar la nueva parte inferior de la caja actual. Finalmente, actualizo el peso de los regalos restando el peso de la caja actual. Mientras el peso de los regalos sea mayor que 0, el bucle continuará.
108+
109+
Finalmente, devuelvo las cajas apiladas como una cadena de texto separada por saltos de línea. Para ello, utilicé el método `join` con el argumento `'\n'`. Así, las cajas apiladas se mostrarán una debajo de la otra.
110+
111+
**Veamos con un ejemplo cómo funciona la función:**
112+
113+
Supongamos que tenemos un `weight` igual a `3`.
114+
115+
```js
116+
distributeWeight(3)
117+
```
118+
119+
Primero, inicializamos el objeto `boxLayouts` y el array `stackedBoxes`.
120+
121+
```js
122+
const boxLayouts = {
123+
1: [' _ ', '|_|'],
124+
2: [' ___ ', '|___|'],
125+
5: [' _____ ', '| |', '|_____|'],
126+
10: [' _________ ', '| |', '|_________|'],
127+
};
128+
129+
const stackedBoxes = [];
130+
```
131+
132+
Ahora inicializamos el array `numbers` con los pesos de las cajas en orden descendente. Estos los sacaremos del objeto `boxLayouts`.
133+
134+
```js
135+
const numbers = Object.keys(boxLayouts).map(Number).reverse();
136+
137+
// Object.keys(boxLayouts) => ['1', '2', '5', '10']
138+
// ['1', '2', '5', '10'].map(Number) => [1, 2, 5, 10]
139+
// [1, 2, 5, 10].reverse() => [10, 5, 2, 1]
140+
141+
const numbers = [10, 5, 2, 1];
142+
```
143+
144+
Ahora viene lo interesante. Iniciamos un bucle `while` que se ejecutará mientras el peso de los regalos sea mayor que 0.
145+
146+
```js
147+
while (weight > 0) {
148+
```
149+
150+
Para esta primera iteración, el peso de los regalos es `3`. Llamamos a la función `findTheBiggestBox` con el peso de los regalos y obtenemos el peso de la caja más grande que pueda soportar ese peso.
151+
152+
```js
153+
while (3 > 0) // true
154+
```
155+
156+
```js
157+
// const boxWeight = findTheBiggestBox(3);
158+
const boxWeight = 2;
159+
160+
// const [bottom, ...rest] = boxLayouts[boxWeight].slice().reverse();
161+
// const [bottom, ...rest] = boxLayouts[2].slice().reverse();
162+
// const [bottom, ...rest] = [' ___ ', '|___|'].slice().reverse();
163+
// const [bottom, ...rest] = ['|___|', ' ___ '].reverse();
164+
// const [bottom, ...rest] = ['|___|', ' ___ '];
165+
const bottom = '|___|';
166+
const rest = [' ___ '];
167+
168+
// const last = stackedBoxes.shift();
169+
// shift() elimina el primer elemento del array y lo devuelve
170+
// const last = [].shift();
171+
const last = undefined;
172+
173+
// const newBottom = `${bottom}${last?.slice(bottom.length, -1) ?? ''}`;
174+
// const newBottom = `|___|${undefined?.slice(4, -1) ?? ''}`;
175+
// const newBottom = `|___|${undefined ??''}`;
176+
// const newBottom = `|___|${''}`;
177+
const newBottom = '|___|';
178+
179+
// stackedBoxes.unshift(...[newBottom, ...rest].reverse());
180+
// unshift() agrega uno o más elementos al inicio del array y devuelve la nueva longitud del array
181+
182+
// stackedBoxes.unshift(...['|___|', ' ___ '].reverse());
183+
// stackedBoxes.unshift(...[' ___ ', '|___|']);
184+
// stackedBoxes.unshift(' ___ ', '|___|');
185+
186+
// ahora stackedBoxes es [' ___ ', '|___|']
187+
188+
// weight -= boxWeight;
189+
// weight = weight - boxWeight;
190+
// weight = 3 - 2;
191+
weight = 1;
192+
```
193+
194+
Como el peso de los regalos es mayor que 0, continuamos con la siguiente iteración.
195+
196+
```js
197+
while (1 > 0) // true
198+
```
199+
200+
```js
201+
// const boxWeight = findTheBiggestBox(1);
202+
const boxWeight = 1;
203+
204+
// const [bottom, ...rest] = boxLayouts[boxWeight].slice().reverse();
205+
// const [bottom, ...rest] = boxLayouts[1].slice().reverse();
206+
// const [bottom, ...rest] = [' _ ', '|_|'].slice().reverse();
207+
// const [bottom, ...rest] = ['|_|', ' _ '].reverse();
208+
// const [bottom, ...rest] = ['|_|', ' _ '];
209+
const bottom = '|_|';
210+
const rest = [' _ '];
211+
212+
// const last = stackedBoxes.shift();
213+
// shift() elimina el primer elemento del array y lo devuelve
214+
// const last = [' ___ ', '|___|'].shift();
215+
const last = ' ___ ';
216+
217+
// ahora stackedBoxes es ['|___|']
218+
219+
// const newBottom = `${bottom}${last?.slice(bottom.length, -1) ?? ''}`;
220+
// const newBottom = `|_|${' ___ '.slice(3, -1) ?? ''}`;
221+
// const newBottom = `|_|${' ___ '.slice(3, -1) ?? ''}`;
222+
// const newBottom = `|_|${'_'}`;
223+
const newBottom = '|_|_';
224+
225+
// stackedBoxes.unshift(...[newBottom, ...rest].reverse());
226+
// stackedBoxes.unshift(...['|_|_', ' _ '].reverse());
227+
// stackedBoxes.unshift(...[' _ ', '|_|_']);
228+
// stackedBoxes.unshift(' _ ', '|_|_');
229+
230+
// ahora stackedBoxes es [' _ ', '|_|_', '|___|']
231+
232+
// weight -= boxWeight;
233+
// weight = weight - boxWeight;
234+
// weight = 1 - 1;
235+
weight = 0;
236+
```
237+
238+
Como el peso de los regalos es igual a 0, el bucle `while` termina. Ahora devolvemos las cajas apiladas como una cadena de texto separada por saltos de línea.
239+
240+
```js
241+
while (0 > 0) // false
242+
```
243+
244+
```js
245+
// return stackedBoxes.join('\n');
246+
// return [ ' _ ', '|_|_', '|___|' ].join('\n');
247+
// return ' _ \n|_|_\n|___|';
248+
return ' _ \n|_|_\n|___|';
249+
```
250+
251+
En este caso, el resultado es `' _ \n|_|_\n|___|'`.
252+
253+
Transformado en cajas, se vería así:
254+
255+
```txt
256+
_
257+
|_|_
258+
|___|
259+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
function distributeWeight(weight) {
2+
const boxLayouts = {
3+
1: [' _ ', '|_|'],
4+
2: [' ___ ', '|___|'],
5+
5: [' _____ ', '| |', '|_____|'],
6+
10: [' _________ ', '| |', '|_________|'],
7+
};
8+
9+
const stackedBoxes = [];
10+
const numbers = Object.keys(boxLayouts).map(Number).reverse();
11+
12+
function findTheBiggestBox(boxWeight) {
13+
return numbers.find((number) => number <= boxWeight);
14+
}
15+
16+
while (weight > 0) {
17+
const boxWeight = findTheBiggestBox(weight);
18+
const [bottom, ...rest] = boxLayouts[boxWeight].slice().reverse();
19+
const last = stackedBoxes.shift();
20+
const newBottom = `${bottom}${last?.slice(bottom.length, -1) ?? ''}`;
21+
stackedBoxes.unshift(...[newBottom, ...rest].reverse());
22+
23+
weight -= boxWeight;
24+
}
25+
26+
return stackedBoxes.join('\n');
27+
}
28+
29+
module.exports = distributeWeight;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/* eslint-disable operator-linebreak */
2+
const distributeWeight = require('./index');
3+
4+
describe('19 => Apila-cajas-magicas-para-repartir-regalos', () => {
5+
const TEST_CASES = [
6+
{
7+
input: 1,
8+
output: ' _ \n|_|',
9+
},
10+
{
11+
input: 2,
12+
output: ' ___ \n|___|',
13+
},
14+
{
15+
input: 3,
16+
output: ' _ \n|_|_\n|___|',
17+
},
18+
{
19+
input: 4,
20+
output: ' ___ \n|___|\n|___|',
21+
},
22+
{
23+
input: 5,
24+
output: ' _____ \n| |\n|_____|',
25+
},
26+
{
27+
input: 6,
28+
output: ' _ \n|_|___\n| |\n|_____|',
29+
},
30+
{
31+
input: 7,
32+
output: ' ___ \n|___|_\n| |\n|_____|',
33+
},
34+
{
35+
input: 18,
36+
output:
37+
' _ \n|_|_\n|___|_\n| |\n|_____|___\n| |\n|_________|',
38+
},
39+
{
40+
input: 121,
41+
output:
42+
' _ \n|_|_______\n| |\n|_________|\n| |\n|_________|\n| |\n|_________|' +
43+
'\n| |\n|_________|\n| |\n|_________|\n| |\n|_________|\n| |\n' +
44+
'|_________|\n| |\n|_________|\n| |\n|_________|\n| |\n|_________|\n' +
45+
'| |\n|_________|\n| |\n|_________|',
46+
},
47+
];
48+
49+
it('should return string type', () => {
50+
const testCase = TEST_CASES[0];
51+
const { input } = testCase;
52+
const result = distributeWeight(input);
53+
expect(typeof result).toBe('string');
54+
});
55+
56+
it.each(TEST_CASES)('should return expected output', (testCase) => {
57+
const { input, output } = testCase;
58+
const result = distributeWeight(input);
59+
expect(result).toBe(output);
60+
});
61+
});

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ npm run test 'year'/'challenge'/index.test.js
7676
| 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) | ⭐⭐⭐⭐⭐ |
7777
| 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) | ⭐⭐⭐⭐⭐ |
7878
| 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) | ⭐⭐⭐⭐⭐ |
79+
| 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) | ⭐⭐⭐⭐⭐ |
7980
| 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) | ⭐⭐⭐⭐⭐ |
8081
| 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) | ⭐⭐⭐⭐⭐ |
8182
| 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) | ⭐⭐⭐⭐⭐ |

0 commit comments

Comments
 (0)