Cores complementares


26

Dada a entrada de uma cor no #rrggbbformato hexadecimal, imprima seu complemento RGB no mesmo formato.

O complemento RGB R 2 G 2 B 2 de qualquer cor R 1 G 1 B 1 é definido como a cor com o valor R 2 255 - R 1 , valor B 2 255 - B 1 e valor G 2 255 - G 1 .

Os dígitos hexadecimais podem estar em maiúsculas (# FFAA20) ou minúsculas (# ffaa20). As maiúsculas e minúsculas da entrada e da saída não precisam ser consistentes (portanto, você pode receber entradas em minúsculas, mas em maiúsculas e vice-versa).

Como esse é o , o código mais curto em bytes vence.

Casos de teste (observe que, como fornecer ao seu programa / função sua própria saída deve resultar na entrada original (é involutória ), os casos de teste devem funcionar nas duas direções):

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

2
Sinto muito, mas o sRGB não funciona dessa maneira. Você deve converter para o espaço linear de primeira, que hex-códigos não sejam.
— John Dvorak

2
@JanDvorak Oh bem. O estado do desafio refletirá minha ignorância, pois não posso realmente mudar isso agora. : P
— Maçaneta da porta

A média de dois valores no sRGB pode ser um desafio separado decente. sRGB = RGB ^ 0,45 na maior parte do intervalo, mas linear próximo à parte inferior do intervalo.
— John Dvorak

Respostas:


17

Pitão, 9 8 bytes

Obrigado a @isaacg por -1 byte!

sXz.HM16

Subtrair o valor de uma determinada cor de 255 é equivalente a subtrair cada um dos dígitos hexadecimais de 15. Digamos que um número seja 16a + b . Então o valor do número criado subtraindo seus dígitos de 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 +

Experimente aqui . Suíte de teste.


Boa resposta! Eu pedi seu idéia de usar '0123456789abcdef'para converter para hex (em vez de dec2hexfunção)
— Luis Mendo

Acho que seu link está incorreto. ( Copie e cole FTW. )
— PurkkaKoodari

@ Pietu1998 Opa; Eu resolvo isso.
— lirtosiast

O Ué desnecessário - é preenchido implicitamente por M.
— Isaacg

6

Retina, 13 10 bytes

T`w`G-A9-0

Existem três partes no código, separadas por backticks ( `): Tespecifica o modo transliterado, que substitui cada caractere na segunda parte pelo seu caractere correspondente na terceira parte.

wé o mesmo que o do regex tradicional \wou _0-9A-Za-zque é expandido para _0123456789ABCDEFGH....

A segunda parte é expandida para GFEDCBA9876543210, graças à capacidade bacana de Retina de expandir na ordem inversa. Coloque-as umas sobre as outras e obteremos:

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

Observe que o último caractere, 0é repetido para se ajustar ao comprimento da string mais longa, mas nos preocupamos apenas com os caracteres hexadecimais, mostrados por pontos de interpolação.

Agradecemos a Martin Büttner por sugerir essa abordagem.

Experimente o conjunto de testes online.


4

Marbelous, 41 bytes

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

Intérprete online aqui. A entrada deve estar em maiúscula.

Explicação

A 00e ]]na parte inferior vai buscar o primeiro caractere (a #) e ele vai cair para o fundo e ser emitido antes de mais nada.

As 3 primeiras linhas são um loop para buscar todos os caracteres restantes.

Primeiro, precisamos converter os caracteres do dígito hexadecimal para 0-15, fazendo x -= 48, x -= x > 9 ? 7 : 0(já que 'A' - '9'é 8).

Para encontrar o complemento, basta converter todos os dígitos xem 15-x. Isso é equivalente a (para valores de 8 bits) (~x)+16 = ~(x-16).

Finalmente, temos que converter esses números novamente em dígitos hexadecimais, fazendo isso x += x > 9 ? 7 : 0, x += 48.

Então agora nós temos x -= 48, x -= x > 9 ? 7 : 0, x = ~(x - 16), x += x > 9 ? 7 : 0, x += 48.

Observe que, se removermos a expressão com o primeiro operador ternário, os dígitos de entrada A- Fresultarão em um x negativo após a negação.

Assim, podemos alterar a expressão anterior para:, x -= 48, x -= 16, x = ~x, x += (x > 9 || x < 0) ? 7 : 0, x += 48que é igual a x -= 64, x = ~x, x += (x > 9 || x < 0) ? 7 : 0, x += 48.

O código acima é apenas uma implementação da última expressão. -Wé x -= 32e +Oé x += 24. Como o Marbelous usa aritmética de 8 bits não assinada, a condição <Acobre o caso de x > 9e x < 0.


Você criou o Marbelous?
— Rɪᴋᴇʀ

O @RikerW Marbelous foi criado / desenvolvido por vários usuários do PPCG, incluindo eu: Veja aqui .
— es1024

OK. Obrigado por me avisar.
— Rɪᴋᴇʀ

4

JavaScript ES6, 61 bytes 66 68 48 53 64

Economiza alguns bytes graças a @ Cᴏɴᴏʀ O'Bʀɪᴇɴ, @NinjaBearMonkey e @nderscore

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

Aproveita a conversão automática de tipo. Corrigindo os zeros eliminaram a contagem de bytes


Use em eval(`0x${s.slice(1)}`)vez deparseInt
— Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Esse é o mesmo comprimento?
— precisa saber é o seguinte

@ CᴏɴᴏʀO'Bʀɪᴇɴ graças, eu usei - em vez de eval que salvou ainda mais bytes
— Downgoat

Oh, esqueceu-se sobre o tipo de auto seleção de elenco: D
— Conor O'Brien

Experimente com a entrada #FFFFFF. Retorna #0.
— Conor O'Brien

4

JavaScript ES6, 63 58 52 49 bytes

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

Obrigado ao nderscore por salvar 11 bytes!


-5 bytes:c=>"#"+[...c].map(x=>"fedcba9876543210"[+('0x'+x)]).join``
— nderscore 01/01

@ exatamente, pensei sobre isso já :) Obrigado. Estava indo para usá-lo, mas com "eval".
— Nicael

1
ah, eu tenho mais um -6:c=>c.replace(/\w/g,x=>"fedcba9876543210"[+('0x'+x)])
— nderscore 01/01

3

Jolf, 17 bytes

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

Experimente aqui! , Conjunto de testes (use a execução completa, que agora funciona.)


3

Julia, 74 49 bytes

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

Muito tempo no momento, mas é um começo. Esta é uma função lambda que aceita uma string e retorna uma string. A saída estará em minúscula, mas a entrada poderá estar em qualquer um.

Como Thomas observou , subtrair cada componente de cor de 2 dígitos de 255 é equivalente a subtrair cada dígito individual na entrada hexadecimal de 15. Ao fazer um loop sobre a sequência de entrada, excluindo o líder #, convertemos 15 - o dígito analisado em hexadecimal. Juntamos tudo isso e depois aderimos a um #e chamamos de bom.


3

Japt , 35 32 22 20 16 15 bytes

¡Y?(F-XnG)sG :X

Explicação:

¡                 //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)

Agradável! Vi isso ontem à noite e disse a mim mesmo: "Amanhã ajudarei a jogar golfe". Mas agora você já jogou mais longe do que eu pensava ser possível. :)
— ETHproductions

2

Perl, 30 bytes

inclui +1 para -p

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

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


2

MATL , 21 bytes

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

Isso usa a versão 6.0.0 do idioma / compilador, anterior ao desafio.

Os dígitos da entrada devem estar em maiúsculas.

Exemplo

Isso foi executado no Octave:

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

Editar (12 de junho de 2016)

O código agora pode ser experimentado online . As vírgulas precisam ser substituídas por espaços e 6Lpor 4L, para se adaptar às mudanças no idioma.

Explicação

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 bytes

1 byte graças ao xnor .

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

Experimente online. Suíte de teste.

Explicação

  • z é a entrada
  • tz remove o #
  • itz16 analisa como um número hexadecimal
  • t^8 8calcula 8 8 - 1
  • -t^8 8itz16calcula 8 8 - 1 - entrada
  • %"#%06x"-t^2 24itz16 formata-o em uma string hexadecimal de 6 caracteres e adiciona o #

Que tal 8 ^ 8 para 2 ^ 24?
— Xnor

1

Haskell, 85 bytes

Minha primeira submissão, provavelmente será a mais longa (85 bytes), mas ei, você precisa começar em algum lugar. Em Haskell:

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

Ele está usando a mesma subtração de 15 truques que eu vi outras pessoas usarem.

Eu também tentei usar printf junto com o outro truque (subtrair 8 ^ 8 - 1) e funciona em ghci, mas por algum motivo não compila:

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

Se alguém pudesse fazer esse trabalho, seria ótimo!


Bem-vindo à programação de quebra-cabeças e código de golfe. Essas são respostas muito boas (melhores do que eu poderia fazer em Haskell!). No entanto, existe um formato de resposta comum para desafios de código-golfe que permite que o snippet do placar coloque sua resposta no placar. Vou editá-lo para você; você pode aceitar ou negar a edição.
— Wizzwizz4

Para responder aos comentários de outros usuários, digite @username.
— Wizzwizz4

@ wizzwizz4 Muito obrigado pela sua ajuda.
— Lpapez

A qualquer momento! Quer experimentar alguns dos meus desafios? Analise sua cadeira e a seqüência de mapas da Hilbert Curve são meus favoritos, embora a curva de Hilbert seja realmente difícil.
— Wizzwizz4

@ wizzwizz4 Certamente, vou ver o que posso fazer.
— Lpapez

1

Mathematica, 69 60 bytes

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

Mais uma vez, é o processamento de strings que me mata aqui.


1

C, 94 bytes

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;}

A função recebe uma matriz de caracteres, retorna valor inverso. Produz letras maiúsculas para resposta. O código inverte cada caractere hexadecimal ASCII para seu inverso, se for válido, ignorando-o de outra forma.


Você pode economizar espaço declarando globalmente iantes da função:i;
— Liam

1

𝔼𝕊𝕄𝕚𝕟 2, 18 caracteres / 34 bytes

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

Try it here (Firefox only).

Usando uma versão criada após o desafio.

Explicação

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

Solução não competitiva, 15 caracteres / 29 bytes

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

Usa transliteração.


Você também pode adicionar uma versão competitiva, para que possamos ver como o idioma se comporta?
— precisa saber é o seguinte

Certo. Veja nova edição.
— Mama Fun Roll

Bom uso do símbolo APL ⌿.
— lirtosiast

Hehe, esse símbolo foi o que fez mais sentido /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])

Primeiro código de golfe, por favor, dê opiniões :)


Você tem permissão para exigir que a entrada esteja "quotes"entre btw, portanto input()funciona. Você não precisa da nova linha e do recuo no loop for e rangefunciona muito bem. Também há alguns espaços que você pode remover.
— Rɪᴋᴇʀ

int("ff", 16)pode ser substituído por apenas 255.
— Maçaneta

Você precisa dos parênteses dentro dos colchetes após cada x?
— Azul

0

CJam, 16 bytes

qA,'G,65>+s_W%er

Isso é bastante longo, porque o CJam lida com as alterações básicas de maneira diferente; portanto, era mais curto fazer transliteração. Veja minha resposta da Retina para mais informações sobre transliteração.

Experimente online.

Explicação

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 bytes

Originalmente eu usei 256^3então 16^6. Então eu vi o Pietu1998 8^8e agora essa solução usa isso.

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

0

Java, 95 90 bytes

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

XOR bit a bit.


0

Bash + tr, 35 bytes

tr 0-9A-Fa-f fedcba9876543210543210

A saída é sempre em minúscula.

Infelizmente "tr" não leva intervalos na ordem inversa, então eu tive que explicá-los.


0

C, 147 bytes

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);}}

O strtol usado para converter da sequência hexadecimal em int subtraiu o número de 255 para obter o elogio, como dizia o post original. No entanto, estou me perguntando se existe uma maneira de passar um intervalo de caracteres de s para strtol, para que eu não tenha que perder um monte de bytes copiando para uma nova string?


Eu não acho que os compiladores geralmente impõem retornos de função e padrão para int, então você provavelmente omite o voidtipo de retorno?
— Liam

0

R, 62 bytes

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

0

sed, 48 bytes

y/0123456789ABCDEFabcdef/fedcba9876543210543210/

Ou 36 bytes, se você precisar apenas suportar um caso.


Você não precisa suportar letras minúsculas e maiúsculas.
— Martin Ender

@ MartinBüttner, a pergunta parece exigir suporte para os dois casos na entrada, mas não na saída. Como minha solução bash + tr, esta solução suporta tanto na entrada, mas apenas grava em letras minúsculas.
— Glenn Randers-Pehrson

Você tem um extra 0no seu código, entre 9e A(embora a contagem de bytes esteja correta, deve haver um erro de cópia).
— hobbs

A pergunta diz que você pode escolher em qual caso sua entrada e saída serão.
— precisa saber é o seguinte

0

PowerShell, 48 bytes

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

Necessariamente recebe entrada via param($a)como uma sequência de caracteres, delimitada por 'ou ", uma vez que C:\Tools\Scripts\Golfing> .\complementary-colors #a1b2c3na linha de comando do PowerShell será tratada #a1b2c3como um comentário e a ignorará sumariamente.

Da esquerda para a direita, "#{0:x6}"-f(...)formata nossos cálculos de saída de volta em hexadecimal com 6 caracteres garantidos (para contabilizar a entrada #ffffff). Dentro das parênteses, subtraímos nosso número de entrada de 0xffffff. Fazemos isso aproveitando o fato de que o PowerShell analisa números hexadecimais no formato 0xNNN, para construirmos um número hexadecimal de formato adequado a partir do nosso número de entrada $a. (Observe que a concatenação mais .Trim()é mais curta do que .Replace()aqui em um byte.) Também aproveitamos o MBoperador unário via 16MB-1para construir em 16777215vez de 0xffffff.


0

TeaScript, 24 bytes

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

Erros no intérprete não estão me deixando mais curto :(

Experimente online


Downvote explicação? Ele funciona para todos os casos de teste
— Downgoat
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.