13
3
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
13
3
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
14
$_=?#+"%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
16
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:
Sample run:
c:\a\ruby>rgb2hex
255 100 0
#FF6400
This is genius! – Albert Renshaw – 2015-10-07T00:01:33.737
6
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$
1This is missing the pound sign (#) required per the sample outputs in the question. – Iszi – 2013-11-12T01:51:20.210
5
Thanks to @manatwork for pointing out
ForEach-Object
can be used in place of afor
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)
}
)
Make the loop foreach($i in 1,2,3)
to reduce it to 68 characters. – manatwork – 2013-11-12T14:02:25.240
@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! – Iszi – 2013-11-13T15:16:10.500
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.)
@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! – Iszi – 2013-11-13T15:24:01.457
Probably some version incompatibility. http://i.stack.imgur.com/xvTAT.png Hopefully your even shorter code will work everywhere.
– manatwork – 2013-11-13T15:30:01.740@manatwork Which version are you using? $PSVersionTable.psversion
Also, I'm not sure about compatibility for this script with 3.0. I seem to recall they changed the way variables are scoped by default, so calling $1
, $2
, or $3
from outside the function in which they were created might not work without some additional code. – Iszi – 2013-11-13T15:49:29.883
2, 0, -1, -1? (Now I realize I never seen a PowerShell version number before.) http://i.stack.imgur.com/mBwvT.png
– manatwork – 2013-11-13T15:56:51.410Apparently, in some cases, foreach
is not translated as an alias to ForEach-Object
- it's its own loop construct. http://superuser.com/a/675488/50086
I was about to comment here, but then ended up writing my own implementation after noticing that the task is fairly trivial. You can at least drop the parentheses and the 0 around the Read-Host
. +$foo
is the same as (0+$foo)
(a trick I shared in Tips for golfing in PowerShell, too :)). You can then drop the quotes around $_
as well. Which then brings you down to 46.
2Oh, dang. You can get this to 41 by using -join
: '#'+-join(1..3|%{"{0:X2}"-f+(read-host)})
. – Joey – 2013-11-18T11:59:17.663
4
(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
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
#!/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'> </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:
Where you could roll the mousewheel to change values (with shift key holded for step by 15)...
Added a *more unorthodox method* : – F. Hauri – 2015-10-06T16:47:49.330
Lol. That inner loop is indeed shockingly unorthodox. – manatwork – 2015-10-06T16:55:35.303
@manatwork thanks, I find d+=${c[$b$a 0x10]}
something sexy! – F. Hauri – 2015-10-06T16:57:07.227
1... or maybe d+=${c[$b$a 020]}
will do the job and look nice – F. Hauri – 2015-10-06T17:01:48.440
Actually the terminating newline was not requested and only “#” needs escaping, so printf \#%02X%02X%02X
is enough. – manatwork – 2013-11-09T16:35:24.430
3
perl -nE 'say"#",map{unpack H2,chr}split'
It's hard to make such a short program unorthodox, but I think this works.
I like this answer :) a few more and I think I might settle on this if nothing better rolls around. – Quillion – 2013-11-07T18:51:29.533
Cool! Just an unpack
question: can you make the hexadecimal a..f uppercase, like in the question? – manatwork – 2013-11-07T18:52:46.147
@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. – breadbox – 2013-11-07T19:28:19.263
Thank you, @breadbox. Those tricky little pack
and unpack
never get into my coding style. So its unorthodox enough for me. – manatwork – 2013-11-07T19:35:54.677
Wrong count. This make 30 char! – F. Hauri – 2013-11-09T19:22:16.273
@F.Hauri The -n
option counts as one character, so the total is 31. The rules for counting option characters are described here: http://meta.codegolf.stackexchange.com/questions/273/on-interactive-answers-and-other-special-conditions/274#274.
3
"#"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"
Will provide explanation on request. If you can figure it out I'd rather not bother – Cruncher – 2013-11-07T21:23:45.650
3
perl -ne 'printf"#"."%02x"x3,split'
13 31 133
#0d1f85
Sorry, it's not as sexy than using unpack
, but shorter!
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
3
trace("#"+(72<<16|61<<139|b).toString(16));
Output: #483D8B
Can you not drop a lot of white space here? I don't know Action Script, but they don't look required – Cruncher – 2013-11-12T19:47:15.347
@Cruncher yeah sorry, one of my first answers here. – Ilya Gazman – 2013-11-12T20:53:19.213
2Kill the semicolon at the end to save a char – Doorknob – 2013-11-20T19:35:36.917
2
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
Wait, readf
? Shouldn't that be scanf
? – breadbox – 2013-11-07T21:39:21.460
@breadbox ah yeah I spent too much time in D; either way no difference in char count – ratchet freak – 2013-11-08T12:46:34.020
2
: D 0 <<# # # #> TYPE #>> ; 35 EMIT HEX SWAP ROT D D D DECIMAL
doesn't work for 1 1 1 which should output #010101 – ratchet freak – 2013-11-08T12:49:29.237
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? – Darren Stone – 2013-11-08T16:33:37.113
2
[#]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
(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
2There are not enough dc
answers on this website. – breadbox – 2013-11-09T19:53:43.843
2
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.
Nice one, but fails on the 3rd sample posted in the question. – manatwork – 2013-11-11T11:09:14.480
Ah, good call. Fixed. – Casey Chu – 2013-11-11T11:22:42.013
2Using eval('(('+DEC.replace(/ /g,'<<8)+'))
instead of eval('256*(256*('+DEC.replace(/ /g,')+'))
let you save 5 chars! – F. Hauri – 2013-11-12T12:03:46.410
2
'#'+-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.
Nice work! Shows I still have much to learn about golfing! – Iszi – 2013-11-17T18:39:02.470
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
. – Joey – 2013-11-17T20:12:32.930
2
That's it. Use the built in.
rgb(r,g,b,m=255)
2
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
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"
– AdmBorkBork – 2015-11-02T14:18:30.457
@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 – blabb – 2015-11-02T17:23:14.267
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. – AdmBorkBork – 2015-11-02T17:34:39.407
1
main(){int a,b,c;scanf("%d%d%d",&a,&b,&c);printf("#%02X%02X%02X",a,b,c);}
Boring C program - very orthodox.
doesn't work with a b or c smaller than 16 – ratchet freak – 2013-11-07T20:09:38.617
Changed %X to %02X. – Ian James – 2013-11-07T20:59:33.613
1
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?
Maybe use format strings? '%02x' seems to be what everyone else has done. – jqblz – 2015-10-07T00:58:45.993
1
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".)
1
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.
1
'#{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
1
\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
1
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 #
Bonus:
To convert it back use this:
blsq ) "#483d8b"[-2cob6
{72 61 139}
0
function h(i){x=(i*=1).toString(16);return 16>i?"0"+x:x}function c(r,g,b){return"#"+h(r)+h(g)+h(b)}
#!/usr/bin/smjs
function h(i){x=(i*=1).toString(16);return 16>i?"0"+x:x}
function c(r,g,b){return"#"+h(r)+h(g)+h(b)}
if (typeof(arguments[2]) != "undefined" )
print(c(arguments[0],arguments[1],arguments[2]));
var line;
while (line=readline()) {
var a=line.split(" ");
print(c(a[0],a[1],a[2]));
};
rgb.js 14 15 16 <<< $'15 16 17\n16 17 18'
#0e0f10
#0f1011
#101112
function h(i){x=(i*=1).toString(16);return 16>i?"0"+x:x}
function c([r,g,b]){return"#"+h(r)+h(g)+h(b)}
function d(){o.innerHTML="";t.value.split("\n").forEach(
function(l){o.innerHTML+=c(l.split(" "))+"<br>"; })};d()
<textarea id="t" onkeyup="d()">72 61 139
75 0 130
0 255 127</textarea><div id="o"></div>
1You are multiplying i by 1 twice. Better do i*=1
once. And choose a different name for the local variable, so you can leave out the var
keyword. I don't have smjs
, but function h(i){x=(i*=1).toString(16);return 16>i?"0"+x:x}function c(r,g,b){return"#"+h(r)+h(g)+h(b)}
should do the same in 99 characters. – manatwork – 2013-11-11T11:19:58.120
@manatwork smjs
is the binary tool from spidermonkey, also available as standard Debian packakge.
Oops. Actually I know+use+enjoy that interpreter, but I always met it with then name js
. – manatwork – 2013-11-11T14:53:39.940
0
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
0
alert('#'+(r<<16|g<<8|b).toString(16).padStart(6,'0'))
You may want to place a #
before your language name and byte count to make it a header. Also, is this ES6? – jqblz – 2015-10-07T02:22:17.183
0
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"
0
f = StringJoin["#", IntegerString[#, 16, 2]] &
rgbs = {{72, 61, 139}, {75, 0, 130}, {0, 255, 127}}
f /@ rgbs // Column
#483d8b
#4b0082
#00ff7f
0
(format()"#~@{~2,'0x~}"#1=(read)#1##1#)
Read three integers, return a string.
0
h=>'#'+h.split` `.map(x=>(x<16?0:'')+(x*1).toString(16)).join``
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)
– Mwr247 – 2015-10-06T18:47:43.650
1Also, 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. – Mwr247 – 2015-10-06T18:49:04.337
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
. – Mwr247 – 2015-10-06T18:58:32.660
This currently returns #7261139
instead of #483D8B
for the first test case. – Dennis – 2015-10-06T21:24:09.817
0
'#'+''.join([hex(int(i))[2:].upper() for i in input()])
0
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
16
Our FAQ says All questions on this site... should have an objective primary winning criterion, so that it is possible to indisputably decide which entry should win.. Shortest is objective, but "most unorthodox" is not. Also, the [tag:code-golf] tag should be used only if the winning condition is just the shortest code; and the [tag:code-challenge] tag should be used only if the [tag:code-golf] tag isn't.
– Peter Taylor – 2013-11-07T22:57:00.160and accept the winner before some time (in this case, wasn't even 24h) kind of discourages further contributions... – woliveirajr – 2013-11-08T11:11:34.767
@PeterTaylor Sorry I will make sure to read the guidlines from now on :( I guess you are right unorthodox is very vague – Quillion – 2013-11-08T13:55:25.563