AdventJS 2023: Day 5 Challenge

AdventJS 2023: Day 5 Challenge

Santa's Sled Road History!

ยท

5 min read

The solution to the Challenge #5 of AdventJS 2023

The solution to the previous challenge

The solution to the next chprevious challengeallenge

Challenge Description

Santa ๐ŸŽ… is testing his new electric sled, the CyberReindeer, on a North Pole road. The road is represented by a string of characters, where:

  • . = Road

  • S = Santa's Sled

  • * = Open barrier

  • | = Closed barrier

Example of a road: S...|....|.....

For each unit of time, the sled moves one position to the right. If it encounters a closed barrier, it stops until the barrier opens. If it is open, it goes through directly.

All barriers start closed, but after 5 units of time, they all open forever.

Create a function that simulates the sled's movement for a given time and returns an array of strings representing the state of the road at each unit of time:

const road = 'S..|...|..'
const time = 10 // units of time
const result = cyberReindeer(road, time)

/* -> result:
[
  'S..|...|..', // initial state
  '.S.|...|..', // sled advances on the road
  '..S|...|..', // sled advances on the road
  '..S|...|..', // sled stops at the barrier
  '..S|...|..', // sled stops at the barrier
  '...S...*..', // barrier opens, sled advances
  '...*S..*..', // sled advances on the road
  '...*.S.*..', // sled advances on the road
  '...*..S*..', // sled advances on the road
  '...*...S..', // passes through the open barrier
]
*/

The result is an array where each element shows the road at each unit of time.

Take into account that if the sled is in the same position as a barrier, then it takes its place in the array.

Analysis

To solve this challenge, we must move the letter S within the string and stop it when it finds a barrier (|). The barrier will open (*) after 5 units of time. We need to store the journey of the letter S in an array until the units of time run out.

Inputs

  1. Road (road): The original string through which the sled will make its journey.

  2. Time (time): A number with the units of time.

Output

  • An array of the history of the sled's journey

Considerations

  • We must stop the sled when it encounters a barrier and store it in history even if it does not move from there.

  • When the sled passes over an open barrier (*), it will replace it in the string and once it has passed, the open barrier (*) must be put back.

Solution

The initial position of the sled is identified at the beginning. The function iterates for each unit of time, advancing the sled if there is no closed barrier ahead. On the fifth unit of time, all barriers open permanently. The state of the road is updated and saved in an array at each iteration, reflecting the position of the sled and the state of the barriers. The final result is an array showing the state of the road at each moment of the given time.

Code

/**
 * Simulates the movement of Santa's sled on a road for a given time.
 * 
 * @param {string} road - Representation of the road with '.', 'S', '|', and '*'.
 * @param {number} time - Number of units of time to simulate.
 * @return {string[]} - Array representing the state of the road at each unit of time.
 */
function cyberReindeer(road, time) {
  // Stores the state of the road at each unit of time
  const roadStates = [road];

  // Finds the initial position of the sled
  let sledPosition = road.indexOf("S");

  // Character that will be replaced by the sled when it moves
  let replacedChar = ".";

  // Iterates for each unit of time, minus one, since the initial state is already included
  for (let i = 0; i < time - 1; i++) {
    // Gets the current state of the road
    let currentRoadState = roadStates[i];

    // On the fifth iteration (unit of time 5), all barriers open
    if (i === 4) {
      currentRoadState = currentRoadState.replace(/[|]/g, "*");
    }

    // Checks if the next position of the sled is not a closed barrier
    if (currentRoadState[sledPosition + 1] !== "|") {
      // Prepares the new sled position
      // concatenating it to the element that previously was in that position
      const newSledPosition = `${replacedChar}S`;

      // Updates the character replaced by the sled before being replaced
      replacedChar = currentRoadState[sledPosition + 1];

      // Builds the new state of the road with the sled moved one position
      const firstPart = currentRoadState.substring(0, sledPosition);
      const lastPart = currentRoadState.substring(sledPosition + 2);
      currentRoadState = firstPart + newSledPosition + lastPart;

      // Updates the sled position
      sledPosition += 1;
    }

    // Adds the updated state of the road to the array
    roadStates.push(currentRoadState);
  }

  // Returns the array with the state of the road at each unit of time
  return roadStates;
}

Community Solutions

Solution by SantiMenendez19:

javascriptCopy codefunction 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
}

Solution by Achalogy:

javascriptCopy codefunction 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;
}

And that was the challenge for December 5th and its solutions. Do you have another alternative solution? Leave it in the comments!

ย