Skip to content

Commit 668d09c

Browse files
authored
Merge pull request #34 from marcode24/2024-16
✨ Add challenge-16 solution
2 parents f24b553 + 0aae5e8 commit 668d09c

File tree

4 files changed

+304
-0
lines changed

4 files changed

+304
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
# Reto 16: Limpiando-la-nieve-del-camino
2+
3+
Los elfos están trabajando arduamente para limpiar los caminos llenos de nieve mágica ❄️. Esta nieve tiene una propiedad especial: si dos montículos de nieve **idénticos y adyacentes se encuentran, desaparecen automáticamente.**
4+
5+
Tu tarea es escribir una función que ayude a los elfos a simular este proceso. **El camino se representa por una cadena de texto y cada montículo de nieve un carácter.**
6+
7+
Tienes que eliminar todos los montículos de nieve adyacentes que sean iguales **hasta que no queden más movimientos posibles.**
8+
9+
El resultado debe ser el camino final después de haber eliminado todos los montículos duplicados:
10+
11+
```js
12+
removeSnow('zxxzoz') // -> "oz"
13+
// 1. Eliminamos "xx", quedando "zzoz"
14+
// 2. Eliminamos "zz", quedando "oz"
15+
16+
removeSnow('abcdd') // -> "abc"
17+
// 1. Eliminamos "dd", quedando "abc"
18+
19+
removeSnow('zzz') // -> "z"
20+
// 1. Eliminamos "zz", quedando "z"
21+
22+
removeSnow('a') // -> "a"
23+
// No hay montículos repetidos
24+
```
25+
26+
## Mi solución explicada
27+
28+
```js
29+
function removeSnow(s) {
30+
const stack = [];
31+
32+
for (const snow of s) {
33+
if (stack.at(-1) === snow) {
34+
stack.pop();
35+
} else {
36+
stack.push(snow);
37+
}
38+
}
39+
40+
return stack.join('');
41+
}
42+
```
43+
44+
Para resolver este problema, hay que comprender primero lo que se pide, tenemos que eliminar todos los montículos de nieve adyacentes que sean iguales hasta que no queden más movimientos posibles. Pero,
45+
46+
- **¿Qué es un montículo de nieve adyacente?** Son dos montículos de nieve que están uno al lado del otro. Por ejemplo, en la cadena `'zxxzoz'`, los montículos de nieve adyacentes son `'xx'` y `'zz'`. En cambio, `'z'` y `'o'` no son adyacentes.
47+
48+
- **¿Qué significa que dos montículos de nieve sean iguales?** Significa que los dos montículos de nieve tienen el mismo carácter. Por ejemplo, en la cadena `'zxxzoz'`, los montículos de nieve `'xx'` y `'zz'` son iguales porque ambos tienen el carácter `'z'`. En cambio, `'z'` y `'o'` que al sobrar no son iguales.
49+
50+
Para resolver el problema, he utilizado una pila (stack) como estructura de datos. Esta es una elección adecuada porque nos permite almacenar temporalmente los montículos de nieve y eliminar los adyacentes de forma eficiente.
51+
52+
1. Inicializamos una pila vacía.
53+
2. Recorremos cada carácter de la cadena:
54+
- Si el carácter actual es igual al último carácter almacenado en la pila (el tope de la pila), eliminamos ese último carácter porque representan montículos iguales y adyacentes.
55+
- Si no son iguales, agregamos el carácter actual a la pila.
56+
3. Una vez procesados todos los caracteres, la pila contendrá el camino final, con todos los montículos de nieve adyacentes y duplicados eliminados.
57+
4. Finalmente, convertimos la pila en una cadena y la devolvemos como resultado.
58+
59+
**Veamos como funciona:**
60+
61+
Supongamos que tenemos la cadena `'abbacddce'`. Para esto vamos a recorrer cada montículo de nieve de la cadena con un bucle `for...of`, utilizaremos `at(-1)` para obtener el último elemento de la pila, `pop()` para eliminar el último elemento de la pila, y `push()` para añadir un elemento a la pila. Como la cadena `'abbacddce'` tiene 9 montículos de nieve, se realizarán 9 iteraciones.
62+
63+
Para la primera iteración, el montículo de nieve actual es `'a'` y la pila está vacía. Como la pila está vacía, añadimos el montículo de nieve actual a la pila. La pila ahora contiene `['a']`.
64+
65+
```js
66+
snow: 'a'
67+
stack: []
68+
69+
// if(stack.at(-1) === snow)
70+
// if([].at(-1) === 'a')
71+
// if(undefined === 'a')
72+
if(false)
73+
74+
// como la condición es falsa, añadimos el montículo de nieve actual a la pila
75+
stack.push(snow)
76+
```
77+
78+
Para este momento, la pila contiene `['a']`.
79+
80+
Para la segunda iteración, el montículo de nieve actual es `'b'` y la pila contiene `['a']`. Como el montículo de nieve actual es diferente al último montículo de nieve almacenado en la pila, añadimos el montículo de nieve actual a la pila. La pila ahora contiene `['a', 'b']`.
81+
82+
```js
83+
snow: 'b'
84+
stack: ['a']
85+
86+
// if(stack.at(-1) === snow)
87+
// if(['a'].at(-1) === 'b')
88+
// if('a' === 'b')
89+
if(false)
90+
91+
// como la condición es falsa, añadimos el montículo de nieve actual a la pila
92+
stack.push(snow)
93+
```
94+
95+
Para este momento, la pila contiene `['a', 'b']`.
96+
97+
Para la tercera iteración, el montículo de nieve actual es `'b'` y la pila contiene `['a', 'b']`. Como el montículo de nieve actual es igual al último montículo de nieve almacenado en la pila, eliminamos el último montículo de nieve de la pila. La pila ahora contiene `['a']`.
98+
99+
```js
100+
snow: 'b'
101+
stack: ['a', 'b']
102+
103+
// if(stack.at(-1) === snow)
104+
// if(['a', 'b'].at(-1) === 'b')
105+
// if('b' === 'b')
106+
if(true)
107+
108+
// como la condición es verdadera, eliminamos el último montículo de nieve de la pila
109+
stack.pop()
110+
```
111+
112+
Para este momento, la pila contiene `['a']`.
113+
114+
Para la cuarta iteración, el montículo de nieve actual es `'a'` y la pila contiene `['a']`. Como el montículo de nieve actual es igual al último montículo de nieve almacenado en la pila, eliminamos el último montículo de nieve de la pila. La pila ahora contiene `[]`.
115+
116+
```js
117+
snow: 'a'
118+
stack: ['a']
119+
120+
// if(stack.at(-1) === snow)
121+
// if(['a'].at(-1) === 'a')
122+
// if('a' === 'a')
123+
if(true)
124+
125+
// como la condición es verdadera, eliminamos el último montículo de nieve de la pila
126+
stack.pop()
127+
```
128+
129+
Para este momento, la pila está vacía `[]`.
130+
131+
Para la quinta iteración, el montículo de nieve actual es `'c'` y la pila está vacía. Como la pila está vacía, añadimos el montículo de nieve actual a la pila. La pila ahora contiene `['c']`.
132+
133+
```js
134+
snow: 'c'
135+
stack: []
136+
137+
// if(stack.at(-1) === snow)
138+
// if([].at(-1) === 'c')
139+
// if(undefined === 'c')
140+
if(false)
141+
142+
// como la condición es falsa, añadimos el montículo de nieve actual a la pila
143+
stack.push(snow)
144+
```
145+
146+
Para este momento, la pila contiene `['c']`.
147+
148+
Para la sexta iteración, el montículo de nieve actual es `'d'` y la pila contiene `['c']`. Como el montículo de nieve actual es diferente al último montículo de nieve almacenado en la pila, añadimos el montículo de nieve actual a la pila. La pila ahora contiene `['c', 'd']`.
149+
150+
```js
151+
snow: 'd'
152+
stack: ['c']
153+
154+
// if(stack.at(-1) === snow)
155+
// if(['c'].at(-1) === 'd')
156+
// if('c' === 'd')
157+
if(false)
158+
159+
// como la condición es falsa, añadimos el montículo de nieve actual a la pila
160+
stack.push(snow)
161+
```
162+
163+
Para este momento, la pila contiene `['c', 'd']`.
164+
165+
Para la séptima iteración, el montículo de nieve actual es `'d'` y la pila contiene `['c', 'd']`. Como el montículo de nieve actual es igual al último montículo de nieve almacenado en la pila, eliminamos el último montículo de nieve de la pila. La pila ahora contiene `['c']`.
166+
167+
```js
168+
snow: 'd'
169+
stack: ['c', 'd']
170+
171+
// if(stack.at(-1) === snow)
172+
// if(['c', 'd'].at(-1) === 'd')
173+
// if('d' === 'd')
174+
if(true)
175+
176+
// como la condición es verdadera, eliminamos el último montículo de nieve de la pila
177+
stack.pop()
178+
```
179+
180+
Para este momento, la pila contiene `['c']`.
181+
182+
Para la octava iteración, el montículo de nieve actual es `'c'` y la pila contiene `['c']`. Como el montículo de nieve actual es igual al último montículo de nieve almacenado en la pila, eliminamos el último montículo de nieve de la pila. La pila ahora contiene `[]`.
183+
184+
```js
185+
snow: 'c'
186+
stack: ['c']
187+
188+
// if(stack.at(-1) === snow)
189+
// if(['c'].at(-1) === 'c')
190+
// if('c' === 'c')
191+
if(true)
192+
193+
// como la condición es verdadera, eliminamos el último montículo de nieve de la pila
194+
stack.pop()
195+
```
196+
197+
Para este momento, la pila está vacía `[]`.
198+
199+
Para la novena iteración, el montículo de nieve actual es `'e'` y la pila está vacía. Como la pila está vacía, añadimos el montículo de nieve actual a la pila. La pila ahora contiene `['e']`.
200+
201+
```js
202+
snow: 'e'
203+
stack: []
204+
205+
// if(stack.at(-1) === snow)
206+
// if([].at(-1) === 'e')
207+
// if(undefined === 'e')
208+
if(false)
209+
210+
// como la condición es falsa, añadimos el montículo de nieve actual a la pila
211+
stack.push(snow)
212+
```
213+
214+
Para este momento, la pila contiene `['e']`.
215+
216+
Como hemos recorrido todos los montículos de nieve de la cadena `'abbacddce'`, la pila contiene el resultado final `['e']`. Finalmente, devolvemos la pila como una cadena `'e'`.
217+
218+
```js
219+
// return stack.join('')
220+
// return ['e'].join('')
221+
return 'e'
222+
```
223+
224+
La cadena final después de haber eliminado todos los montículos duplicados es `'e'`.
225+
226+
Y así es como se resuelve este problema 🎉
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/* eslint-disable no-restricted-syntax */
2+
function removeSnow(s) {
3+
const stack = [];
4+
5+
for (const snow of s) {
6+
if (stack.at(-1) === snow) {
7+
stack.pop();
8+
} else {
9+
stack.push(snow);
10+
}
11+
}
12+
13+
return stack.join('');
14+
}
15+
16+
module.exports = removeSnow;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
const removeSnow = require('./index');
2+
3+
describe('16 => Limpiando-la-nieve-del-camino', () => {
4+
const TEST_CASES = [
5+
{
6+
input: 'abbaca',
7+
output: 'ca',
8+
},
9+
{
10+
input: 'azxxzy',
11+
output: 'ay',
12+
},
13+
{
14+
input: 'aabccba',
15+
output: 'a',
16+
},
17+
{
18+
input: 'aaabbaacc',
19+
output: 'a',
20+
},
21+
{
22+
input: 'xyzzy',
23+
output: 'x',
24+
},
25+
{
26+
input: 'abbacddce',
27+
output: 'e',
28+
},
29+
{
30+
input: '',
31+
output: '',
32+
},
33+
{
34+
input: 'a',
35+
output: 'a',
36+
},
37+
{
38+
input: 'aa',
39+
output: '',
40+
},
41+
{
42+
input: 'ab',
43+
output: 'ab',
44+
},
45+
{
46+
input: 'abc',
47+
output: 'abc',
48+
},
49+
];
50+
51+
it('should return string type', () => {
52+
const testCase = TEST_CASES[0];
53+
const result = removeSnow(testCase.input);
54+
expect(typeof result).toBe('string');
55+
});
56+
57+
it.each(TEST_CASES)('should return $output', ({ input, output }) => {
58+
const result = removeSnow(input);
59+
expect(result).toBe(output);
60+
});
61+
});

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ npm run test 'year'/'challenge'/index.test.js
7474
| 13 | [🤖 ¿El robot está de vuelta?](https://adventjs.dev/es/challenges/2024/13) | 🔴 | [here](./2024/13-el-robot-esta-de-vuelta/index.js) | [here](./2024/13-el-robot-esta-de-vuelta/README.md#mi-solución-explicada) | ⭐⭐⭐⭐⭐ |
7575
| 14 | [🦌 Acomodando los renos](https://adventjs.dev/es/challenges/2024/14) | 🟢 | [here](./2024/14-acomodando-los-renos/index.js) | [here](./2024/14-acomodando-los-renos/README.md#mi-solución-explicada) | ⭐⭐⭐⭐⭐ |
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) | ⭐⭐⭐⭐⭐ |
77+
| 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) | ⭐⭐⭐⭐⭐ |
7778

7879
Difficulties legend:
7980
🟢 Easy 🟡 Medium 🔴 Hard

0 commit comments

Comments
 (0)