9
\$\begingroup\$

Given Color codes in CMYK, convert it to RGB value.

Input:
string of 4 integers(ranging from 0-100) separated by space

86 86 0 43
28 14 0 6
0 41 73 4

Output:

#141592
#ABCDEF
#F49043 

Shortest code wins!

HINT: For converting CMYK to RGB you may use formula such as:

Red   = 255 x (1 - Cyan/100)    x (1 - Black/100)   
Green = 255 x (1 - Magenta/100) x (1 - Black/100)   
Blue  = 255 x (1 - Yellow/100)  x (1 - Black/100)   

and use these three variables to get the value in #RRGGBB format

\$\endgroup\$
  • 1
    \$\begingroup\$ Can we take CMYK values as decimals from 0 to 1 or is it required to do 0 to 100? \$\endgroup\$ – HyperNeutrino Jun 30 '17 at 17:39
  • 1
    \$\begingroup\$ Also, are we supposed to input multiple CMYK codes at once or just one and convert it? \$\endgroup\$ – HyperNeutrino Jun 30 '17 at 17:41
  • 7
    \$\begingroup\$ Can we take the input as a list of numbers or does it have to be a delimited string? \$\endgroup\$ – Business Cat Jun 30 '17 at 17:41
  • 7
    \$\begingroup\$ The input / output that you provided doesn't match the formula, also how should we handle the rounding? \$\endgroup\$ – Rod Jun 30 '17 at 18:33
  • 2
    \$\begingroup\$ @Rod It's a bit unclear yet how floating-point inaccuracies should be handled. \$\endgroup\$ – Erik the Outgolfer Jul 1 '17 at 7:33

16 Answers 16

5
\$\begingroup\$

PHP, 90 bytes

<?="#";for($c=explode(" ",$argn);$i<3;)printf("%02X",255*(1-$c[+$i++]/100)*(1-$c[3]/100));

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Python 3, 100 98 bytes

-2 bytes thanks to Rod.

lambda s:'#'+''.join('%02X'%int(.0255*(100-int(i))*(100-int(s.split()[3])))for i in s.split()[:3])

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Golfing the math. o0 Thanks! \$\endgroup\$ – totallyhuman Jun 30 '17 at 18:42
2
\$\begingroup\$

Jelly, 24 bytes

ḲV÷ȷ2ạ1×Ṫ$×255ḞṃØHṙ1¤ṭ”#

A full program which prints the result.

Try it online!

Note: rounding rather than flooring may be used by inserting the two bytes of code +. between 255 and .

How?

ḲV÷ȷ2ạ1×Ṫ$×255ḞṃØHṙ1¤ṭ”# - Main link: list of character, s
Ḳ                        - split at spaces (makes a list of lists of characters)
 V                       - evaluate as Jelly code (makes a list of the decimal numbers)
   ȷ2                    - literal 100
  ÷                      - divide (vectorises to yield [C/100, M/100, Y/100, K/100])
     ạ1                  - absolute difference with 1 -> [1-(C/100),...]
         $               - last two links as a monad:
        Ṫ                -   tail (this is 1-(K/100))
       ×                 -   multiply (vectorises across the other three)
          ×255           - multiply by 255 (vectorises)
              Ḟ          - floor to the nearest integer
                    ¤    - nilad followed by link(s) as a nilad:
                ØH       -   hex-digit yield = "0123456789ABCDEF"
                  ṙ1     -   rotate left by 1 -> "123456789ABCDEF0"
               ṃ         - base decompress (use those as the digits for base length (16))
                      ”# - literal character '#'
                     ṭ   - tack
                         - implicit print
\$\endgroup\$
  • \$\begingroup\$ Another way to round would be _.Ċ instead of +.Ḟ...but the latter is maybe more widely used. \$\endgroup\$ – Erik the Outgolfer Jul 1 '17 at 7:47
2
\$\begingroup\$

Retina, 103 bytes

\d+
$*1;100$*
(1*);\1

1(?=.* (1*))|1
$1
1
51$*
(1{32000})*(1{2000})*1*.
;$#1;$#2
T`d`L`1\d
;B\B|;

^
#

Try it online! Note: This code is very slow, so please don't hammer Dennis's server. Explanation:

\d+
$*1;100$*
(1*);\1

Convert each number to unary and subtract from 100.

1(?=.* (1*))|1
$1

Multiply all the numbers by the last number, which is deleted.

1
51$*

Multiply by 51, so that once we divide by 2000, we get 100 * 100 * 51 / 2000 = 255 as desired.

(1{32000})*(1{2000})*1*.
;$#1;$#2

Divide by 32000 and floor divide the remainder by 2000, thus generating a pair of base 16 values, although sadly themselves still written in base 10.

T`d`L`1\d
;B\B|;

Convert from base 10 to base 16.

^
#

Insert the leading #.

\$\endgroup\$
2
\$\begingroup\$

Java 8, 166 bytes

s->{int i=0,c[]=java.util.Arrays.stream(s.split(" ")).mapToInt(Byte::new).toArray();for(s="#";i<3;)s+=s.format("%02X",(int)(.0255*(100-c[i++])*(100-c[3])));return s;}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Javascript (ES6), 106 bytes

f=
(s,z=s.split` `,k=z.pop())=>'#'+z.map(x=>('0'+(.0255*(100-x)*(100-k)+.5|0).toString(16)).slice(-2)).join``
<input id=i value="28 14 0 6"/><button onclick="o.innerHTML=f(i.value)"/>Go</button>
<pre id=o></pre>

