AdventJS 2023: Day 4 Challenge

AdventJS 2023: Day 4 Challenge

Decoding messages in parentheses!

ยท

3 min read

The solution to Challenge #4 of AdventJS 2023

The solution to the previous challenge

The solution to the next challenge

Challenge Description

In ๐ŸŽ… Santa's workshop, some Christmas messages have been written peculiarly: the words within the brackets must be read backward.

Santa needs these messages to be correctly formatted. Your task is to write a function that takes a string and reverses the characters within each pair of parentheses, removing the parentheses as well.

However, bear in mind that there may be nested parentheses, so you should reverse the characters in the correct order.

const a = decode('hola (odnum)')
console.log(a) // hola mundo

const b = decode('(olleh) (dlrow)!')
console.log(b) // hello world!

const c = decode('sa(u(cla)atn)s')
console.log(c) // santaclaus

// Step by step:
// 1. Reverse the nested -> sa(ualcatn)s
// 2. Reverse the remaining one -> santaclaus

Notes:

  • The input strings will always be well-formed with parentheses that match correctly, you do not need to validate them.

  • There should not be any parentheses left in the final message.

  • The maximum nesting level is 2.

Analysis

In this exercise, the goal is to reverse the letters that are within parentheses. If there are nested parentheses, you'll need to reorder multiple times, depending on the number of nested levels.

Input

  1. Message (message): A string with the message in which we must search and reorder the letters that are inside parentheses.

Output

  • The correctly ordered string

Considerations

  • There is no need to validate that the parentheses match and are well closed.

  • All parentheses in the text should be removed.

Solution

To cover all cases and considerations, you should start by looking for the last opening parenthesis ( and then match it with the first closing parenthesis ) after the opening one. Extract the letters that are inside and reorder them in reverse.

Then repeat the process with the resulting string, so a while loop can be used to achieve this.

Code

/**
 * Decodes a message by reversing the characters between each pair of parentheses.
 *
 * @param {string} message - The message to be decoded.
 * @return {string} - The decoded message.
 */
function decode(message) {
  // Initialize variables to store the indices of the opening and closing parentheses
  let init, end;

  // Loop until there are no more opening and closing parentheses
  while (init !== -1 || end !== -1) {
    // Find the index of the last opening parenthesis
    init = message.lastIndexOf("(");

    // Find the index of the closing parenthesis after the last opening parenthesis
    end = message.indexOf(")", init);

    // Extract the encoded string between the opening and closing parentheses
    const encoded = message.substring(init, end + 1);

    // Reverse the characters in the encoded string, excluding the opening and closing parentheses
    const decoded = encoded.split("").slice(1, -1).reverse().join("");

    // Replace the encoded string with the decoded string in the original message
    message = message.replace(encoded, decoded);
  }

  // Return the decoded message
  return message;
}

Community Solutions

Solution by cristianstu:

function decode(message) {
  const msg = message.replace(/\(([^()]*)\)/g, (_, match) => 
    match.split('').reverse().join('')
  );

  return msg.includes('(') ? decode(msg) : msg;
}

Solution by TimmyElTaco:

function decode(message) {
  let matches = [];

  while (matches = message.match(/\(([^()]*)\)/)) {
    matches = matches.map((word) => {
      return word.split('').reverse().join('')
    })
    let string = matches[0].replace(/[()]/g, '');
    message = message.replace(/\(([^()]*)\)/, string);
  }

  return message;
}

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

ย