32
\$\begingroup\$

Given an input of a color in #rrggbb hex format, output its RGB complement in the same format.

The RGB complement R2G2B2 of any color R1G1B1 is defined as the color with R2 value 255 - R1, B2 value 255 - B1, and G2 value 255 - G1.

Hex digits may be either in uppercase (#FFAA20) or lowercase (#ffaa20). The case of the input and output need not be consistent (so you may take input in lowercase but output in uppercase, and vice versa).

Since this is , the shortest code in bytes wins.

Test cases (note that since giving your program/function its own output should result in the original input (it is involutory), the test cases should work in both directions):

In/Out   Out/In
----------------
#ffffff  #000000
#abcdef  #543210
#badcab  #452354
#133742  #ecc8bd
#a1b2c3  #5e4d3c
#7f7f80  #80807f
\$\endgroup\$
3
  • 2
    \$\begingroup\$ I'm sorry, but sRGB doesn't work that way. You should convert to linear space first, which hex-codes aren't in. \$\endgroup\$ Commented Jan 1, 2016 at 7:38
  • 2
    \$\begingroup\$ @JanDvorak Oh well. The state of the challenge will reflect my ignorance, then, since I can't really change it now. :P \$\endgroup\$
    – Doorknob
    Commented Jan 1, 2016 at 14:42
  • 2
    \$\begingroup\$ Averaging two values in sRGB could be a decent separate challenge, though. sRGB = RGB^0.45 over most of the range, but linear near the bottom of the range. \$\endgroup\$ Commented Jan 1, 2016 at 14:46

37 Answers 37

1
2
0
\$\begingroup\$

R, 62 bytes

f=function(a)sprintf('#%06x',(8^8-1)-strtoi(substr(a,2,7),16))
\$\endgroup\$
0
\$\begingroup\$

PowerShell, 48 bytes

param($a)"#{0:x6}"-f(16MB-1-("0x"+$a.Trim('#')))

Necessarily takes input via param($a) as a string, delimited with ' or ", since C:\Tools\Scripts\Golfing> .\complementary-colors #a1b2c3 on the PowerShell command line will treat #a1b2c3 as a comment and summarily ignore it.

Left-to-right, the "#{0:x6}"-f(...) formats our output calculations back into hexadecimal with a guaranteed 6 characters (to account for input #ffffff). Inside the parens, we subtract our input number from 0xffffff. We do this by leveraging the fact that PowerShell parses hexadecimal numbers in format 0xNNN, so we construct a proper-format hex number from our input number $a. (Note that concatenation plus .Trim() is shorter than .Replace() here by one byte.) We also leverage the MB unary operator via 16MB-1 to construct 16777215 instead of 0xffffff.

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

TeaScript, 24 bytes

"#"+S(8**8-1-xS1)t16))x6

Bugs in the interpreter aren't letting me get this shorter :(

Try it online

\$\endgroup\$
1
  • \$\begingroup\$ Downvote explanation? It works for all the test cases \$\endgroup\$
    – Downgoat
    Commented Jan 1, 2016 at 17:51
0
\$\begingroup\$

PHP, 37 bytes

printf('#%06x',8**8-1-hexdec($argn));

Try it online!

Or if you prefer to be more bit-wise (and byte-foolish) about it:

PHP, 38 bytes

printf('#%06x',~hexdec($argn)&8**8-1);

Try it online!

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

Thunno 2, 4 bytes

kfḲṆ

Try it online!

Thunno 2 j, 11 bytes

ḣ²Hɠ⁻_Ḥ2ṛ'#

Try it online!

Explanation

kfḲṆ  # Implicit input
kf    # Hexadecimal characters: "0123456789ABCDEF"
  Ḳ   # Bifurcate: duplicate and reverse
   Ṇ  # Transliterate: [0-9A-F] -> [F-A9-0]
      # Implicit output
ḣ²Hɠ⁻_Ḥ2ṛ'#  '# Implicit input
ḣ             # Remove the leading "#"
 ²            # Split into pairs
  H           # Convert each from hexadecimal
   ɠ⁻_        # Subtract each from 255
      Ḥ       # Convert each to hexadecimal
       2ṛ     # Pad with 0s to length 2
         '#  '# Push "#" to the stack
              # Implicit output of joined stack
\$\endgroup\$
0
\$\begingroup\$

Ruby, 31 bytes

->s{"#%6x"%(8**8-1-s[1..].hex)}

Attempt This Online!

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

05AB1E, 6 bytes

15Ýh‡

Try it online or verify all test cases.

Or with the more straight-forward approach (15 bytes):

ćs2ôH₅αh2jð0:J«

Try it online or verify all test cases.

Explanation:

15Ý         # Push a list in the range [0,15]
   h        # Convert each integer to a hexadecimal character
    Â       # Bifurcate this list; short for Duplicate & Reverse copy
     ‡      # Transliterate the (implicit) input-string using these two lists
            # (after which the result is output implicitly)
ć           # Extract head of the (implicit) input-string; push remainder-string and
            # first item separately to the stack
s           # Swap so the remainder-string is at the top
 2ô         # Split it into pairs
        H   # Convert each string in the triplet from hexadecimal to an integer
         ₅α # Take the absolute difference with 255
        h   # Convert it back to hexadecimal
   2jð0:    # Pad leading 0s to single hexadecimal characters if necessary:
   2j       #  Pad potential leading spaces to make all strings of length 2
     ð0:    #  Then replace all spaces with 0s
 J          # Join the triplet of pairs back to a string
«           # Append it back to the "#" that's on the stack
            # (after which the result is output implicitly)
\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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