# The hue of a color

You are given the RGB values of a color. Your task is simple: to calculate the hue, in the simplest definition.

Say the channels with highest, middle and lowest value are X, Y, Z (which are either red, green or blue) and their values are x, y, z. The hue of this color is (h(X)-h(Y))*(1 + (x-y)/(x-z))/2 + h(Y), where:

h(red) = 0 (or 360 if one of X or Y is blue)
h(green) = 120
h(blue) = 240


The input consists of 3 integers from 0 to 255 which are not all equal, in any consistent order. The output can be floats, or integers rounded either up or down, which doesn't have to be consistent. If the integer part of the output is 0 or 360, you can print either of them.

You cannot call builtins for color space conversions, including implicit conversions such as while manipulating an image.

This is code-golf. Shortest code wins.

## Examples

Input:  0 182 255
Output: 197 (or 198)

Input:  127 247 103
Output: 110

Input:  0 0 1
Output: 240

Input:  255 165 245
Output: 307 (or 306)


## Edit

You don't have to follow the exact formula, but only have to give the same result as the above formula. I'd like to also see some answers golfing the formula itself.

• Should we convert from sRGB to a linear scale first? I think we should, but nobody seems to have so far. Aug 19, 2015 at 13:10
• @JanDvorak The task is to calculate the hue, in the simplest definition. In this case, "simplest" means you should assume the input is already in the right scale, and use the exact formula given in the question or anything that gives the same result. Aug 19, 2015 at 13:27
• But... 24 bpp usually means sRGB. If not, the format specification (you) should specify otherwise. Aug 19, 2015 at 13:33
• @JanDvorak You should use this definition for RGB and the hue. Aug 19, 2015 at 13:59
• It has to be said: huehuehue. Aug 19, 2015 at 16:05

# C#, 188210206197 191 bytes

int H(int r,int g,int b){int[]a={r,g,b};System.Array.Sort(a);int x=a[2],y=a[1],c=x==g?1:(x==b?2:(y==b?3:0)),d=y==g?1:(y==b?2:(x==b?3:0));return(int)((c-d)*120*(1+(x-y)*1D/(x-a[0]))/2+d*120);}


Thanks to Sok for saving 4 bytes and to SLuck49 for saving 15!

• As you only use z once in the output calculation, and you don't use it in the preceding calculations, you do away with the variable and change the output to return(int)((c-d)*(1+(x-y)/(double)(x-a[0]))/2+d);, saving you 4 bytes.
– Sok
Aug 19, 2015 at 14:47
• You can factor 120 out of the c and d assignments and into the return like this c=x==g?1:(x==b?2:(y==b?3:0)),d=y==g?1:(y==b?2:(x==b?3:0)) and then return(int)((c-d)*120*(1+(x-y)/(double)(x-a[0]))/2+d*120); to save 4 bytes. Aug 19, 2015 at 20:23
• Also do you really need the cast to double? If you do you can use this instead (x-a[0])*1D to save another 5 bytes. Aug 19, 2015 at 20:25
• @SLuck49 Thanks! Yes, I actually need the cast, it gives inaccurate results otherwise, but that *1D multiplication is a nice trick! Aug 19, 2015 at 20:32
• Also also (just noticed) you can drop the using all together by fully qualifying System.Array for another 6 bytes. Aug 19, 2015 at 20:53

## Pyth, 415553 51 bytes

