Similar RGB Color

Updated on 08 July, 2025
Similar RGB Color header image

Problem Statement

In RGB color models, colors are often represented using hexadecimal values, for instance, "#AABBCC". This standard format can notably be simplified through a shorthand notation "#ABC", where each component of the color is duplicated to form the full length. For example, "#15c" expands to "#1155cc" when converted from shorthand to full length.

Additionally, there exists a method to quantify the similarity between two colors represented in the full 6-digit hexadecimal format. This method calculates similarity through a formula that considers the difference between respective hex color segments: -(AB - UV)^2 - (CD - WX)^2 - (EF - YZ)^2. Here, AB, CD, and EF represent segments of one color while UV, WX, and YZ represent another.

The problem revolves around determining the most similar shorthand notation color to a given 6-digit color. Given any 6-digit hexadecimal color following the pattern "#ABCDEF", we are tasked to convert it to its corresponding shorthand notation "#XYZ" that maximizes similarity based on the defined formula.

Examples

Example 1

Input:

color = "#09f166"

Output:

"#11ee66"

Explanation:

The similarity is -(0x09 - 0x11)2 -(0xf1 - 0xee)2 - (0x66 - 0x66)2 = -64 -9 -0 = -73.
This is the highest among any shorthand color.

Example 2

Input:

color = "#4e3fe1"

Output:

"#5544dd"

Constraints

  • color.length == 7
  • color[0] == '#'
  • color[i] is either digit or character in the range ['a', 'f'] for i > 0.

Approach and Intuition

To solve the problem, follow these steps:

  1. Understand the relationship between shorthand and full-length hexadecimal color representation:

    • Shorthand notation duplicates each hex digit to create a full six-character sequence. Therefore, to generate possible full-length versions from a shorthand representation, each digit from 0 to f (in hex) must be considered for every position in XYZ.
  2. Calculate the similarity between the given full-length color string and each possible shorthand derivative:

    • Utilize the provided similarity formula where subtraction and squaring of numerical differences for respective segments measure how "close" two colors are.
  3. Iteratively test each possible shorthand color:

    • Using nested loops iterate over all combinations of hexadecimal digits from 00 to ff (for red, green, and blue). For each combination, convert it into a shorthand format and then back to its expanded full-length form.
    • Compute the similarity between the original color and the computed shorthand full-length. Keep track of the shorthand notation that yields the highest similarity score.
  4. Return the shorthand notation with the highest similarity to the input color:

    • This final result will be the shorthand color which, when expanded, resembles the provided color most closely based on the formula.

Remember, due to the nature of the task, multiple shorthand colors may exhibit the same level of highest similarity with the input color. Hence, any of these could be a valid solution.

Solutions

  • C++
cpp
class Solution {
public:
    string findClosestMatch(string section) {
        int hexValue = stoi(section, nullptr, 16);
        int similarHex = round(hexValue / 17.0);
        string closestHex;
        closestHex = similarHex > 9 ? 'a' + similarHex - 10 : '0' + similarHex;
        return closestHex + closestHex;
    }
    
    string closestRGB(string originalColor) {
        string optimizedColor = "#";
    
        for (int j = 1; j < 6; j += 2) {
            optimizedColor += findClosestMatch(originalColor.substr(j, 2));
        }
    
        return optimizedColor;
    }
};

In the given C++ code snippet, start by understanding that the main purpose is to find a color code in RGB that is closest to the one provided, with the restriction that the RGB values must be composed of characters that are the same.

  • findClosestMatch is a function designed to handle a single RGB component (e.g., "ae"). This function:

    1. Converts the two-character hexadecimal value to its integer equivalent.
    2. Finds the nearest valid single hex character replicated twice that approximates the input. This is done by dividing the integer by 17 and rounding off to get the nearest whole number. Depending on if the rounded value is above 9, it either translates into a character between 'a' to 'f' or remains a numeric character.
    3. The result is then doubled to conform to the format, for example, "aa".
  • closestRGB takes the complete color code (expected format like "#aabbcc") and initializes a string optimizedColor with "#".

    1. Then, iterating over each pair of hex digits (representing RGB components), it calls findClosestMatch for each pair. The loop skips every second character due to the step increase by 2, starting from index 1.
    2. Concatenates the results to form the new closest matching RGB color code.

Following these functions, the code provides an optimized way to decompose an RGB color into individual components, approximate each by the closest visually similar color, and rebuild the color code.

  • Java
java
class Solution {
    public String closestHex(String hexSegment) {
        int value = Integer.parseInt(hexSegment, 16);
        int closestVal = Math.round((float)value / 17);
        return Integer.toHexString(closestVal).repeat(2);
    }
        
    public String closestRGB(String originalColor) {
        StringBuilder closestColor = new StringBuilder();
        closestColor.append("#");
            
        for (int index = 1; index < 6; index += 2) {
            closestColor.append(closestHex(originalColor.substring(index, index + 2)));
        }
            
        return closestColor.toString();
    }
}

The Java solution presented here is designed to find the closest similar RGB color to a given RGB color in hexadecimal format. The provided code follows two primary steps:

  1. Implement the closestHex method:

    • This method takes a string representing a two-character segment of a hexadecimal value.
    • Convert this hexadecimal string to an integer.
    • Compute the closest multiple of 17 to this integer (since color codes in shortened hex format are multiples of 17), and round to the nearest integer.
    • Convert this integer back to a two-character hexadecimal string.
  2. Implement the closestRGB method:

    • Start by appending a "#" to initialize the resultant RGB color string.
    • Iterate through the input color's hexadecimal characters in pairs (representing the red, green, and blue segments, respectively).
    • For each segment, call closestHex to compute the closest color value, and append this to the resultant color string.

This approach ensures that the closest RGB color in hexadecimal format is efficiently computed by handling each color component separately. The algorithm makes use of standard integer and string manipulation functions in Java to perform the necessary conversions and calculations.

  • Python
python
class Solution:
    def closestRGB(self, hex_color: str) -> str:
        def nearestSimilar(hex_segment):
            decimal_value = int(hex_segment, 16)
            nearest = round(decimal_value / 17)
            return format(nearest, 'x') * 2
    
        result_color = "#"
        for j in range(1, 7, 2):
            result_color += nearestSimilar(hex_color[j:j + 2])
            
        return result_color

This article guides you on implementing a Python solution that finds the closest matching RGB color to a given hex color. The code provided uses the Python3 programming language.

The crux of the solution lies in the closestRGB function inside the Solution class. This function takes a single string argument hex_color that represents the color in hexadecimal format.

Here's how the function operates:

  • A nested function nearestSimilar is defined, which:

    • Converts a two-character hexadecimal segment to its decimal equivalent.
    • Calculates the closest value which, when multiplied by 17, approximates the original decimal value. This is achieved through rounding.
    • Returns the calculated value in hexadecimal format, making sure to double the character to maintain the two-character grouping needed for RGB notation.
  • The function initializes a string result_color with '#', which is the starting character for hex color codes.

  • A for loop runs with a step of 2, starting from index 1 up to 6, to process each pair of hexadecimal digits (representing red, green, and blue components separately). The loop:

    • Extracts two characters from hex_color at a time.
    • Passes them to nearestSimilar to get the closest color segment.
    • Adds the returned value to result_color.
  • Finally, the revived hexadecimal color string in result_color is returned.

The key takeaway is the transformation of each RGB component separately before reassembling them. This ensures the resulting color closely approximates the original while still being simpler by using fewer unique hexadecimal values (only those obtainable by the product of 17). This method adeptly balances simplicity and accuracy in arriving at an RGB value near the input.

Comments

No comments yet.