DEV Community

Cover image for AdventJS 2023: Reto del Día 5
Fenriuz
Fenriuz

Posted on • Updated on

AdventJS 2023: Reto del Día 5

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
]
*/
Enter fullscreen mode Exit fullscreen mode

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

  1. Road(road): El string original por el cual el trineo hará su recorrido.
  2. 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;
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
alejandropicano profile image
Alejandro Miguel Pi Cano • Edited
function cyberReindeer(road, time) { 
  if (time == 0)
   return [];

   let result = [];
   result.push(road);
   let previous = ".", position = 1;

  for(let i=1;i<time;i++){
      if(i==5)
      road = road.replaceAll("|", "*");
       if(road[position] != "|"){
         let current = road[position]; 
         let fp=road.substr(0, position-1);
         let sp=road.substr(position+1, road.length-1-position);  
         road= fp + previous + "S" + sp           
         previous = current;
         position++;
      }
      result.push(road);
  }
  return result;
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
fenriuz profile image
Fenriuz

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:

Bloque de código

Collapse
 
alejandropicano profile image
Alejandro Miguel Pi Cano

Hola, gracias, soy nuevo por aquí, ya lo he formateado correctamente ;)