\$\endgroup\$
2
\$\begingroup\$

C++ (gcc), 169 166 bytes

#import<iostream>
#import<iomanip>
#define F(x)int(.0255*(100-x)*(100-k))
int main(){
int c,m,y,k;
std::cin>>c>>m>>y>>k;
std::cout<<"#"<<std::hex<<F(c)<<F(m)<<F(y);
}

Try it online!

Using the optimized formula. Added +.5 to convert CMYK=0 0 0 0 correct to RGB=0xffffff which is not necessary.

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

Python 3, 114 110 108 106 104 bytes

  • @xnor saved 4 bytes: deleted unnecessary code
  • @rod saved 2 bytes: shorter formula
  • saved 2+2 bytes: range[3] as [0,1,2], unwanted [] removed
n=input().split()
print('#'+''.join(hex(int(.0255*(100-int(n[i]))*(100-int(n[3]))))[2:]for i in[0,1,2]))

Try it online!

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

Ruby, 92+1 for -p flag= 93 bytes

gsub(/(.+) (.+) (.+) (.+)/){'#%X%X%X'%[$1,$2,$3].map{|n|255*(1-n.to_i/1e2)*(1-$4.to_i/1e2)}}

Try it online!

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

Perl 5, 58 52 + 1 (-a) = 59 53 bytes

printf"#%2X%2X%2X",map{.0255*(100-$_)*(100-$F[3])}@F

Try it online!

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

dc, 53 bytes

16o?35Pskrsprlpr[Fk100/1r-255*1lk100/-*0k1/nz0<b]dsbx

Try it online!

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

Javascript, 104 bytes

s=>"#"+[0,1,2].map(n=>("0"+((255-2.55*s[n])*(1-s[3]/100)|0).toString(16)).slice(-2),s=s.split` `).join``

Example code snippet:

f=

s=>"#"+[0,1,2].map(n=>("0"+((255-2.55*s[n])*(1-s[3]/100)|0).toString(16)).slice(-2),s=s.split` `).join``

console.log(f("86 86 0 43"))
console.log(f("28 14 0 6"))
console.log(f("0 41 73 4"))

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

q/kdb+, 55 bytes

Solution:

"#",raze{(last($)0x0 vs)each"h"$.0255*x[3]*x 0 1 2}100-

Examples:

q)"#",raze{(last($)0x0 vs)each"h"$.0255*x[3]*x 0 1 2}100-86 86 0 43
"#141491"
q)"#",raze{(last($)0x0 vs)each"h"$.0255*x[3]*x 0 1 2}100-28 14 0 6
"#adcef0"
q)"#",raze{(last($)0x0 vs)each"h"$.0255*x[3]*x 0 1 2}100-0 41 73 4
"#f59042"

Explanation:

Fairly straightforward, stole the 0.0255 trick from other solutions (thanks!). Evaluation is performed right to left.

"#",raze {(last string 0x0 vs) each "h"$ .0255 * a[3] * a 0 1 2}100- / ungolfed
         {                                                     }     / lambda function
                                                                100- / subtract from 100 (vector)
                                                        a 0 1 2      / index into a at 0, 1 and 2 (CMY)
                                                 a[3]                / index into at at 3 (K)
                                                      *              / multiply together
                                         .0255 *                     / multiply by 0.255
                                    "h"$                             / cast to shorts
          (                  ) each                                  / perform stuff in brackets on each list item
                       0x0 vs                                        / converts to hex, 1 -> 0x0001
                string                                               / cast to string, 0x0001 -> ["00", "01"]
           last                                                      / take the last one, "01"
    raze                                                             / join strings together
"#",                                                                 / prepend the hash

Notes:

Rounds numbers by default, would cost 3 bytes (_) to floor instead before casting to short.

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

05AB1E, 18 bytes

$#т/-¤s¨*255*hJ'#ì

Try it online!

-1 thanks to kalsowerus.

Has floating-point inaccuracies, so results might be off-by-one, but the formula in the question is used.

\$\endgroup\$
  • \$\begingroup\$ You can save a byte: $ is just the same as \$\endgroup\$ – kalsowerus Jul 7 '17 at 12:45
  • \$\begingroup\$ @kalsowerus Well, not exactly, but it'd work in this case... \$\endgroup\$ – Erik the Outgolfer Jul 7 '17 at 12:47
  • \$\begingroup\$ Oh right.. I'm not sure which input is input when there would be multiple \$\endgroup\$ – kalsowerus Jul 7 '17 at 12:48
0
\$\begingroup\$

Haskell, 165 bytes

q=(1-).(/100)
x!y=h$ceiling$q x*(q y)*255
f c m y k=concat["#",c!k,m!k,y!k]
h x|x<16=[s!!x]|0<1=(h((x-m)`quot`16))++[s!!m] where m=x`mod`16
s=['0'..'9']++['a'..'f']
\$\endgroup\$
0
\$\begingroup\$

Fortran, 156 bytes

PROGRAM C
REAL,DIMENSION(4,3)::d
READ(*,*)((d(i,j),i=1,4),j=1,3)
WRITE(*,'((A,3(Z2)))')(35,(INT(.0255*(100-d(i,j))*(100-d(4,j))),i=1,3),j=1,3)
END PROGRAM C
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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