13
\$\begingroup\$

Given three integers rgb, output hexadecimal representation as a string.

Input:          Output:
72 61 139       #483D8B
75 0 130        #4B0082
0 255 127       #00FF7F

Shortest most unorthodox code wins

\$\endgroup\$

32 Answers 32

14
\$\begingroup\$

Ruby: 19 characters

$_=?#+"%02X"*3%$F

Sample run:

bash-4.1$ ruby -pae '$_=?#+"%02X"*3%$F' <<< '72 61 139'
#483D8B

bash-4.1$ ruby -pae '$_=?#+"%02X"*3%$F' <<< '75 0 130'
#4B0082

bash-4.1$ ruby -pae '$_=?#+"%02X"*3%$F' <<< '0 255 127'
#00FF7F
\$\endgroup\$
16
\$\begingroup\$

Ruby

I was going more for the "unorthodox" part. ;)

10;a=    gets.   split
.  map  {|       x|  #x
"%02X"  %(  x.   to_i)
}; $>   <<   ?#  <<  a[
00  ..   1+2].   join;

The font (on my web browser) is a bit tall, so it looks distorted, but it looks better in Courier New:

image

Sample run:

c:\a\ruby>rgb2hex
255 100 0
#FF6400
\$\endgroup\$
  • \$\begingroup\$ This is genius! \$\endgroup\$ – Albert Renshaw Oct 7 '15 at 0:01
6
\$\begingroup\$

q/k (3 chars)

Not exactly unorthodox but quite short

4h$

Example

q)4h$ 72 61 139
0x483d8b

To match the output format in the question exactly, we can do (for 9 chars):

"#",/$4h$
\$\endgroup\$
  • 1
    \$\begingroup\$ This is missing the pound sign (#) required per the sample outputs in the question. \$\endgroup\$ – Iszi Nov 12 '13 at 1:51
5
\$\begingroup\$

PowerShell: 71 52 51 41

Thanks to @manatwork for pointing out ForEach-Object can be used in place of a for loop.
Thanks to @Joey for pointing out that I could use -join on the loop output, instead of having to put it into variables.

Golfed code:

'#'+-join(1..3|%{"{0:X2}"-f+(read-host)})

Note:

There's no error checking here for invalid inputs. The script will happily take 256, 4096, and 65536 as inputs, then output #100100010000 (which obviously won't work as RGB).

Ungolfed, with comments:

# Put a hashtag in front of the output.
'#'+

