互补色


26

给定以#rrggbb十六进制格式输入的颜色,请以相同格式输出其RGB补码。

任意颜色R 1 G 1 B 1的RGB补色R 2 G 2 B 2定义为R 2值为255-R 1,B 2值为255-B 1和G 2值为255-G 1的颜色。

十六进制数字可以是大写(#FFAA20)或小写(#ffaa20)。输入和输出的大小写不必保持一致(因此,您可以使用小写输入,但可以使用大写输出,反之亦然)。

由于这是,因此以字节为单位的最短代码为准。

测试用例(请注意,由于为程序/函数提供自己的输出应导致原始输入(这是 不合理的),因此测试用例应在两个方向上都起作用:

In/Out   Out/In
----------------
#ffffff  #000000
#abcdef  #543210
#badcab  #452354
#133742  #ecc8bd
#a1b2c3  #5e4d3c
#7f7f80  #80807f

2
抱歉,sRGB不能那样工作。你应该转换为线性空间第一,其十六进制代码不在家。
约翰·德沃夏克

2
@JanDvorak哦,很好。那么,挑战的状态将反映出我的无知,因为我现在无法真正改变它。:P
门把手

但是,在sRGB中对两个值求平均可能是一个不错的独立挑战。在大部分范围内,sRGB = RGB ^ 0.45,但在范围底部附近呈线性。
John Dvorak

Answers:


17

Pyth,9 8字节

感谢@isaacg提供了-1个字节!

sXz.HM16

从255减去某种颜色的值等于从15减去其每个十六进制数字。假设数字为16a + b。然后,通过从15中减去其数字而创建的数字的值为16(15-a)+(15-b)= 255-(16a + b)

sXz.HM16     implicit: z=input()
      16      
   .HM        map hex representation over range
   .HM16     '0123456789abcdef'
  z           the input string
 X            Translate characters in x1 present in x2 to reversed x2
              that is, '0' becomes f, '1' becomes 'e', and so on.
              The initial '#' is unchanged.
s             That produced a list, so join into a string by reducing +

在这里尝试。测试套件。


好答案!我借用了您使用'0123456789abcdef'转换为十六进制(而不是dec2hex函数)的想法
Luis Mendo

我认为您的链接不正确。(复制粘贴FTW。
PurkkaKoodari'1

@ Pietu1998糟糕; 我会解决的。
lirtosiast'1

U是不必要的-它隐含填写的M
isaacg '16

6

视网膜,13 10字节

T`w`G-A9-0

该代码分为三部分,以反引号(`)分隔:T指定音译模式,该模式将第二部分中的每个字符替换为第三部分中的相应字符。

w与传统的regex相同\w,或_0-9A-Za-z扩展为_0123456789ABCDEFGH...

GFEDCBA9876543210由于Retina具有逆向扩展的精巧功能,第二部分扩展为。将它们放在一起,我们得到:

_0123456789ABCDEFGH...
GFEDCBA987654321000...
 ^^^^^^^^^^^^^^^^

请注意,最后一个字符0重复进行以适应较长字符串的长度,但是我们只关心十六进制字符(以脱字符号表示)。

感谢MartinBüttner提出了这种方法。

在线尝试测试套件。


4

Marbelous,41个字节

00@0
\\]]\/
-W/\@0
-W
~~
<A+700
+O//]]
+O

在线翻译在这里。输入应为大写。

说明

底部的00]]将获取第一个字符(#),并且将其降至底部并先输出。

前3行是获取所有剩余字符的循环。

首先,我们需要将十六进制数字字符转换为0-15 x -= 48, x -= x > 9 ? 7 : 0(因为'A' - '9'是8)。

要找到补码,我们只需要将每个数字转换x15-x。等效于(对于8位值)(~x)+16 = ~(x-16)

最后,我们必须通过执行将这些数字转换回十六进制数字x += x > 9 ? 7 : 0, x += 48

现在我们有了x -= 48, x -= x > 9 ? 7 : 0, x = ~(x - 16), x += x > 9 ? 7 : 0, x += 48

请注意,如果我们使用第一个三元运算符删除表达式,则输入数字A- F取反后将得到负x。

因此,我们可以将先前的表达式更改为:x -= 48, x -= 16, x = ~x, x += (x > 9 || x < 0) ? 7 : 0, x += 48,等于x -= 64, x = ~x, x += (x > 9 || x < 0) ? 7 : 0, x += 48

上面的代码只是最后一个表达式的实现。-Wx -= 32并且+Ox += 24。由于Marbelous使用无符号的8位算术,条件<A盖两者的情况下x > 9x < 0


您创建了Marbelous吗?
Rɪᴋᴇʀ

@RikerW Marbelous是由包括我在内的多个PPCG用户创建/创建的:请参见此处
es1024

好的。谢谢你让我知道。
Rɪᴋᴇʀ

4

JavaScript ES6,61字节66 68 48 53 64

由于@CᴏɴᴏʀO'Bʀɪᴇɴ,@ NinjaBearMonkey和@nderscore,节省了很多字节

s=>"#"+(1e5+(8**8+~('0x'+s.slice(1))).toString(16)).slice(-6)

利用自动类型广播。修复零会杀死字节数


使用eval(`0x${s.slice(1)}`)代替parseInt
Conor O'Brien

@CᴏɴᴏʀO'Bʀɪᴇɴ一样长吗?
PurkkaKoodari'1

@CᴏɴᴏʀO'Bʀɪᴇɴ谢谢,我用- eval代替了eval,它节省了更多的字节
Downgoat

哦,忘记了自动打字机:D
Conor O'Brien

用input尝试一下#FFFFFF。返回#0
科纳·奥布莱恩

4

的JavaScript ES6,63 58 52 49字节

c=>c.replace(/\w/g,x=>(15-`0x${x}`).toString(16))

感谢nderscore节省11个字节!


-5个字节:c=>"#"+[...c].map(x=>"fedcba9876543210"[+('0x'+x)]).join``
nderscore '16

@nder正好,已经考虑过了:)谢谢。将要使用它,但是带有“ eval”。
nicael '16

1
啊,我c=>c.replace(/\w/g,x=>"fedcba9876543210"[+('0x'+x)])
又有

3

Jolf,17个字节

pq#-w^88C Li1~560
pq                pad
         _Li1     the input, w/out the first char
        C    ~5   parsed as a base-16 integer (~5 = 16)
    w^88          8 ^ 8 - 1 (the magic number)
   -              subtract the parsed input from said number
  #               convert result to hexadecimal
               60 pad the result with 6 0's

在这里尝试!测试套件(使用完整版,现在可以使用。)


3

朱莉娅74 49字节

h->"#"join([hex(15-parse(Int,i,16))for i=h[2:7]])

目前相当长,但这是一个开始。这是一个lambda函数,它接受一个字符串并返回一个字符串。输出将是小写字母,但输入可以是小写字母。

正如Thomas所指出的,从255中减去每个2位数字的颜色分量等于从15中减去十六进制输入中的每个数字。循环遍历输入字符串(不包括前导)#,将15解析后的数字转换为十六进制。我们将所有这些都加入,然后加入a #并称其为好。


3

Japt35 32 22 20 16 15字节

¡Y?(F-XnG)sG :X

说明:

¡                 //Take input and map (shortcut to "Um@"). Input should in the form of "#123456"
 Y?               //if Y is not 0, then return (F-XnG)sG, otherwise last step...
    F-XnG           //Subtract X, converted from hexadecimal (G is 16) to decimal, from 15
          sG        //convert decimal to hexadecimal
             :X   //...otherwise return X unchanged (happens only with #, the first char)

好东西!昨晚我看到了这个,对自己说:“明天我会帮助打高尔夫球的。” 但是到目前为止,您的高尔夫运动比我想像的还要远。:)
ETHproductions '16

2

Perl,30个字节

为包括+1 -p

s/\w/sprintf"%x",15&~hex$&/eg

用法:echo #000000 | perl -p file.pl
echo #000000 | perl -pe 's/\w/sprintf"%x",15&~hex$&/eg'


2

MATL,21字节

35,5Y216,j6L)!16ZA-)h

这使用的语言/编译器版本6.0.0,比挑战更早。

输入数字应为大写。

这已在Octave上执行:

>> matl
 > 35,5Y216,j6L)!16ZA-)h
 >
> #FFAA20
#0055DF

编辑(2016年6月12日)

现在可以在线尝试该代码。逗号需要更换的空间,6L通过4L,以符合该语言的变化。

说明

35,             % number literal: ASCII code of '#'
5Y2             % '0123456789ABCDEF'
16,             % number literal
j               % input string
6L)             % remove first element
!               % transpose
16ZA            % convert from hex to dec
-               % subtract from 16
)               % index into '0123456789ABCDEF' to convert back to hex
h               % prepend 35, which gets automatically converted into '#'

1

Pyth,20个 19字节

感谢xnor 1个字节

%"#%06x"-t^8 8itz16

在线尝试。 测试套件。

说明

  • z 是输入
  • tz 删除 #
  • itz16 解析为十六进制数
  • t^8 8计算8 8 - 1
  • -t^8 8itz16计算8 8-1-输入
  • %"#%06x"-t^2 24itz16 将其格式化为零填充的6个字符的十六进制字符串,并添加 #

2 ^ 24的8 ^ 8怎么样?
xnor

1

Haskell,85个字节

我的第一次提交,可能是最长的(85个字节),但是,您必须从某个地方开始。在Haskell中:

import Numeric;f=('#':).concatMap((flip showHex)"".(15-).fst.head.readHex.(:[])).tail

它使用的是我看到其他人使用的15种技巧的相同减法。

我还尝试将printf与其他技巧一起使用(减去8 ^ 8-1),它可以在ghci中工作,但由于某些原因它无法编译:

g=printf "#%06x" .(8^8-1-).fst.head.readHex.tail

如果有人可以完成这项工作,那就太好了!


欢迎使用编程难题和Code Golf。这些都是很好的答案(比我在Haskell中做的要好!)。但是,对于代码高尔夫球挑战有一种常见的答案格式,该模式可让排行榜代码片段将您的答案放入排行榜。我会为您编辑。您可以接受或拒绝修改。
wizzwizz4 2016年

要回复其他用户的评论,请键入@username
wizzwizz4 2016年

@ wizzwizz4非常感谢您的协助。
lpapez '16

任何时间!您想接受我的一些挑战吗?分析您的椅子和将字符串映射到Hilbert曲线是我的最爱,尽管Hilbert曲线确实很难。
wizzwizz4 2016年

@ wizzwizz4当然,我会看看我能做什么。
lpapez '16

1

Mathematica,69 60字节

"#"<>IntegerString[8^8-#~StringDrop~1~FromDigits~16-1,16,6]&

再次,是字符串处理使我丧命。


1

C,94个字节

t(char*b){for(int i;i=*b;++b)*b=i>96&i<103?150-i:i>64&i<71|i>47&i<54?118-i:i>53&i<58?111-i:i;}

函数接受一个char数组,返回反值。产生大写字母以进行响应。如果有效,该代码会将每个ASCII十六进制字符翻转为其相反的字符,否则将其忽略。


您可以通过i在函数之前全局声明来节省一些空间:i;
Liam

1

𝔼𝕊𝕄𝕚𝕟2,18个字符/ 34个字节

ïē/\w⌿,↪(ḏ-`ᶍ⦃$}”ⓧ

Try it here (Firefox only).

使用挑战后创建的版本。

说明

ïē/\w⌿,↪(ḏ-`ᶍ⦃$}”ⓧ // implicit: ï=input, ḏ=15
ïē/\w⌿,             // replace all alphanumeric chars in ï with:
       ↪(ḏ-`ᶍ⦃$}”ⓧ // (15 - char's decimal form) converted to hex
                    // implicit output

非竞争性解决方案,15个字符/ 29个字节

ïē/\w⌿,↪(ḏ-`ᶍ⦃$}”ⓧ

使用音译。


您还可以添加一个竞争版本,以便我们了解该语言的堆叠方式吗?
lirtosiast 2016年

当然。看到新的编辑。
Mama Fun Roll

很好地使用APL符号
lirtosiast

呵呵,那个符号是最有意义的那个符号/g
Mama Fun Roll

1

Python,96

x=input()
print("#")
for i in range(3):
    print(hex(255-int(x[(1+2*i)]+x[(2+2*i)],16))[2:4])

第一次打高尔夫球,请提出意见:)


允许您要求输入以"quotes"btw为单位,因此input()可以正常工作。您不需要for循环上的换行符和缩进,并且range工作正常。您还可以删除几个空格。
–Rɪᴋᴇʀ16年

int("ff", 16)可以用just代替255
门把手

每个x后是否需要括号内的括号?

0

CJam,16个字节

qA,'G,65>+s_W%er

这相当长,因为CJam处理基本更改的方式有所不同,因此仅进行音译会更短。看我的音译的更多信息,视网膜答案

在线尝试。

说明

q      e# Get the input
A,     e# Push [0 1 ... 8 9]
'G,65> e# Push "ABCDEF"
+s     e# Combine and convert to string
_W%    e# Make a copy and reverse it
er     e# Replace each character in the first string with
       e# the corresponding character in the second

0

Python 3,44个字节

原来我用256^3的话16^6。然后我看到了Pietu1998的8^8,现在此解决方案使用了它。

"#{:06x}".format(8**8-1-int(input()[1:],16))

0

Java,95个 90字节

String f(String v){return v.format("#%06x",0xFFFFFF^Integer.parseInt(v.substring(1),16));}

按位XOR。


0

Bash + tr,35个字节

tr 0-9A-Fa-f fedcba9876543210543210

输出始终为小写。

不幸的是,“ tr”的取值范围不是相反的,因此我不得不将它们拼写清楚。


0

C,147字节

void p(char s[]){char c[3];int i=1;printf("#");while(i<6){strncpy(c,s+i++,2);i++;int x=255-strtol(c,NULL,16);x<10?printf("0%x",x):printf("%x",x);}}

使用strtol从十六进制字符串转换为int,然后从255减去数字以得到如原始帖子所说的赞美。但是,我想知道是否有办法将s范围的字符传递到strtol,这样我就不必浪费一堆字节来复制到新字符串了吗?


我不认为编译器通常会强制执行函数返回并默认将其设置为int,因此您可能会省略void返回类型吗?
利亚姆

0

R,62个字节

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

0

sed,48个字节

y/0123456789ABCDEFabcdef/fedcba9876543210543210/

如果只需要支持一种情况,则为36个字节。


您不需要同时支持小写和大写。
Martin Ender'1

@MartinBüttner这个问题似乎需要在输入中支持这两种情况,但在输出中不需要。就像我的bash + tr解决方案一样,该解决方案在输入上都支持这两种方法,但只写小写的输出。
Glenn Randers-Pehrson'1

0的代码中有一个额外的字符,在9和之间A(字节数正确,但是必须是复制错误)。
hobbs

问题是您可以选择输入和输出是哪种情况。
lirtosiast,2016年

0

PowerShell,48个字节

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

由于在PowerShell命令行上会将其视为注释,因此总会忽略它,因此必须param($a)'或分隔字符串作为输入。"C:\Tools\Scripts\Golfing> .\complementary-colors #a1b2c3#a1b2c3

从左到右,将"#{0:x6}"-f(...)输出计算的格式重新格式化为十六进制,并保证有6个字符(用于输入#ffffff)。在括号内,我们从中减去输入数字0xffffff。我们利用PowerShell解析格式为16进制数这一事实来做到这一点0xNNN,因此我们从输入数构造一个格式正确的十六进制数$a。(请注意,串联加号.Trim().Replace()此处短1个字节。)我们还利用MB一元运算符via 16MB-1构造16777215而不是0xffffff


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.