Solución al reto #5 del AdventJS 2023
Solución del reto anterior
Solución del siguiente reto
Descripción del Reto
Santa 🎅 está probando su nuevo trineo eléctrico, el CyberReindeer, en una carretera del Polo Norte. La carretera se representa con una cadena de caracteres, donde:
.
= Carretera
S
= Trineo de Santa
*
= Barrera abierta
|
= Barrera cerrada
Ejemplo de carretera: S...|....|.....
Cada unidad de tiempo, el trineo avanza una posición a la derecha. Si encuentra una barrera cerrada, se detiene hasta que la barrera se abra. Si está abierta, la atraviesa directamente.
Todas las barreras empiezan cerradas, pero después de 5 unidades de tiempo, se abren todas para siempre.
Crea una función que simule el movimiento del trineo durante un tiempo dado y devuelva un array de cadenas representando el estado de la carretera en cada unidad de tiempo:
const road = 'S..|...|..'
const time = 10 // unidades de tiempo
const result = cyberReindeer(road, time)
/* -> result:
[
'S..|...|..', // estado inicial
'.S.|...|..', // avanza el trineo la carretera
'..S|...|..', // avanza el trineo la carretera
'..S|...|..', // el trineo para en la barrera
'..S|...|..', // el trineo para en la barrera
'...S...*..', // se abre la barrera, el trineo avanza
'...*S..*..', // avanza el trineo la carretera
'...*.S.*..', // avanza el trineo la carretera
'...*..S*..', // avanza el trineo la carretera
'...*...S..', // avanza por la barrera abierta
]
*/
El resultado es un array donde cada elemento muestra la carretera en cada unidad de tiempo.
Ten en cuenta que si el trineo está en la misma posición que una barrera, entonces toma su lugar en el array.
Análisis
Para resolver este reto debemos ir moviendo la letra S
dentro del string y detenerlo al encontrar una barrera (|
), la barrera se abrirá (*
) al pasar 5 unidades de tiempo. Debemos ir guardando en un arreglo el recorrido de la letra S
hasta que se acaben las unidades de tiempo.
Entradas
- Road(
road
): El string original por el cual el trineo hará su recorrido. - Time(
time
): Un número con las unidades de tiempo.
Salida
- Un arreglo con el historial del recorrido que hizo el trineo
Consideraciones
- Debemos detener el trineo al encontrar una barrera y guardarlo en el historial aunque no se mueva de allí
- Cuando el trineo pasa sobre una barrera abierta (
*
) éste la va a reemplazar en el string y una vez la haya pasado se debe volver a colocar la barrera abierta (*
)
Solución
La posición inicial del trineo se identifica al principio. La función itera por cada unidad de tiempo, avanzando el trineo si no hay una barrera cerrada delante. En la quinta unidad de tiempo, todas las barreras se abren permanentemente. El estado de la carretera se actualiza y guarda en un array en cada iteración, reflejando la posición del trineo y el estado de las barreras. El resultado final es un array que muestra el estado de la carretera en cada momento del tiempo dado.
Código
/**
* Simula el movimiento del trineo de Santa en una carretera durante un tiempo dado.
*
* @param {string} road - Representación de la carretera con '.', 'S', '|', y '*'.
* @param {number} time - Número de unidades de tiempo para simular.
* @return {string[]} - Array que representa el estado de la carretera en cada unidad de tiempo.
*/
function cyberReindeer(road, time) {
// Almacena el estado de la carretera en cada unidad de tiempo
const roadStates = [road];
// Encuentra la posición inicial del trineo
let sledPosition = road.indexOf("S");
// Carácter que será reemplazado por el trineo cuando se mueve
let replacedChar = ".";
// Itera por cada unidad de tiempo, menos uno, ya que el estado inicial ya está incluido
for (let i = 0; i < time - 1; i++) {
// Obtiene el estado actual de la carretera
let currentRoadState = roadStates[i];
// En la quinta iteración (unidad de tiempo 5), todas las barreras se abren
if (i === 4) {
currentRoadState = currentRoadState.replace(/[|]/g, "*");
}
// Verifica si la siguiente posición del trineo no es una barrera cerrada
if (currentRoadState[sledPosition + 1] !== "|") {
// Prepara la nueva posición del trineo
// concatenandólo al elemento que anteriormente estaba en esa posición
const newSledPosition = `${replacedChar}S`;
// Actualiza el carácter reemplazado por el trineo antes de ser reemplazado
replacedChar = currentRoadState[sledPosition + 1];
// Construye el nuevo estado de la carretera con el trineo movido una posición
const firstPart = currentRoadState.substring(0, sledPosition);
const lastPart = currentRoadState.substring(sledPosition + 2);
currentRoadState = firstPart + newSledPosition + lastPart;
// Actualiza la posición del trineo
sledPosition += 1;
}
// Añade el estado actualizado de la carretera al array
roadStates.push(currentRoadState);
}
// Retorna el array con el estado de la carretera en cada unidad de tiempo
return roadStates;
}
Soluciones de la comunidad
Solución por SantiMenendez19:
function cyberReindeer(road, time) {
let result = []
let timePassed = 0
let pos = 0
let aux = "."
while (time > 0) {
result.push(road)
time--
timePassed++
if (timePassed >= 5) road = road.replace(/\|/gi, "*")
if (road[pos+1] === '.' || road[pos+1] === '*') {
road = road.split("")
road[pos] = aux
aux = road[pos+1]
road[pos+1] = "S"
road = road.join("")
pos++
}
}
return result
}
Solución por Achalogy:
function cyberReindeer(road, time) {
let moves = [road]
let a = 0
let b = "."
for (let i = 1; i < time; i++) {
if (i == 5) road = road.replace(/\|/g, "*")
const newRoad = road.replace(/S[\.\*]/, `${b}S`)
if (newRoad != road) {
a++
b = road[a]
}
road = newRoad
moves.push(road)
}
return moves;
}
Y ese fue el reto para el 5 de diciembre y sus soluciones. ¿Tienes otra solución alternativa? ¡Déjala en los comentarios!
Top comments (3)
Hola Alejandro! Buena y legible solución. Gracias por compartirla.
Como consejo, cuando insertes un bloque de código puedes ponerle
javascript
para que dev.to lo reconozca como código de JS y pueda hacer el resaltado de sintaxis, ejemplo:Hola, gracias, soy nuevo por aquí, ya lo he formateado correctamente ;)