# Join the nested code into one string.
-join(

    # Pipe 1..3 to ForEach-Object to run a loop three times.
    1..3|%{

        # Take user input and format it as hex, with minimum two digits in output.
        "{0:X2}"-f+(read-host)
    }
)
\$\endgroup\$
  • \$\begingroup\$ Make the loop foreach($i in 1,2,3) to reduce it to 68 characters. \$\endgroup\$ – manatwork Nov 12 '13 at 14:02
  • \$\begingroup\$ @manatwork I don't think that's the proper syntax for a foreach in PowerShell. (At least, I haven't been able to get some test runs to work.) However, using the right syntax, a built-in alias, and another PowerShell shortcut I recently discovered, I think I've got something better, shaving another 12 characters off your suggestion. (1..3)|%{...} (Insert bracketed statement from existing script in place of the ellipsis.) I still need to fully test this in the script, but thanks for pointing me in that direction! \$\endgroup\$ – Iszi Nov 13 '13 at 15:16
  • \$\begingroup\$ No idea whether it's the proper syntax or not, but the SS64 reference for foreach mentions it and it works for me. (No idea about the version. The one which came with Windows 7.) \$\endgroup\$ – manatwork Nov 13 '13 at 15:20
  • \$\begingroup\$ @manatwork That's interesting. I'd like to dig around and figure out what's wrong with that some more (I was getting "unexpected token 'in'..." errors.) some other time. It's possible the SS64 article was written for a different version of PowerShell - I'm not sure. For now, I've confirmed that (1..3)|% works and brings the script down to 56 characters. I'll edit that into the answer, and definitely credit you for the idea. Thanks again! \$\endgroup\$ – Iszi Nov 13 '13 at 15:24
  • 2
    \$\begingroup\$ Oh, dang. You can get this to 41 by using -join: '#'+-join(1..3|%{"{0:X2}"-f+(read-host)}). \$\endgroup\$ – Joey Nov 18 '13 at 11:59
4
\$\begingroup\$

bash 22 21 chars

(Thanks @manatwork for 1 char using \ instead of double-quotes)

printf \#%02X%02X%02X 12 12 12 
#0C0C0C

or reading STDIN in a loop: 48 chars:

while read f;do printf "#%02X%02X%02X\n" $f;done <<<$'72 61 139\n75 0 130\n0 255 127'
#483D8B
#4B0082
#00FF7F

Added 2015-10-06: bash (more unorthodox method) 84 83 chars

c=({0..9} {a..f}) d=\#;for b;do for a in / %;do d+=${c[$b$a 020]};done;done;echo $d

I know, it could be 82 chars if 020 where written 16, but I prefer this... Or maybe d+=${c[$b$a 0x10]} which was first post.

hexcolor() {
    local a b c=({0..9} {a..f}) d=\#
    for b ;do
        for a in / % ;do
            d+=${c[$b$a 0x10]}
        done
    done
    echo $d
}
hexcolor 72 61 139
#483d8b
hexcolor 75 0 130
#4b0082
hexcolor 0 255 127
#00ff7f

Another approach

#!/bin/bash
browser=firefox   #  google-chrome iceweasel
url="data:text/html;charset=UTF-8,<html><head></head><body>"
url+="<script type='text/javascript'>
  function h(i){var h=i.toString(16);if(16>1*i)h='0'+h;
  return h};function C(r,g,b){return'\043'+h(r)+h(g)+h(b)};
  function m(){ var r=1.0*R.value; var g=1.0*G.value; var b=1.0*B.value;
   var fore='black';if(384>r+g+b)fore='white';var c=C(r,g,b);
   s.setAttribute('style','background:'+c+';color:'+fore+';');s.innerHTML=c};
  function w(e){console.log(e);var val=e.target.value;var q=1;if(e.shiftKey)
  q=15;if(e.detail){if(e.detail>0){q=0-q;}}else if(0>e.wheelDelta){q=0-q;};
  val=1*val+q;if(val>255)val=255;if(0>val)val=0;e.target.value=val;m(); };
  function k(e){console.log(e);var val=e.target.value;var q=1;if(e.shiftKey)q=
  15;if(e.keyCode==38){val=1*val+q;if(val>255)val=255;e.target.value=val;m();}
  else if(e.keyCode==40){val=1*val-q;if(0>val)val=0;e.target.value=val;m();}};
  function n(){R=document.getElementById('R');G=document.getElementById('G');
    B=document.getElementById('B');s=document.getElementById('s');
    R.addEventListener('DOMMouseScroll',w);R.addEventListener('mousewheel',w);
    G.addEventListener('DOMMouseScroll',w);G.addEventListener('mousewheel',w);
    B.addEventListener('DOMMouseScroll',w);B.addEventListener('mousewheel',w);
  m();};var R, G, B, s;window.onload=n;
  </script><style>div{display:inline-block;width:10em;}</style>
  <div id='s'>&nbsp;</div>"
input="%s:<input type='text' size='5' value='200'"
input+=" onKeyDown='k(event)' onChange='m()' id='%s' />"
for c in R G B ;do
    printf -v add "$input" $c $c
    url+="$add"
  done    
$browser "$url"

This will display a browser window, with:

RGB int 2 hex viewer converter

Where you could roll the mousewheel to change values (with shift key holded for step by 15)...

\$\endgroup\$
  • \$\begingroup\$ Actually the terminating newline was not requested and only “#” needs escaping, so printf \#%02X%02X%02X is enough. \$\endgroup\$ – manatwork Nov 9 '13 at 16:35
  • \$\begingroup\$ Added a more unorthodox method : \$\endgroup\$ – F. Hauri Oct 6 '15 at 16:47
  • \$\begingroup\$ Lol. That inner loop is indeed shockingly unorthodox. \$\endgroup\$ – manatwork Oct 6 '15 at 16:55
  • \$\begingroup\$ @manatwork thanks, I find d+=${c[$b$a 0x10]} something sexy! \$\endgroup\$ – F. Hauri Oct 6 '15 at 16:57
  • 1
    \$\begingroup\$ ... or maybe d+=${c[$b$a 020]} will do the job and look nice \$\endgroup\$ – F. Hauri Oct 6 '15 at 17:01
3
\$\begingroup\$

Perl, 31 characters

perl -nE 'say"#",map{unpack H2,chr}split'

It's hard to make such a short program unorthodox, but I think this works.

\$\endgroup\$
  • \$\begingroup\$ I like this answer :) a few more and I think I might settle on this if nothing better rolls around. \$\endgroup\$ – Quillion Nov 7 '13 at 18:51
  • \$\begingroup\$ Cool! Just an unpack question: can you make the hexadecimal a..f uppercase, like in the question? \$\endgroup\$ – manatwork Nov 7 '13 at 18:52
  • \$\begingroup\$ @manatwork I tried to find a way to do it inside of unpack, but no luck. One way is to use sprintf instead of unpack, but that's longer and completely orthodox. The other way is to just modify the string to uppercase : map{uc unpack H2,chr}, at a cost of three characters. \$\endgroup\$ – breadbox Nov 7 '13 at 19:28
  • \$\begingroup\$ Thank you, @breadbox. Those tricky little pack and unpack never get into my coding style. So its unorthodox enough for me. \$\endgroup\$ – manatwork Nov 7 '13 at 19:35
  • \$\begingroup\$ Wrong count. This make 30 char! \$\endgroup\$ – F. Hauri Nov 9 '13 at 19:22
