DEV Community

Cover image for AdventJS 2023: Day 4 Challenge
Fenriuz
Fenriuz

Posted on • Originally published at alexvalle.dev on

AdventJS 2023: Day 4 Challenge

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

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

Community Solutions

Solution by cristianstu:

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

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

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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

Top comments (1)

Collapse
 
lesterpaz99 profile image
Obed Paz

Here's my solution, a bit long but I'll refactor it:

function decode(message) {
  // Code here

  let level = 0;
  let textToDecode = '';
  let protectedContent = '';
  let result = '';

  for (let char of message) {
    if (char === '(') {
      level += 1;
      continue;
    }

    if (char === ')' && level === 1) {
      level -= 1;
      textToDecode = textToDecode.split('').reverse().join('');
      result += textToDecode;
      textToDecode = '';
      continue;
    }

    // max level
    if (char === ')' && level === 2) {
      level -= 1;
      protectedContent = protectedContent.split('').reverse().join('');
      textToDecode += protectedContent;
      protectedContent = '';
      continue;
    }

    if (level === 1) {
      textToDecode += protectedContent;
      protectedContent = '';
      textToDecode += char;
      continue;
    }

    // max level
    if (level === 2) {
      protectedContent += char;
      continue;
    }

    // level 0
    result += textToDecode;
    textToDecode = ''; // reset
    result += char;
  }
  return result;
}
Enter fullscreen mode Exit fullscreen mode