Colori complementari


26

Dato un input di un colore in #rrggbbformato esadecimale, genera il suo complemento RGB nello stesso formato.

Il complemento RGB R 2 G 2 B 2 di qualsiasi colore R 1 G 1 B 1 è definito come il colore con valore R 2 255 - R 1 , valore B 2 255 - B 1 e valore G 2 255 - G 1 .

Le cifre esadecimali possono essere in maiuscolo (# FFAA20) o in minuscolo (# ffaa20). Il caso dell'input e dell'output non deve essere coerente (quindi è possibile prendere l'input in minuscolo ma l'output in maiuscolo e viceversa).

Dato che si tratta di , vince il codice più breve in byte.

Casi di test (nota che dato che dare al tuo programma / funzione il proprio output dovrebbe comportare l'input originale (è involontario ), i casi di test dovrebbero funzionare in entrambe le direzioni):

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

2
Mi dispiace, ma sRGB non funziona in questo modo. Dovresti prima convertirlo in spazio lineare, in cui i codici esadecimali non sono presenti.
— John Dvorak

2
@JanDvorak Oh beh. Lo stato della sfida rifletterà la mia ignoranza, quindi, poiché non posso davvero cambiarla ora. : P
— Maniglia della porta

Tuttavia, fare la media di due valori in sRGB potrebbe essere una discreta sfida separata. sRGB = RGB ^ 0.45 sulla maggior parte dell'intervallo, ma lineare vicino alla parte inferiore dell'intervallo.
— John Dvorak,

Risposte:


17

Pyth, 9 8 byte

Grazie a @isaacg per -1 byte!

sXz.HM16

Sottrarre il valore di un certo colore da 255 equivale a sottrarre ciascuna delle sue cifre esadecimali da 15. Supponi che un numero sia 16a + b . Quindi il valore del numero creato sottraendo le sue cifre da 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 +

Provalo qui . Suite di test.


Bella risposta! Ho preso in prestito la tua idea di usare '0123456789abcdef'per convertire in esadecimale (invece della dec2hexfunzione)
— Luis Mendo

Penso che il tuo link non sia corretto. ( Copia-incolla FTW. )
— PurkkaKoodari

@ Pietu1998 Whoops; Lo aggiusterò.
— lirtosiast

Non Uè necessario - è implicitamente compilato da M.
— Isaacg,

6

Retina, 13 10 byte

T`w`G-A9-0

Il codice contiene tre parti, separate da backtick ( `): Tspecifica la modalità traslitterata, che sostituisce ogni carattere nella seconda parte con il carattere corrispondente nella terza parte.

wè lo stesso di regex tradizionale \w, o _0-9A-Za-z, che è espanso a _0123456789ABCDEFGH....

La seconda parte viene espansa GFEDCBA9876543210, grazie alla nobile capacità di Retina di espandersi in ordine inverso. Mettili uno sopra l'altro e otterrai:

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

Nota che l'ultimo carattere, 0viene ripetuto per adattarsi alla lunghezza della stringa più lunga, ma ci preoccupiamo solo dei caratteri esadecimali, mostrati dai punti di inserimento.

Grazie a Martin Büttner per aver suggerito questo approccio.

Prova la suite di test online.


4

Marbelous, 41 byte

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

Interprete online qui. L'input deve essere in maiuscolo.

Spiegazione

Il 00e ]]in basso recupererà il primo carattere (il #) e cadrà in basso e verrà emesso prima di ogni altra cosa.

Le prime 3 righe sono un ciclo per recuperare tutti i caratteri rimanenti.

Per prima cosa dobbiamo convertire i caratteri esadecimali in 0-15, facendo x -= 48, x -= x > 9 ? 7 : 0(poiché 'A' - '9'è 8).

Per trovare il complemento, dobbiamo semplicemente convertire ogni cifra xin 15-x. Ciò equivale a (per valori a 8 bit) (~x)+16 = ~(x-16).

Infine, dobbiamo riconvertire questi numeri in cifre esadecimali x += x > 9 ? 7 : 0, x += 48.

Quindi ora abbiamo x -= 48, x -= x > 9 ? 7 : 0, x = ~(x - 16), x += x > 9 ? 7 : 0, x += 48.

Nota che se rimuoviamo l'espressione con il primo operatore ternario, quindi immettiamo le cifre A- si Fotterrà una x negativa dopo la negazione.

Quindi possiamo cambiare l'espressione precedente in:, x -= 48, x -= 16, x = ~x, x += (x > 9 || x < 0) ? 7 : 0, x += 48che è uguale a x -= 64, x = ~x, x += (x > 9 || x < 0) ? 7 : 0, x += 48.

Il codice sopra è solo un'implementazione dell'ultima espressione. -Wè x -= 32ed +Oè x += 24. Poiché Marbelous utilizza un'aritmetica a 8 bit senza segno, la condizione <Acopre sia il caso di x > 9e x < 0.


Hai creato Marbelous?
— R

@RikerW Marbelous è stato creato / arricchito da diversi utenti PPCG incluso me stesso: vedi qui .
— es1024,

Va bene. Grazie per avermi fatto sapere.
— R

4

JavaScript ES6, 61 byte 66 68 48 53 64

Salva parecchi byte grazie a @ Cᴏɴᴏʀ O'Bʀɪᴇɴ, @NinjaBearMonkey e @nderscore

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

Sfrutta il cast di tipo automatico. Riparare gli zeri ha ucciso il conteggio dei byte


Usa eval(`0x${s.slice(1)}`)invece diparseInt
— Conor O'Brien il

@ CᴏɴᴏʀO'Bʀɪᴇɴ La stessa lunghezza?
— PurkkaKoodari,

@ CᴏɴᴏʀO'Bʀɪᴇɴ grazie, ho usato - invece di eval che ha salvato ancora più byte
— Downgoat

Oh, ho dimenticato il casting di tipo automatico: D
— Conor O'Brien,

Provalo con l'input #FFFFFF. Ritorni #0.
— Conor O'Brien,

4

JavaScript ES6, 63 58 52 49 byte

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

Grazie a nderscore per aver salvato 11 byte!


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

@nder esattamente, ci ho già pensato :) Grazie. Lo avrebbe usato, ma con "eval".
— nicael

1
ah, ne ho ancora uno -6:c=>c.replace(/\w/g,x=>"fedcba9876543210"[+('0x'+x)])
— nderscore

3

Jolf, 17 byte

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

Provalo qui! , Suite di test (usa la corsa completa, che ora funziona.)


3

Julia, 74 49 byte

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

Abbastanza lungo al momento, ma è un inizio. Questa è una funzione lambda che accetta una stringa e restituisce una stringa. L'output sarà in minuscolo ma l'ingresso può essere in entrambi.

Come ha osservato Thomas , sottraendo ogni componente di colore a 2 cifre da 255 equivale a sottrarre ogni singola cifra nell'input esadecimale da 15. Passando sopra la stringa di input, escluso il carattere iniziale #, convertiamo 15 - la cifra analizzata in esadecimale. Ci uniamo a tutti questi, poi puntiamo su un #e lo chiamiamo buono.


3

Japt , 35 32 22 20 16 15 byte

¡Y?(F-XnG)sG :X

Spiegazione:

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

Ben fatto! L'ho visto ieri sera e mi sono detto: "Domani ti aiuterò a giocare a golf". Ma ormai hai giocato a golf più di quanto pensassi possibile. :)
— ETHproductions

2

Perl, 30 byte

include +1 per -p

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

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


2

MATL , 21 byte

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

Questo utilizza la versione 6.0.0 del linguaggio / compilatore, che è precedente alla sfida.

Le cifre di input devono essere maiuscole.

Esempio

Questo è stato eseguito su Octave:

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

Modifica (12 giugno 2016)

Il codice può ora essere provato online . Le virgole devono essere sostituite da spazi e 6Lda 4L, per conformarsi ai cambiamenti nella lingua.

Spiegazione

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 byte

1 byte grazie a xnor .

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

Provalo online. Suite di test.

Spiegazione

  • z è l'input
  • tz rimuove il #
  • itz16 analizza come un numero esadecimale
  • t^8 8calcola 8 8 - 1
  • -t^8 8itz16calcola 8 8 - 1 - input
  • %"#%06x"-t^2 24itz16 lo formatta in una stringa esadecimale a 6 caratteri con spaziatura zero e aggiunge il #

Che ne dici di 8 ^ 8 per 2 ^ 24?
— xnor

1

Haskell, 85 byte

La mia prima presentazione, probabilmente sarà la più lunga (85 byte) ma hey, devi iniziare da qualche parte. In Haskell:

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

Sta usando la stessa sottrazione del trucco di 15 che ho visto usare da altre persone.

Ho anche provato a usare printf insieme all'altro trucco (sottrai 8 ^ 8 - 1) e funziona in ghci ma per qualche ragione non si compila:

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

Se qualcuno potesse fare questo lavoro sarebbe fantastico!


Benvenuti in Programming Puzzle and Code Golf. Queste sono risposte molto buone (meglio di quanto potrei fare a Haskell!). Tuttavia, esiste un formato di risposta comune per le sfide del code-golf che consente allo snippet di classifica di inserire la tua risposta in classifica. Lo modificherò per te; puoi accettare o rifiutare la modifica.
— wizzwizz4,

Per rispondere ai commenti di altri utenti, digitare @username.
— wizzwizz4,

@ wizzwizz4 Mille grazie per l'assistenza.
— lpapez,

In qualsiasi momento Vuoi provare alcune delle mie sfide? Analizzare la sedia e la stringa della mappa su Hilbert Curve sono i miei preferiti, anche se la curva di Hilbert è davvero difficile.
— wizzwizz4,

@ wizzwizz4 Certamente, vedrò cosa posso fare.
— lpapez,

1

Mathematica, 69 60 byte

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

Ancora una volta, è l'elaborazione delle stringhe che mi uccide qui.


1

C, 94 byte

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 funzione accetta un array di caratteri, restituisce un valore inverso. Produce lettere maiuscole per la risposta. Il codice inverte ciascun carattere esadecimale ASCII al suo contrario se è valido, altrimenti lo ignora.


Puoi risparmiare un po 'di spazio dichiarando globalmente iprima della funzione:i;
— Liam,

1

𝔼𝕊𝕄𝕚𝕟 2, 18 caratteri / 34 byte

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

Try it here (Firefox only).

Utilizzando una versione creata dopo la sfida.

Spiegazione

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

Soluzione non competitiva, 15 caratteri / 29 byte

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

Usa la traslitterazione.


Puoi aggiungere anche una versione competitiva, così possiamo vedere come si impila la lingua?
— lirtosiast,

Sicuro. Vedi nuova modifica.
— Mama Fun Roll,

Bel uso del simbolo APL ⌿.
— lirtosiast,

Hehe, quel simbolo era quello che aveva più senso /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])

Primo codice golf, si prega di dare opinioni :)


Puoi richiedere che l'input sia in "quotes"BTW, quindi input()funziona. Non hai bisogno della nuova riga e del rientro nel ciclo for e rangefunziona perfettamente. Ci sono anche un paio di spazi che puoi rimuovere.
— Rɪᴋᴇʀ

int("ff", 16)può essere sostituito con solo 255.
— Maniglia della porta

Hai bisogno delle parentesi tra parentesi dopo ogni x?
— Blue

0

CJam, 16 byte

qA,'G,65>+s_W%er

Questo è abbastanza lungo perché CJam gestisce le modifiche di base in modo diverso, quindi è stato più breve fare semplicemente traslitterazione. Vedi la mia risposta Retina per ulteriori informazioni sulla traslitterazione.

Provalo online.

Spiegazione

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 byte

Inizialmente l'ho usato 256^3, quindi 16^6. Poi ho visto Pietu1998 8^8e ora questa soluzione lo utilizza.

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

0

Java, 95 90 byte

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

Bitwise XOR.


0

Bash + tr, 35 byte

tr 0-9A-Fa-f fedcba9876543210543210

L'output è sempre in minuscolo.

Sfortunatamente "tr" non prende le gamme in ordine inverso, quindi ho dovuto precisarle.


0

C, 147 byte

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

Usato strtol per convertire da stringa esadecimale a int, quindi sottratto il numero da 255 per ottenere il complimento come ha detto il post originale. Mi chiedo, tuttavia, se esiste un modo per passare una serie di caratteri da s a strtol, quindi non devo sprecare un sacco di byte copiando in una nuova stringa?


Non penso che i compilatori di solito impongano i rendimenti delle funzioni e quelli predefiniti in int, quindi probabilmente ometti il voidtipo restituito?
— Liam,

0

R, 62 byte

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

0

sed, 48 byte

y/0123456789ABCDEFabcdef/fedcba9876543210543210/

O 36 byte se è necessario supportare solo un caso.


Non è necessario supportare sia lettere minuscole che maiuscole.
— Martin Ender,

@ MartinBüttner la domanda sembra richiedere supporto per entrambi i casi nell'input, ma non nell'output. Come la mia soluzione bash + tr, questa soluzione supporta sia l'input che la scrittura minuscola.
— Glenn Randers-Pehrson,

Hai un extra 0nel tuo codice, tra il ( 9e il Aconteggio dei byte è corretto, tuttavia deve essere un errore di copia).
— Hobbs

La domanda dice che puoi scegliere il caso in cui input e output sono.
— Lirtosiast

0

PowerShell, 48 byte

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

Prende necessariamente l'input via param($a)come stringa, delimitato da 'o ", da alloraC:\Tools\Scripts\Golfing> .\complementary-colors #a1b2c3 nella riga di comando di PowerShell verrà trattato #a1b2c3come un commento e lo ignorerà in modo sommario.

Da sinistra a destra, i "#{0:x6}"-f(...)formati che i nostri calcoli di output riportano in esadecimali con 6 caratteri garantiti (per tenere conto dell'input #ffffff). All'interno delle parentesi, sottraggiamo il nostro numero di input da 0xffffff. Facciamo questo sfruttando il fatto che PowerShell analizza i numeri esadecimali in formato 0xNNN, quindi costruiamo un numero esadecimale di formato adeguato dal nostro numero di input $a. (Si noti che la concatenazione plus .Trim()è più breve di .Replace()qui di un byte.) Sfruttiamo anche l' MBoperatore unario 16MB-1per costruire 16777215anziché 0xffffff.


0

TeaScript, 24 byte

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

I bug nell'interprete non mi permettono di ottenere questo più breve :(

Provalo online


Spiegazione del downvote? Funziona con tutti i casi di test
— Downgoat,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.