3
\$\begingroup\$

Action Script 3 | 43 characters

trace("#"+(72<<16|61<<139|b).toString(16));

Output: #483D8B

\$\endgroup\$
  • \$\begingroup\$ Can you not drop a lot of white space here? I don't know Action Script, but they don't look required \$\endgroup\$ – Cruncher Nov 12 '13 at 19:47
  • \$\begingroup\$ @Cruncher yeah sorry, one of my first answers here. \$\endgroup\$ – Ilya Gazman Nov 12 '13 at 20:53
  • 2
    \$\begingroup\$ Kill the semicolon at the end to save a char \$\endgroup\$ – Doorknob Nov 20 '13 at 19:35
3
\$\begingroup\$

Perl 24 chars

perl -ne 'printf"#"."%02x"x3,split'
13 31 133
#0d1f85

Sorry, it's not as sexy than using unpack, but shorter!

More obscure version:

But if you really prefer to use unpack, then you could:

$==24;s/\d+[\n ]*/{$=-=8;($&<<$=).do{rand>.5?qw<+>[0]:"|"}}/eg;$_=
pack("N",eval($_.587.202.560));say$1,unpack("H6",$2)if/^(.)(.*)$/s

For sample, it's not the shorter version, but I like it! ( Note the use of rand for randering this :-)

perl -nE '
    $==24;s/\d+[\n ]*/{$=-=8;($&<<$=).
    do{rand>.5?qw<+>:"|"}}/eg;$_=pack(
    "N",eval($_.587.202.560) );say $1,
    unpack("H"."6",$2) if /^(.)(.*)$/s
  ' <<< $'72 61 139\n75 0 130\n0 255 127'
#483d8b
#4b0082
#00ff7f
\$\endgroup\$
3
\$\begingroup\$

><> 103 60

"#"or>1[:82*%:}-82*,86*+:"9"v
    ;^?l ]o+*7)"9":+*68o+*7)<

Made use of the wasted white space, and moved some code into it

Run with command line inputs:

python fish.py generateHex.fish -v 255 36 72

output: "#FF2448"

\$\endgroup\$
  • \$\begingroup\$ Will provide explanation on request. If you can figure it out I'd rather not bother \$\endgroup\$ – Cruncher Nov 7 '13 at 21:23
2
\$\begingroup\$

Forth, 62 characters

