Help with function that calculates average color

Help with function that calculates average color
0

#1

Can someone please help me out on this question please?

Write a function that takes 2 colors as arguments and returns the average color.

  • The parameters will be two 6-digit hexadecimal strings. This does not need to be validated.
  • The return value should be a 6-digit hexadecimal string.
  • The hexadecimal strings represent colors in RGB, much like in CSS.
  • The average color is to be determined by taking the arithmetic mean for each component: red, green and blue.

Manipulating Complex Objects challenge
#2

I moved your question to a new topic, because it was completely unrelated to the other thread.

Sounds fairly straight forward. What have you tried so far?


#3

@RandellDawson no problem. This is how far I’ve gotten I don’t know if am correct or not:
MY SOLUTION BELOW:

function colorFind(rgb(255,0,0), rgb(0,255,0)){
red.sort(function(a,b){
return a-b;
});
for(var a=0; a < red.length; a++){
if(rgb(255,0,0)[a] >= rgb(0,255,0))
return a;
}
return red;
}
colorFind(rgb(255,0,0), rgb(0,255,0), rgb(0,0,255));


#4

Functions have parameters which define placeholders for the values passed into them. The following is not a valid function definition.

function colorFind(rgb(255,0,0), rgb(0,255,0)){

The following would be a valid function definition;

function colorFind(hexColor1, hexColor2){

You have called the sort function on a variable called red, but you have not declared red in your code.

I think you need to go back and review how to create functions before continuing. See the following challenge for a review.

Also, your requirements said your function would receive two 6-digit hexacecimal strings. You seem to not understand what those would look like. Take a look at the following challenge which would show what those look like.

Once you have a better understanding of the above two challenges, you first need to figure out how you will separate the components of each hexadecimal string before you can figure out how to calculate the average color which needs to be returned by the function.


#5

Once you solve this problem, you can take a look at my solution. There is probably a more elegant solution, but mine seems to work.

const averageColor = (hex1, hex2) => {
  const splitHEX = color => color.match(/.{1,2}/g);
  const leadingZero = val => (Number(val) < 10 ? '0'+val : val).toUpperCase(); 
  const convert = val => parseInt(val,16)
  const color1 = splitHEX(hex1);
  const color2 = splitHEX(hex2);
  return color1.map((component, idx) =>
    leadingZero(Math.round( (convert(component) + convert(color2[idx]) ) / 2 ).toString(16)))
  .join('');
};
averageColor('FF0000','FFFF00'); // 'FF80000'

#6

After thinking about it a bit more, I came up with a solution which will produce the average color for any number of colors passed to the function.

const averageColor = (...colors) => {
  const leadingZero = val => Number(val) < 10 ? '0'+val : val; 
  const compSums = colors.reduce((rgb, color) => {
    const comps = color.match(/.{1,2}/g).map(comp=> parseInt(comp,16));
    return rgb.map((comp,i)=> comp+comps[i]);
  },[0, 0, 0]);
  return compSums.map(sum => leadingZero(Math.round(sum/colors.length)).toString(16)
  ).join('').toUpperCase();
};

averageColor('FF0000','FFFF00','0000FF'); // 'AA5555'

#7

This second solution is quite abit complex than the first… Tell me @RandellDawson what’s the best way I can get to really improve on the way to approach algorithm challenges and also atleast be good at them now that am focusing mostly on Javascript. Am asking you because you seem to be experienced and somehow a teacher


#8

@sammiles You will get better as you practice solving more problems/challenges. The one thing that helps me when I have a complex problem to solve is breaking it down into smaller pieces (problems) first and then solve each separately. If you do not break some problems down, you can easily get overwhelmed with where to start.

I actually broke this problem down (see my thought process for my first solution below), before actually writing any code.

Piece #1
I knew I first had to be able to separate each of the two colors down to the 3 components (red, green, blue) and I knew that I would need to iterate over both color’s red, green, and blue components, so I concluded the easiest way to do that was to create an array for each color containing the 3 components. At this point, I was not concerned about how I would create the array of components, but knew that is the data structure that I needed to help me solve the problem.

Piece #2
Assuming I would have to color variables with three 2-letter string elements in each, I now needed to figure out a formula which would help me calculate the arithmetic mean for each color component. Since I knew there were only two colors, I knew I could add a component from one color to the corresponding component of the other color and divide by 2 to get the mean.

Piece #3
Since these components were represented in hexadecimal, I decided to convert them to decimal first to make it easier for me to calculate the mean. Also, I decided I should store these mean values in an array of components, where I could iterate over them later to create a final hexcode string that the function would return.

Now that I had my basic outline of what I needed to do to solve this problem, I decided to start writing code for each piece (see below).

Piece #1 Code
There are several ways I could have created these arrays of components, but because I have worked with the match function before, I knew I could split it into two character groups using a regular expression ( the /.{1,2}/g part. Also, since I knew I would need to do this for each color, I created a function called splitHex that would return an array of these components. If I would have not known how to use the match function to create the array of colors, I could have used something like the code below to write the splitHex function.

  const splitHEX = color => {
    var componentsArr = [];
    for (var i = 0; i < color.length; i += 2) {
      componentsArr.push(color.slice(i, i+2));
    }
    return componentsArr;
  };

Piece #2 Code
So to calculate the mean for each component using the two colors, I used the map function to iterate over the first color’s components and made use of the map function’s 2nd argument (element index) to reference the second color’s components. I decided to round the mean to the nearest integer to avoid fractions of hexadecimal numbers for colors. Also, because a hexcode for a component must be exactly 2 characters, I created a function which would add a ‘0’ to the beginning of any number less than 10.

Piece #3 Code
My formula in piece #2 (above) needed the components’ values to be in decimal, so I remembered that the parseInt function had that functionality built into it. Notice I created a function to reduce repeating the same code for each component which need to be converted.


#9

This is very helpful I’ll start using this method when solving a problem. I definitely think it’s a good way to start with when you’re faced with a challenge. Thanks a lot for breaking it down for me.