Colores complementarios

26

Dada la entrada de un color en #rrggbbformato hexadecimal, genera su complemento RGB en el mismo formato.

El complemento RGB R 2 G 2 B 2 de cualquier color R 1 G 1 B 1 se define como el color con el valor R 2 255 - R 1 , el valor B 2 255 - B 1 y el valor G 2 255 - G 1 .

Los dígitos hexadecimales pueden estar en mayúsculas (# FFAA20) o en minúsculas (# ffaa20). El caso de la entrada y la salida no tiene por qué ser coherente (por lo que puede tomar la entrada en minúsculas pero la salida en mayúsculas y viceversa).

Como se trata de , gana el código más corto en bytes.

Casos de prueba (tenga en cuenta que dado que dar a su programa / función su propia salida debería dar como resultado la entrada original (es involuntario ), los casos de prueba deberían funcionar en ambas direcciones):

In/Out   Out/In
----------------
#ffffff  #000000
#abcdef  #543210
#badcab  #452354
#133742  #ecc8bd
#a1b2c3  #5e4d3c
#7f7f80  #80807f
Pomo de la puerta
fuente
2
Lo siento, pero sRGB no funciona de esa manera. Primero debe convertir al espacio lineal, en el que no están los códigos hexadecimales.
John Dvorak
2
@ JanDvorak Oh, bueno. El estado del desafío reflejará mi ignorancia, entonces, ya que realmente no puedo cambiarlo ahora. : P
Pomo de la puerta
Sin embargo, promediar dos valores en sRGB podría ser un desafío separado decente. sRGB = RGB ^ 0.45 en la mayor parte del rango, pero lineal cerca de la parte inferior del rango.
John Dvorak el

Respuestas:

17

Pyth, 9 8 bytes

¡Gracias a @isaacg por -1 byte!

sXz.HM16

Restar el valor de un determinado color de 255 es equivalente a restar cada uno de sus dígitos hexadecimales de 15. Digamos que un número es 16a + b . Entonces el valor del número creado restando sus dígitos de 15 es 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 +

Pruébalo aquí . Banco de pruebas.

lirtosiast
fuente
¡Buena respuesta! Tomé prestada su idea de usar '0123456789abcdef'para convertir a hexadecimal (en lugar de dec2hexfunción)
Luis Mendo
Creo que tu enlace es incorrecto. ( Copiar y pegar FTW. )
PurkkaKoodari
@ Pietu1998 Whoops; Lo arreglaré.
lirtosiast el
El Ues innecesario, está implícitamente rellenado por M.
isaacg
6

Retina, 13 10 bytes

T`w`G-A9-0

Hay tres partes en el código, separadas por backticks ( `): Tespecifica el modo transliterar, que reemplaza cada carácter en la segunda parte con su carácter correspondiente en la tercera parte.

wes lo mismo que las expresiones regulares tradicionales \w, o _0-9A-Za-z, que se expande a _0123456789ABCDEFGH....

La segunda parte se expande GFEDCBA9876543210, gracias a la ingeniosa capacidad de Retina para expandirse en orden inverso. Póngalos uno encima del otro y obtendremos:

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

Tenga en cuenta que el último carácter, 0se repite para ajustarse a la longitud de la cadena más larga, pero solo nos preocupamos por los caracteres hexadecimales, que se muestran con los caracteres de careta.

Gracias a Martin Büttner por sugerir este enfoque.

Prueba el paquete de prueba en línea.

NinjaOsoMono
fuente
4

Maravilloso, 41 bytes

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

Intérprete en línea aquí. La entrada debe estar en mayúscula.

Explicación

El 00y ]]en la parte inferior buscará el primer carácter (el #) y caerá al fondo y se generará antes que nada.

Las primeras 3 líneas son un bucle para buscar todos los caracteres restantes.

Primero necesitamos convertir los caracteres de dígitos hexadecimales a 0-15, haciendo x -= 48, x -= x > 9 ? 7 : 0(ya que 'A' - '9'es 8).

Para encontrar el complemento, simplemente necesitamos convertir cada dígito xa 15-x. Esto es equivalente a (para valores de 8 bits) (~x)+16 = ~(x-16).

Finalmente, tenemos que convertir estos números nuevamente en dígitos hexadecimales, haciendo x += x > 9 ? 7 : 0, x += 48.

Entonces ahora tenemos x -= 48, x -= x > 9 ? 7 : 0, x = ~(x - 16), x += x > 9 ? 7 : 0, x += 48 .

Tenga en cuenta que si eliminamos la expresión con el primer operador ternario, ingrese dígitos A-F se traducirá en un negativo x después de la negación.

Por lo tanto, podemos cambiar la expresión anterior a:, x -= 48, x -= 16, x = ~x, x += (x > 9 || x < 0) ? 7 : 0, x += 48que es igual ax -= 64, x = ~x, x += (x > 9 || x < 0) ? 7 : 0, x += 48 .

El código anterior es solo una implementación de la última expresión. -Wes x -= 32y +Oes x += 24. Dado que Marbelous usa aritmética de 8 bits sin signo, la condición <Acubre tanto el caso de x > 9como x < 0.

es1024
fuente
¿Creaste Marbelous?
Rɪᴋᴇʀ
@RikerW Marbelous fue creado / desarrollado por varios usuarios de PPCG, incluido yo mismo: ver aquí .
es1024
Bueno. Gracias por hacérmelo saber.
Rɪᴋᴇʀ
4

JavaScript ES6, 61 bytes 66 68 48 53 64

Ahorra bastantes bytes gracias a @ Cᴏɴᴏʀ O'Bʀɪᴇɴ, @NinjaBearMonkey y @nderscore

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

Aprovecha el auto-type-casting. La fijación de los ceros mató el recuento de bytes

Downgoat
fuente
Usar en eval(`0x${s.slice(1)}`)lugar deparseInt
Conor O'Brien el
@ CᴏɴᴏʀO'Bʀɪᴇɴ ¿Esa es la misma longitud?
PurkkaKoodari
@ CᴏɴᴏʀO'Bʀɪᴇɴ gracias, utilicé en - lugar de eval que ahorró aún más bytes
Downgoat
Oh, se olvidó del auto type casting: D
Conor O'Brien
Pruébalo con la entrada #FFFFFF. Las devoluciones #0.
Conor O'Brien
4

JavaScript ES6, 63 58 52 49 bytes

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

¡Gracias a nderscore por guardar 11 bytes!

nicael
fuente
-5 bytes:c=>"#"+[...c].map(x=>"fedcba9876543210"[+('0x'+x)]).join``
nderscore el
@nder exactamente, ya lo pensé :) Gracias. Lo iba a usar, pero con "eval".
nicael
1
ah, tengo uno más -6:c=>c.replace(/\w/g,x=>"fedcba9876543210"[+('0x'+x)])
nderscore
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

Pruébalo aquí! , Conjunto de pruebas (Usar ejecución completa, que ahora funciona)

Conor O'Brien
fuente
3

Julia, 74 49 bytes

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

Bastante largo en este momento pero es un comienzo. Esta es una función lambda que acepta una cadena y devuelve una cadena. La salida estará en minúsculas, pero la entrada puede estar en cualquiera.

Como señaló Thomas , restar cada componente de color de 2 dígitos de 255 es equivalente a restar cada dígito individual en la entrada hexadecimal de 15. Al recorrer la cadena de entrada, excluyendo el inicio #, convertimos 15, el dígito analizado en hexadecimal. Nos unimos a todos estos, luego agregamos un #y lo llamamos bueno.

Alex A.
fuente
3

Japt , 35 32 22 20 16 15 bytes

¡Y?(F-XnG)sG :X

Explicación:

¡                 //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
fuente
¡Buena esa! Lo vi anoche y me dije: "Mañana ayudaré a jugar golf". Pero a estas alturas ya lo has jugado más de lo que creía posible. :)
ETHproductions
2

Perl, 30 bytes

incluye +1 para -p

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

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

Kenney
fuente
2

MATL , 21 bytes

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

Esto usa la versión 6.0.0 del lenguaje / compilador, que es anterior al desafío.

Los dígitos de entrada deben estar en mayúscula.

Ejemplo

Esto se ha ejecutado en Octave:

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

Editar (12 de junio de 2016)

El código ahora se puede probar en línea . Las comas deben ser reemplazadas por espacios y 6Lpor4L , para ajustarse a los cambios en el lenguaje.

Explicación

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
fuente
1

Pyth, 20 19 bytes

1 byte gracias a xnor .

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

Pruébalo en línea. Banco de pruebas.

Explicación

  • z es la entrada
  • tz elimina el #
  • itz16 analiza como un número hexadecimal
  • t^8 8calcula 8 8 - 1
  • -t^8 8itz16calcula 8 8 - 1 - entrada
  • %"#%06x"-t^2 24itz16 lo formatea en una cadena hexadecimal de 6 caracteres con relleno de cero y agrega el #
PurkkaKoodari
fuente
¿Qué tal 8 ^ 8 para 2 ^ 24?
xnor
1

Haskell, 85 bytes

Mi primer envío, probablemente será el más largo (85 bytes) pero bueno, tienes que comenzar en alguna parte. En Haskell:

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

Está usando la misma resta de 15 trucos que vi usar a otras personas.

También intenté usar printf junto con el otro truco (restar 8 ^ 8 - 1) y funciona en ghci pero por alguna razón no se compila:

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

¡Si alguien pudiera hacer que esto funcionara, sería genial!

lpapez
fuente
Bienvenido a Programming Puzzles y Code Golf. Estas son respuestas muy buenas (¡mejor de lo que podría hacer en Haskell!). Sin embargo, hay un formato de respuesta común para los desafíos de código de golf que permite que el fragmento de la tabla de clasificación ponga su respuesta en la tabla de clasificación. Lo editaré para ti; puedes aceptar o rechazar la edición.
wizzwizz4
Para responder a los comentarios de otros usuarios, escriba @username.
wizzwizz4
@ wizzwizz4 Muchas gracias por su ayuda.
lpapez
¡En cualquier momento! ¿Quieres probar algunos de mis desafíos? Analizar su silla y Cadena de mapa a Hilbert Curve son mis favoritas, aunque la curva de Hilbert es realmente difícil.
wizzwizz4
@ wizzwizz4 Ciertamente, veré qué puedo hacer.
lpapez
1

Mathematica, 69 60 bytes

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

Una vez más, es el procesamiento de cadenas lo que me mata aquí.

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

La función toma una matriz de caracteres, devuelve un valor inverso. Produce letras mayúsculas para la respuesta. El código voltea cada carácter hexadecimal ASCII a su inverso si es válido, de lo contrario lo ignora.

Dave P.
fuente
Puede ahorrar algo de espacio declarando globalmente iantes de la función:i;
Liam
1

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

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

Try it here (Firefox only).

Usando una versión creada después del desafío.

Explicación

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

Solución no competitiva, 15 caracteres / 29 bytes.

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

Utiliza transliteración.

Mama Fun Roll
fuente
¿Puedes agregar también una versión competitiva para que podamos ver cómo se acumula el idioma?
lirtosiast el
Seguro. Ver nueva edición.
Mama Fun Roll
Buen uso del símbolo APL .
lirtosiast el
Jeje, ese símbolo era el que tenía más 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])

Primer código de golf, por favor dar opiniones :)

Mezcla Miau
fuente
Puede solicitar que la entrada esté en "quotes"BTW, por lo que input()funciona. No necesita la nueva línea y la sangría en el bucle for, y rangefunciona bien. También hay un par de espacios que puedes eliminar.
Rɪᴋᴇʀ
int("ff", 16)puede ser reemplazado por solo 255.
Pomo de la puerta
¿Necesita los paréntesis dentro de los corchetes después de cada x?
Azul
0

CJam, 16 bytes

qA,'G,65>+s_W%er

Esto es bastante largo porque CJam maneja los cambios de base de manera diferente, por lo que fue más corto simplemente hacer transliteración. Vea mi respuesta de Retina para más información sobre transliteración.

Pruébalo en línea.

Explicación

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
NinjaOsoMono
fuente
0

Python 3, 44 bytes

Originalmente solía 256^3, entonces 16^6. Luego vi Pietu1998 8^8y ahora esta solución usa eso en su lugar.

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

Java, 95 90 bytes

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

Bitwise XOR.

SuperJedi224
fuente
0

Bash + tr, 35 bytes

tr 0-9A-Fa-f fedcba9876543210543210

La salida siempre es minúscula.

Desafortunadamente "tr" no toma rangos en orden inverso, así que tuve que explicarlos.

Glenn Randers-Pehrson
fuente
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);}}

Usé strtol para convertir de hexadecimal a int y luego restamos el número de 255 para obtener el cumplido como decía la publicación original. Sin embargo, me pregunto si hay una manera de pasar un rango de caracteres de s a strtol para no tener que desperdiciar un montón de bytes copiando a una nueva cadena.

Danwakeem
fuente
No creo que los compiladores usualmente impongan retornos de funciones y valores predeterminados a int, por lo que probablemente omita el voidtipo de retorno.
Liam
0

R, 62 bytes

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

sed, 48 bytes

y/0123456789ABCDEFabcdef/fedcba9876543210543210/

O 36 bytes si solo necesita admitir un caso.

Neil
fuente
No necesita admitir tanto minúsculas como mayúsculas.
Martin Ender
@ MartinBüttner, la pregunta parece requerir soporte para ambos casos en la entrada, pero no en la salida. Al igual que mi solución bash + tr, esta solución admite ambas entradas, pero solo escribe en minúsculas.
Glenn Randers-Pehrson
Tienes un extra 0en tu código, entre 9y A(el conteo de bytes es correcto, sin embargo, debe ser un error de copia).
hobbs
La pregunta dice que puede elegir en qué caso son sus entradas y salidas.
lirtosiast el
0

PowerShell, 48 bytes

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

Necesariamente toma la entrada vía param($a)como una cadena, delimitada con 'o ", ya que C:\Tools\Scripts\Golfing> .\complementary-colors #a1b2c3en la línea de comando de PowerShell se tratará #a1b2c3como un comentario y la ignorará sumariamente.

De izquierda a derecha, los "#{0:x6}"-f(...)formatos de nuestros cálculos de salida vuelven a ser hexadecimales con 6 caracteres garantizados (para tener en cuenta la entrada #ffffff). Dentro de los parens, restamos nuestro número de entrada 0xffffff. Hacemos esto aprovechando el hecho de que PowerShell analiza los números hexadecimales en formato 0xNNN, por lo que construimos un número hexadecimal de formato adecuado a partir de nuestro número de entrada $a. (Tenga en cuenta que la concatenación plus .Trim()es más corta que .Replace()aquí en un byte). También aprovechamos el MBoperador unario a través 16MB-1de construir en 16777215lugar de 0xffffff.

AdmBorkBork
fuente
0

TeaScript, 24 bytes

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

Los errores en el intérprete no me permiten acortar esto :(

Pruébalo en línea

Downgoat
fuente
¿Explicación de voto negativo? Funciona para todos los casos de prueba
Downgoat