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.