Skip to content

Latest commit

 

History

History
120 lines (95 loc) · 5.2 KB

File metadata and controls

120 lines (95 loc) · 5.2 KB

Solution

Submission link - https://bigfrontend.dev/problem/78/discuss/928

/**
 * @param {string} hex
 * @return {string}
 */
function hexToRgba(hex) {

  if(!hex.startsWith('#')) throw new Error(); // throw error if input is invalid

  const result = [];

  // check if 3 hexadecimal digits or 
  // 4 hexadecimal digits (with alpha value)
  // this includes "#" sign too, that's why +1
  if(hex.length == 4 || hex.length == 5) {
    for(let i = 1; i < hex.length; i++) {
      const value = getFunctionalValue(hex[i] + hex[i]);
      result.push(value);
    }
    setAlphaValue(result);
  } else if(hex.length == 7 || hex.length == 9) { // either 6 hexadecimal digits value or +2 digits for alpha value
    for(let i = 1; i < hex.length - 1; i+=2) {
      const value = getFunctionalValue(hex[i] + hex[i+1]);
      result.push(value);
    }
    setAlphaValue(result);
  } else {
    throw new Error(); // apart from above checks all are invalid inputs
  }


  function getFunctionalValue(hexPart) { // logic to convert hexadecimal for to integer value
    return Number.parseInt(hexPart, 16);
  }

  function setAlphaValue(result) {
    if(result.length < 4) { // 3 digits means no alpha value
      result.splice(3, 1, 1); // if no alpha value then set it to 1. (splice(start, removeTill, replacement))
    } else {
      const value = Number.parseFloat((result[3] / 255).toFixed(2)) // if more than 3 means we need to get fractional value
      result.splice(3, 1, value);
    }
  }

  return `rgba(${result.join(',')})`;

}

Short story

Again, such problems can be solved by regex or with an iterative approach. As you need to know about conversion rules before you write code, I tried digging online to understand hex to RGB color conversion. I will explain the conversion in the algorithm section and feel free to suggest any kind of optimization in the above code.

Understanding Hexadecimal colors

There are 4 valid variants of hexadecimal color.

  • shorthand (#fff)
  • shorthand with alpha value (#fff3)
  • longhand (#ffffff)
  • longhand with alpha value (#ffffff33)

Each pair from left to right represents a red, green, and blue value. If we have shorthand input then we simply add it twice to form a pair. The alpha value works similarly, we either have a pair or single.

This helps us to understand valid input length which is either -

  • 3 (for shorthand)
  • 4 (for shorthand with alpha value)
  • 6 (for longhand)
  • 8 (for longhand with alpha value)

If you are not separating # then you can add +1 in the above length. We are doing the same in our program.

Algorithm

There is two main logic in the above program.

  • Conversion of hexadecimal colors
  • Conversion of the alpha value

Conversion of hexadecimal colors

  • If it is shorthand then we simply add it twice and convert into an integer with base 16
  • If it is longhand then we add current and next value and convert into an integer with base 16

Conversion of the alpha value

  • The steps are the same as converting to hexadecimal and we do it along with hexadecimal conversion
  • We know that we will have either 3 or 4 values in the array. Length 3 implies that there is no alpha value.
    • If no alpha value then we add 1
    • Else we convert it to fraction/percentage dividing by 255 (maximum color value)

Code overview

There can be many invalid inputs in the above program.

  • We begin with checking if the input starts with the # sign. That's how hexadecimal colors are written. If it doesn't then we throw an error.
  • Next, we create an array result to store our RGB values.
  • For input length validation, we check if the length is either 4 or 5 (this includes # sign too)
    • If this check is valid then we know it is shorthand (with or without alpha value)
    • We iterate over input hex
    • We get the value by passing the current value hex[i] twice in getFunctionalValue that converts it to an integer with base 16
    • We push the value in the result array
  • If the above check fails then we check if the length is either 7 or 9 (this includes # sign too)
    • If this check is valid then we know it is longhand (with or without alpha value)
    • We iterate over input hex
    • We get the value by passing the current value hex[i] and next value hex[i+1] in getFunctionalValue which converts it to an integer with base 16
    • We increment the index by 2 (i+=2) because we already covered the next value in the above step
    • We push the value in the result array
  • If this check fails then we consider that input is invalid and we throw an error.
  • We also have a setAlphaValue function whose job is to convert the alpha value to a fraction. We call this function in each valid case.
    • As we know that result will have either 3 or 4 values. If it is 3 means only RGB is present and we can safely add 1 as alpha value for this case.
    • If its length is 4 means we need to convert the 3rd result[3] position to a fraction. We divide the alpha value by 255 (maximum color value) to get the fraction.
  • We form RGBA string at the end and return it

🌻 ✨


I'm excited to improve the solution and code walkthrough. Feel free to drop a comment, or send a PR or send memes @knowkalpesh.