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
Maçaneta da porta
fonte
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.

lirtosiast
fonte
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.

NinjaBearMonkey
fonte
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.

es1024
fonte
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

Downgoat
fonte
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!

nicael
fonte
-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.)

Conor O'Brien
fonte
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.

Alex A.
fonte
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)
nicael
fonte
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'.

Kenney
fonte
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 '#'
Luis Mendo
fonte
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 #
PurkkaKoodari
fonte
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!

lpapez
fonte
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.

LegionMammal978
fonte
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.

Dave P.
fonte
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.

Mama Fun Roll
fonte
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 :)

Meow Mix
fonte
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
NinjaBearMonkey
fonte
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))
Sherlock9
fonte
0

Java, 95 90 bytes

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

XOR bit a bit.

SuperJedi224
fonte
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.

Glenn Randers-Pehrson
fonte
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?

Danwakeem
fonte
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))
mnel
fonte
0

sed, 48 bytes

y/0123456789ABCDEFabcdef/fedcba9876543210543210/

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

Neil
fonte
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.

AdmBorkBork
fonte
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

Downgoat
fonte
Downvote explicação? Ele funciona para todos os casos de teste
Downgoat