A.)JohN,VQ*L120?qeQhSQ3j312T+/*-HKeeJhc-GheJ-GhhJ2K


Input is expected in the form r,g,b. Here's an explanation:

                                                        Implicit: Q=eval(input()), evaluates to (r,g,b)
?qeQhSQ                                  Is b the smallest?
3j312T                            Choose [0,1,2] or [3,1,2] based on above
*L120                                         Convert to [0,120,240] or [360,120,240]
,VQ                                              Pair -> [[r,0/360],[g,120],[b,240]]
JohN                                                 Order by 1st element in each pair, store in J
A.)J                                                    Pop biggest from J, set G = x, H = h(X)
Output calculation:
-GheJ                x - y
-GhhJ           x - z
hc                     Divide and increment
KeeJ                       Set K = h(Y)
*-HK                          Multiply by (h(X) - h(Y))
/                   2          Integer division by 2


Saved 4 bytes, thanks to @Jakube and @isaacg

• @jimmy23013 Fixed, thanks for the extra test case
– Sok
Aug 19, 2015 at 12:59
• A couple of golfs: m*120d -> *L120, save eeJ to K inline to save another byte. Aug 19, 2015 at 15:27
• @isaacg I didn't know the L operator generated a range on an int automatically, every day is a shcool day it seems :o) Thanks!
– Sok
Aug 19, 2015 at 15:47

# Javascript (ES6), 14511510810097 90 bytes

Returns floats. Assign to a function to use.

(r,g,b)=>([x,y,z]=[r,g,b].sort((a,b)=>b-a),m=x-z,(x-r?x-g?r-g+4*m:b-r+2*m:g-b+6*m)/m%6*60)


Saved 30 bytes by inlining everything into a single ternary operator sequence and waiting until the end to normalize to 0-360.

Thanks to edc65, Vasu Adari, and ETHproductions for saving even more bytes.

JSFiddle with tests. Try in Firefox.

If removing the function declaration h= is not legal, add 2 bytes.

• You can remove 'var' and some bytes. Aug 26, 2015 at 15:13
• ES6Fiddle needs the var declaration for some reason and I didn't realize it wasn't necessary until I tried ES6 in firefox Aug 26, 2015 at 17:02
• You can save 6 bytes by replacing the curly braces with parentheses, the semicolon with a comma, and removing the return. I believe removing the function declaration (h=) is also legal, bringing the total down to 100. Aug 26, 2015 at 17:15
• This may be obsessive (then again, aren't all good golfers? ;) ), but you could save two more bytes by getting rid of the parenthesis in %6)*60 and its partner on the other side. Also, using brute force on the addition (instead of adding 6 at the end) would actually save one byte over your current setup. (((x==r?(g-b)/m:x==g?2+(b-r)/m:4+(r-g)/m)+6)%6)*60 would become (x==r?6+(g-b)/m:x==g?8+(b-r)/m:10+(r-g)/m)%6*60. Aug 27, 2015 at 2:52
• +1 for the sort, very clever, This is 90 (or 92) (r,g,b)=>([m,_,M]=[r,g,b].sort((a,b)=>a-b),C=M-m,(M-r?M-g?r-g+4*C:b-r+2*C:g-b+6*C)/C%6*60) Aug 27, 2015 at 15:44

# Pyth, 27 bytes

*60%+c-Ft.<QJxQKeSQ-KhSQyJ6


Fomula taken from Wikipedia.

Essentially, the steps are:

1. .<QJxQKeSQ: Roate the largest value to the front of the list.
2. -Ft: Take the difference of the other two values.
3. -KhSQ: Subtract the minimum value from the maximum value.
4. c: Divide 2 by 3.
5. + ... yJ Add twice the index of the maximum value in the list (0 if R, 2 if G, 4 if B).
6. % ... 6: Mod 6, to fix issues with negatives.
7. *60: Multiply by 60 to convert to degrees, and print.

# Octave, 6560 50 bytes

### An approximate solution...

@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)


### Test run

@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)
ans([0   182   255])
ans =  196.14

@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)
ans([127   247   103])
ans =  111.05

@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)
ans([0   0   1])
ans =  240.00

@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)
ans([255   165   245])
ans =  305.82


# Octave, 107 bytes

### Code:

function H=r(c) [b,i]=sort(c);h=60*[6*(i(1)~=3),2,4](i);H=(h(3)-h(2))*(1+(b(3)-b(2))/(b(3)-b(1)))/2+h(2);


### Explained:

function H=r(c)
[b,i]=sort(c);
h=60*[6*(i(1)~=3),2,4](i);
H=(h(3)-h(2))*(1+(b(3)-b(2))/(b(3)-b(1)))/2+h(2);


This function takes a vector containing the R,G,B values as input c and sorts the input in ascending order

• b contains the sorted values [z, y, x]
• i contains the RGB plane associated with each value in b

The vector h is populated with the values

• 60*[6, 2, 4] = [360, 120, 240] (but 3 bytes shorter)
• unless the lowest value is in Blue (i(1) == 3), in which case the first hue value becomes zero
• then use (i) to rearrange h into [h(Z), h(Y), h(X)] order

From there it's just a straight transcription of the formula. You can try it here.

• Hint: use anonymous function notation to squeeze more bytes: @(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360) is ten bytes shorter than definition with function keyword. Aug 28, 2015 at 19:22
• @pawel.boczarski I was wondering if I could do away with the function header altogether, but I don't know if that's legit. But thanks for the tip! :D Aug 28, 2015 at 19:25
• @pawel.boczarski Looking back at this, I still need a r= before the anonymous function in order to call it, right? Aug 28, 2015 at 20:01
• There are many solutions where anonymous functions are posted. Moreover, you could call the so-defined function even like this: (@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360))([127 247 103]) , or argue that you can use ans variable right after the anonymous function was defined, so that assignment is not necessary for the function definition to be complete. In one challenge (codegolf.stackexchange.com/questions/54945) a handle of existing Matlab library function was posted as full solution. Aug 28, 2015 at 20:51
• @pawel.boczarski Wow, that's... just... evil :D I should have known Luis would be involved. I'll revert to the original code and use ans in the sample. Thanks again! Aug 28, 2015 at 21:57

# Pyth, 55

I know @Sok's answer beats mine, but since I finished mine just after he/she posted, I thought I would still post. This was my first time using Pyth so I'm sure I made some obvious mistakes.

DlZK*120ZRKJSQFNJ=Y+YxQN)=kl@Y1+k/*-leYk+1c-eJ@J1-eJhJ2


Input is expected to be r, g, b. You can try it here.

• Doesn't work for 255,165,245. Aug 19, 2015 at 11:47

## PowerShell, 232226222 161 Bytes

See revision history for previous versions

$z,$y,$x=($r,$g,$b=$args)|sort$c=((2,(0,3)[$y-eq$b])[$x-ne$b],1)[$x-eq$g]
$d=((2,(0,3)[$x-eq$b])[$y-ne$b],1)[$y-eq$g] (($c-$d)*120*(1+($x-$y)/($x-$z))/2+$d*120)


Hoo boy, let's see if I can walk through this. Since \n counts the same as ; I left the line breaks in for clarity.

The first line takes input as three $args and stores them into $r, $g,$b. We're really only going to be using $b later, but we need all three so the |sort works appropriately. This makes $z, $y,$x the smallest-to-largest of the input arguments.

The next two lines setup $c and $d by using multiple index-into-an-array calls to set the numbers appropriately. Working from outside in, if $x is -equal to $g (i.e., green was the largest), we set $c=1 ... else, if $x is -notequal to $b (i.e., blue wasn't the largest) $c is either 0 or 3 depending if blue was the second largest ... else, $c=2. Similar logic sets $d.

We then calculate and print the output with the following, which is just the algorithm from the challenge golfed a little bit.

(($c-$d)*120*(1+($x-$y)/($x-$z))/2+$d*120)  • I don't know PowerShell, so correct me if I'm wrong... You don't use $z when calculating $c or $d, and you only use it once in the output calculation, so can you get rid of $z entirely and replace it with $a[0]?
– Sok
Aug 19, 2015 at 15:14

# Ruby, 11796 94 bytes

Code:

h=->r,g,b{z,y,x=[r,g,b].sort;v=x-z.to_f;({r=>(g-b)/v,g=>2+(b-r)/v,b=>4+(r-g)/v}[x]%6*60).to_i}

• Saved 21 bytes by removing () and using r,g,b variables.
• Taking modulus of 6 to convert negative value and multiplying it by 60 to convert to degrees that saved 2 bytes.

Examples:

irb(main):274:0> h.call 0,182,255
=> 197
irb(main):275:0> h.call 127,247,103
=> 110
irb(main):276:0> h.call 0,0,1
=> 240
irb(main):277:0> h.call 255,165,245
=> 306


# SWI-Prolog, 133 bytes

a(L,H):-L=[R,G,B],max_list(L,X),min_list(L,Y),member(X:I:J:U,[R:G:B:0,G:B:R:2,B:R:G:4]),Z is 60*(U+(I-J)/(X-Y)),(Z<0,H is Z+360;H=Z).


Example: a([255,165,245],Hue). outputs Hue = 306.666666666666 .

This uses the following formula:

• Max = max(R,G,B), Min = min(R,G,B).
• If Max = R, U = 0. Else if Max = G, U = 2. Else U = 4.
• If Max = R, I = G and J = B. Else if Max = G, I = B and J = R. Else I = R and J = G.
• Z = U + (I - J)/(Max - Min)
• Hue is either Z or Z + 360 if Z < 0.
• Rounding is optional. Aug 23, 2015 at 8:49

# Perl 5, 138132 119 bytes

### Code:

($m,$c,$M)=sort@A=($R,$G,$B)=@ARGV;print 60*(6+$M>$m?($G>$c?$B-$R:$B>$c?$R-$G:$G-$B)/($M-$m)+($G>$c?2:$B>$c?4:0):0)%360


### Remarks:

Surely Perl can't win such challenge with all the Pyth'oresque golfing. But I wondered if this was possible to do with only 1 calculation step. Thanks to the modulus that worked out nicely. :)

### Test:

$perl hue.pl 0 182 255 197$ perl hue.pl 127 247 103
110
$perl hue.pl 0 0 1 240$ perl hue.pl 255 165 245
307

• comparing to the middle value instead of the maximum shaved some bytes. (== versus >) Aug 28, 2015 at 9:35

# R, 125 bytes

Very similar to beaker's Octave solution. Floating point output.

## Code:

h=function(x){
o=seq(3)[order(-x)];
y=c(60*c(6*(o[3]!=3),2,4)[o],x[o]);
return((y[1]-y[2])*(1+(y[4]-y[5])/(y[4]-y[6]))/2+y[2]);
}


## Examples:

> h(c(0,182,255))
[1] 197.1765
> h(c(127,247,103))
[1] 110
> h(c(0,0,1))
[1] 240
> h(c(255,165,245))
[1] 306.6667


# Python, 154 bytes

def h(c):r=c[:];c.sort();c=c[::-1];x,y,z=c;i,j=[120if n==r[1]else 240if n==r[2]else 0if z==r[2]else 360for n in[x,y]];print ((i-j)*(1+(x-y+0.)/(x-z))/2)+j


Accepts a list of values. Not sure if this can be broken down further. Here it is ungolfed:

def hue(color):
rgb=color[:]  # copy list
color.sort()  # sort list
color=color[::-1]  # reverse sort
x,y,z=color   # pull out x,y,z

# The line
#   i,j=[120if n==r[1]else 240if n==r[2]else 0if z==r[2]else 360for n in[x,y]]
# is basically the following, twice, once for x/hx and the second time for y/hy

if x==rgb[1]: # if x is green
hx = 120
else:
if x==rgb[2]: # if x is blue
hx = 240
else:
if z==rgb[2]: # if z is blue and x is red
hx = 0
else:       # if x is red and y is blue
hx = 1

print ((hx-hy)*(1+(x-y+0.)/(x-z))/2)+hy  # calculate, print


# JavaScript 108

Alternate method.

function H(r,g,b){a=[r,g,b].sort(),M=a[2],c=M-a[0],h=M==r?(g-b)/c%6:M==g?(b-r)/c+2:(r-g)/c+4
return h*60|0;}


JavaScript 194

Using the example method.

Array.prototype.i=[].indexOf
function H(r,g,b,a){a=[r,g,b].sort(),i=[a.i(r),a.i(g),a.i(b)],x=[i[2]?360:0,120,240],hx=x[i.i(2)]|0,hy=x[i.i(1)]|0
return (hx-hy)*(1+(a[2]-a[1])/(a[2]-a[0]))/2+hy|0}

var input = document.getElementById("input").innerHTML;
var output = document.getElementById("output");
var html = "";

input.replace(/(\d+)\,(\d+)\,(\d+)/g, function(m, r, g, b) {
html += H(r, g, b) + "\n";
});

output.innerHTML = html;
<pre id="input">
0,182,255
127,247,103
0,0,1
255,165,245
</pre>

<pre id="output">

</pre>