: D 0 <<# # # #> TYPE #>> ; 35 EMIT HEX SWAP ROT D D D DECIMAL
\$\endgroup\$
  • \$\begingroup\$ doesn't work for 1 1 1 which should output #010101 \$\endgroup\$ – ratchet freak Nov 8 '13 at 12:49
  • \$\begingroup\$ Hi @ratchetfreak. It works for me. Just tested with gforth. Giving it 1 1 1 outputs #010101. Any other values 0-255 also work. What environment or forth are you using? \$\endgroup\$ – Darren Stone Nov 8 '13 at 16:33
2
\$\begingroup\$

C (67 chars no main boilerplate)

int r,g,b;
scanf("%d %d %d",&r,&b,&g);
printf("#%06x",r<<16|g<<8|b);

the bog standard printf & bit twiddler usage

\$\endgroup\$
  • \$\begingroup\$ Wait, readf? Shouldn't that be scanf? \$\endgroup\$ – breadbox Nov 7 '13 at 21:39
  • \$\begingroup\$ @breadbox ah yeah I spent too much time in D; either way no difference in char count \$\endgroup\$ – ratchet freak Nov 8 '13 at 12:46
2
\$\begingroup\$

Dc: 35 32 characters

[#]n16o?ShShSh[Lhd16/n16%n]ddxxx

Sample run:

bash-4.1$ dc -e '[#]n16o?ShShSh[Lhd16/n16%n]ddxxx' <<< '72 61 139'
#483D8B

bash-4.1$ dc -e '[#]n16o?ShShSh[Lhd16/n16%n]ddxxx' <<< '75 0 130'
#4B0082

bash-4.1$ dc -e '[#]n16o?ShShSh[Lhd16/n16%n]ddxxx' <<< '0 255 127'
#00FF7F

Dc: 27 24 characters

(But needs the input numbers on separate lines.)

[#]n16o[?d16/n16%n]ddxxx

Sample run:

bash-4.1$ dc -e '[#]n16o[?d16/n16%n]ddxxx' <<< $'72\n61\n139'
#483D8B

bash-4.1$ dc -e '[#]n16o[?d16/n16%n]ddxxx' <<< $'75\n0\n130'
#4B0082

bash-4.1$ dc -e '[#]n16o[?d16/n16%n]ddxxx' <<< $'0\n255\n127'
#00FF7F
\$\endgroup\$
  • 2
    \$\begingroup\$ There are not enough dc answers on this website. \$\endgroup\$ – breadbox Nov 9 '13 at 19:53
2
\$\begingroup\$

JavaScript, 89 chars

console.log('#' + ('00000' + eval('256*(256*(' + DEC.replace(/ /g, ')+')).toString(16)).slice(-6))

Converts 72 61 139 to 256*(256*(72)+61)+139 and evals it.

\$\endgroup\$
  • \$\begingroup\$ Nice one, but fails on the 3rd sample posted in the question. \$\endgroup\$ – manatwork Nov 11 '13 at 11:09
  • \$\begingroup\$ Ah, good call. Fixed. \$\endgroup\$ – Casey Chu Nov 11 '13 at 11:22
  • 2
    \$\begingroup\$ Using eval('(('+DEC.replace(/ /g,'<<8)+')) instead of eval('256*(256*('+DEC.replace(/ /g,')+')) let you save 5 chars! \$\endgroup\$ – F. Hauri Nov 12 '13 at 12:03
2
\$\begingroup\$

PowerShell, 45

'#'+-join(-split(read-host)|%{'{0:X2}'-f+$_})

Or, if it can be used by piping in the data, you can just use

'#'+-join(-split"$input"|%{'{0:X2}'-f+$_})

which brings it down to 42.

\$\endgroup\$
  • \$\begingroup\$ Nice work! Shows I still have much to learn about golfing! \$\endgroup\$ – Iszi Nov 17 '13 at 18:39
  • \$\begingroup\$ Oh, your idea with the variables was clever too; would have never crossed my mind. It just so happens that it's longer than my usual favourite: -split and -join. \$\endgroup\$ – Joey Nov 17 '13 at 20:12
2
\$\begingroup\$

powershell 37

saved one byte thanks to TimmyD

cat rgb2hex.ps1
$args|%{$o+="{0:X2}"-f[byte]$_};"#$o"
wc -c rgb2hex.ps1
38 rgb2hex.ps1
powershell -f .\rgb2hex.ps1 72 61 139
#483D8B
powershell -f .\rgb2hex.ps1 0 255 127
#00FF7F
\$\endgroup\$
  • \$\begingroup\$ You can save a couple bytes by getting rid of the [byte] since we're given the input as integers, and edit your output to be "#$o" -- that gives 31 bytes for $args|%{$o+="{0:X2}"-f$_};"#$o" \$\endgroup\$ – AdmBorkBork Nov 2 '15 at 14:18
  • \$\begingroup\$ @TimmyD dont know if removing [byte] works correctly in all version in a version in which i tested (iirc 2.0 in xp ) without [byte] it was not concatenating as hex but as ints ie 72 61 139 was #7261139 not #483d8b "#$o" inside quotes isnt a string literal but evaluated string nice to know thanks comments about hex conversion will be appreciated \$\endgroup\$ – blabb Nov 2 '15 at 17:23
  • \$\begingroup\$ It's apparently a difference between PowerShell v2 and v3 -- must be something in how the corresponding .NET version handles hexadecimal conversion, but I can't find documentation on it. \$\endgroup\$ – AdmBorkBork Nov 2 '15 at 17:34
2
\$\begingroup\$

R, 16 bytes

That's it. Use the built in.

rgb(r,g,b,m=255)
\$\endgroup\$
1
\$\begingroup\$

C, 67 73 Characters (65 Chars excluding main)

main(){int a,b,c;scanf("%d%d%d",&a,&b,&c);printf("#%02X%02X%02X",a,b,c);}

Boring C program - very orthodox.

\$\endgroup\$
  • \$\begingroup\$ doesn't work with a b or c smaller than 16 \$\endgroup\$ – ratchet freak Nov 7 '13 at 20:09
  • \$\begingroup\$ Changed %X to %02X. \$\endgroup\$ – Ian James Nov 7 '13 at 20:59
1
\$\begingroup\$

Python 2.7 (80 Characters)

x=lambda y: ("0"+hex(int(y))[2:])[-2:]
print "#"+''.join(map(x,input().split()))

I'm looking for a better way to handle the single digit hex values. Any ideas?

\$\endgroup\$
  • \$\begingroup\$ Maybe use format strings? '%02x' seems to be what everyone else has done. \$\endgroup\$ – bkul Oct 7 '15 at 0:58
1
\$\begingroup\$

Befunge-98, 45 characters

Bleh, duplicated code. Oh well. Just a straightforward implementation of radix conversion.

"#",v
7*+,>#@&:97+/"0"+:"9"`7*+,97+%"0"+:"9"`

Sample run

% cfunge tohex.98 <<<'72 61 139'
#483D8B
% cfunge tohex.98
#75 0 130
4800820 255 127
00FF7F

(Note: prints '#' before reading input---the task doesn't forbid this; given three numbers on stdin it produces the right output on stdout. It also doesn't bother with newlines, and as you can see it doesn't add '#' properly when run "interactively".)

\$\endgroup\$
1
\$\begingroup\$

Game Maker Language, 175 (Error at position 81)

Prompts for 3 to 9-digit RGB. Returns hexadecimal with GML hexadecimal sign, $

d=get_string('','')if(d=='')e=""else e="00"h="0123456789ABCDEF"while(d!=''){b=d&255i=string_char_at(h,byte div 16+1)l=string_char_at(h,byte mod 16+1)e+=i+l;d=d>>8}return '$'+e

Make this a script. Also, compile with uninitialized variables treated as 0.

Source

\$\endgroup\$
1
\$\begingroup\$

Gema, 93 characters

\B=@set{x;0123456789abcdef}\#
<D>=@substring{@div{$1;16};1;$x}@substring{@mod{$1;16};1;$x}
?=

Sample run:

bash-4.3$ gema '\B=@set{x;0123456789abcdef}\#;<D>=@substring{@div{$1;16};1;$x}@substring{@mod{$1;16};1;$x};?=' <<< '0 255 127'
#00ff7f
\$\endgroup\$
1
\$\begingroup\$

Burlsque, 12 bytes (10 bytes for lower-case)

If lower-case is allowed as well then 10 bytes:

psb6\['#+]

Usage:

blsq ) "72 61 139"psb6\['#+]
"#483d8b"

If you desperately need upper-case, add ZZ:

blsq ) "72 61 139"psb6\['#+]ZZ
"#483D8B"

If you don't receive the integers as in a string then go with:

blsq ) {72 61 139}b6\['#+]
"#483d8b"

Explanation:

ps -- parse string
b6 -- to hex
\[ -- concat
'#+] -- prepend #

Try online here.

Bonus:

To convert it back use this:

blsq ) "#483d8b"[-2cob6
{72 61 139}
\$\endgroup\$
1
\$\begingroup\$

Powershell, 28 bytes

'#{0:X2}{1:X2}{2:X2}'-f$args

Test script:

$f = {

"#{0:X2}{1:X2}{2:X2}"-f$args
}

@(
    ,('#483D8B',72, 61, 139)
    ,('#4B0082',75,  0, 130)
    ,('#00FF7F',0 ,255, 127)
) | % {
    $e,$a = $_
    $r = &$f @a
    "$($r-eq$e): $r"
}

Output:

True: #483D8B
True: #4B0082
True: #00FF7F
\$\endgroup\$
0
\$\begingroup\$

Python3.3 @ 60 chars

print("#"+3*"%.2X"%tuple(int(n) for n in input().split())) 

Couldn't resist:

[dan@danbook:code_golf/int_to_hex]$ python3.3 int_to_hex.py
176 11 30
#B00B1E
\$\endgroup\$
0
\$\begingroup\$

Clojure 76 Characters

This might be late, for the sake of completeness:

(defn hexy [r g b] (reduce str (cons "#" (map #(format "%02X" %) [r g b]))))

Example calls:

(hexy 0 255 127)
"#00FF7F"
\$\endgroup\$
0
\$\begingroup\$

Mathematica, 40 characters

f = StringJoin["#", IntegerString[#, 16, 2]] &

rgbs = {{72, 61, 139}, {75, 0, 130}, {0, 255, 127}}

f /@ rgbs // Column

#483d8b

#4b0082

#00ff7f

\$\endgroup\$
0
\$\begingroup\$

Common Lisp, 39 characters

(format()"#~@{~2,'0x~}"#1=(read)#1##1#)

Read three integers, return a string.

\$\endgroup\$
0
\$\begingroup\$

Javascript ES6, 63 bytes

h=>'#'+h.split` `.map(x=>(x<16?0:'')+(x*1).toString(16)).join``
\$\endgroup\$
  • \$\begingroup\$ Coincidentally, I ended up writing almost exactly the same thing as you before I saw yours. Very nice =) They're close enough that I won't post mine, but you can save a few bytes on your mapping with this: x=>(x<16?0:'')+x.toString(16) \$\endgroup\$ – Mwr247 Oct 6 '15 at 18:47
  • 1
    \$\begingroup\$ Also, no need to include the r= at the beginning. It still counts as a function even as an anonymous function, since you can invoke it without having to assign anything. \$\endgroup\$ – Mwr247 Oct 6 '15 at 18:49
  • \$\begingroup\$ Whoops. Meant the map to be: x=>(x<16?0:'')+(x*1).toString(16) Yours and my first one there currently give wrong values for x>9. \$\endgroup\$ – Mwr247 Oct 6 '15 at 18:58
  • \$\begingroup\$ This currently returns #7261139 instead of #483D8B for the first test case. \$\endgroup\$ – Dennis Oct 6 '15 at 21:24
0
\$\begingroup\$

Python 2, 40 bytes

s='#';exec's+="%02X"%input();'*3;print s

Reads the input from three separate lines. Abuses exec and string multiplication.

Example usage:

$ python2 rgbint.py
72
61
139
#483D8B

$ python2 rgbint.py
75
0
130
#4B0082

$ python2 rgbint.py
0
255
127
#00FF7F
\$\endgroup\$
0
\$\begingroup\$

Python (55 chars)

'#'+''.join([hex(int(i))[2:].upper() for i in input()])
\$\endgroup\$

protected by Community Oct 6 '15 at 18:47

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.