La tonalità di un colore


23

Ti vengono dati i valori RGB di un colore. Il tuo compito è semplice: calcolare la tonalità, nella definizione più semplice.

Dire che i canali con il valore più alto, medio e più basso sono X, Y, Z (che sono rossi, verdi o blu) e i loro valori sono x, y, z. La tonalità di questo colore è (h (X) -h (Y)) * (1 + (xy) / (xz)) / 2 + h (Y), dove:

h(red) = 0 (or 360 if one of X or Y is blue)
h(green) = 120
h(blue) = 240

L'input è composto da 3 numeri interi da 0 a 255 che non sono tutti uguali, in qualsiasi ordine coerente. L'output può essere float o numeri interi arrotondati verso l'alto o verso il basso, il che non deve essere coerente. Se la parte intera dell'output è 0 o 360, è possibile stampare uno di essi.

Non è possibile chiamare i builtin per le conversioni dello spazio colore, comprese le conversioni implicite come durante la manipolazione di un'immagine.

Questo è code-golf. Il codice più corto vince.

Esempi

Input:  0 182 255
Output: 197 (or 198)

Input:  127 247 103
Output: 110

Input:  0 0 1
Output: 240

Input:  255 165 245
Output: 307 (or 306)

modificare

Non devi seguire la formula esatta, ma devi solo dare lo stesso risultato della formula sopra. Mi piacerebbe anche vedere alcune risposte giocando a golf la formula stessa.


Dovremmo prima convertire da sRGB a una scala lineare? Penso che dovremmo, ma nessuno sembra aver finora.
John Dvorak,

@JanDvorak Il compito è calcolare la tonalità, nella definizione più semplice . In questo caso, "più semplice" significa che devi supporre che l'input sia già nella scala corretta e utilizzare la formula esatta indicata nella domanda o qualsiasi altra cosa che dia lo stesso risultato.
jimmy23013,

Ma ... 24 bpp di solito significa sRGB. In caso contrario, la specifica del formato (tu) dovrebbe specificare diversamente.
John Dvorak,

@JanDvorak Dovresti usare questa definizione per RGB e la tonalità.
jimmy23013,

9
Va detto: huehuehue.
TheDoctor

Risposte:


6

Pyth, 27 byte

*60%+c-Ft.<QJxQKeSQ-KhSQyJ6

Dimostrazione. Collaudare l'imbragatura.

Fomula tratta da Wikipedia .

In sostanza, i passaggi sono:

  1. .<QJxQKeSQ: Sposta il valore più grande all'inizio della lista.
  2. -Ft: Prende la differenza degli altri due valori.
  3. -KhSQ: Sottrai il valore minimo dal valore massimo.
  4. c: Dividi 2 per 3.
  5. + ... yJ Aggiungi due volte l'indice del valore massimo nell'elenco (0 se R, 2 se G, 4 se B).
  6. % ... 6: Mod 6, per risolvere problemi con aspetti negativi.
  7. *60: Moltiplicare per 60 per convertire in gradi e stampare.

9

C #, 188 210 206 197 191 byte

int H(int r,int g,int b){int[]a={r,g,b};System.Array.Sort(a);int x=a[2],y=a[1],c=x==g?1:(x==b?2:(y==b?3:0)),d=y==g?1:(y==b?2:(x==b?3:0));return(int)((c-d)*120*(1+(x-y)*1D/(x-a[0]))/2+d*120);}

Grazie a Sok per aver salvato 4 byte e a SLuck49 per aver salvato 15 byte!


Poiché si utilizza zuna sola volta nel calcolo dell'output e non lo si utilizza nei calcoli precedenti, si elimina la variabile e si modifica l'output in return(int)((c-d)*(1+(x-y)/(double)(x-a[0]))/2+d);, risparmiando 4 byte.
Dal

È possibile fattorizzare 120 da ce le dassegnazioni e nel ritorno in questo modo c=x==g?1:(x==b?2:(y==b?3:0)),d=y==g?1:(y==b?2:(x==b?3:0))e quindi return(int)((c-d)*120*(1+(x-y)/(double)(x-a[0]))/2+d*120);salvare 4 byte.
SLuck49,

Inoltre, hai davvero bisogno del cast double? Se lo fai puoi usare questo invece (x-a[0])*1Dper salvare altri 5 byte.
SLuck49

@ SLuck49 Grazie! Sì, in realtà ho bisogno del cast, altrimenti darà risultati imprecisi, ma quella *1Dmoltiplicazione è un bel trucco!
Programma FOX

Inoltre (appena notato) è possibile eliminare l'utilizzo tutti insieme qualificandosi completamente System.Arrayper altri 6 byte.
SLuck49,

8

Pyth, 41 55 53 51 byte

A.)JohN,VQ*L120?qeQhSQ3j312T+/*-HKeeJhc-GheJ-GhhJ2K

L'input è previsto nel modulo r,g,b. Ecco una spiegazione:

                                                        Implicit: Q=eval(input()), evaluates to (r,g,b)
               ?qeQhSQ                                  Is b the smallest?
                      3j312T                            Choose [0,1,2] or [3,1,2] based on above
          *L120                                         Convert to [0,120,240] or [360,120,240]
       ,VQ                                              Pair -> [[r,0/360],[g,120],[b,240]]
   JohN                                                 Order by 1st element in each pair, store in J
A.)J                                                    Pop biggest from J, set G = x, H = h(X)
                                                        Output calculation:
                                       -GheJ                x - y
                                            -GhhJ           x - z
                                     hc                     Divide and increment
                                 KeeJ                       Set K = h(Y)
                              *-HK                          Multiply by (h(X) - h(Y))
                             /                   2          Integer division by 2
                            +                     K         Add h(Y)

Salvati 4 byte, grazie a @Jakube e @isaacg


@ jimmy23013 Risolto, grazie per il caso di test aggiuntivo
Pubblicato il

1
Un paio di golf: m*120d-> *L120, salva eeJin Klinea per salvare un altro byte.
isaacg,

@isaacg Non sapevo che l' Loperatore generasse automaticamente un intervallo su un int, ogni giorno è un giorno shcool sembra: o) Grazie!
Dal

8

Javascript (ES6), 145 115 108 100 97 90 byte

Restituisce i galleggianti. Assegnare a una funzione da usare.

(r,g,b)=>([x,y,z]=[r,g,b].sort((a,b)=>b-a),m=x-z,(x-r?x-g?r-g+4*m:b-r+2*m:g-b+6*m)/m%6*60)

Hai salvato 30 byte incorporando tutto in un'unica sequenza operatore ternaria e aspettando fino alla fine per normalizzare a 0-360.

Grazie a edc65, Vasu Adari e ETHproductions per salvare ancora più byte.

JSFiddle con i test. Prova in Firefox.

Se la rimozione della dichiarazione di funzione h=non è legale, aggiungere 2 byte.


È possibile rimuovere 'var' e alcuni byte.
Vasu Adari,

ES6Fiddle ha bisogno della dichiarazione var per qualche motivo e non mi sono reso conto che non era necessario fino a quando non ho provato ES6 in Firefox
DankMemes,

1
È possibile salvare 6 byte sostituendo le parentesi graffe con parentesi, il punto e virgola con una virgola e rimuovendo il simbolo return. Credo che anche la rimozione della dichiarazione di funzione ( h=) sia legale, portando il totale a 100.
ETHproductions

Questo può essere ossessivo (quindi, non sono tutti buoni giocatori di golf?;)), Ma potresti salvare altri due byte eliminando la parentesi %6)*60e il suo partner dall'altra parte. Inoltre, usando la forza bruta sull'aggiunta (invece di aggiungere 6 alla fine) si risparmierebbe effettivamente un byte sull'impostazione corrente. (((x==r?(g-b)/m:x==g?2+(b-r)/m:4+(r-g)/m)+6)%6)*60diventerebbe (x==r?6+(g-b)/m:x==g?8+(b-r)/m:10+(r-g)/m)%6*60.
ETHproductions

1
+1 per l'ordinamento, molto intelligente, questo è 90 (o 92)(r,g,b)=>([m,_,M]=[r,g,b].sort((a,b)=>a-b),C=M-m,(M-r?M-g?r-g+4*C:b-r+2*C:g-b+6*C)/C%6*60)
edc65,

6

Ottava, 65 60 50 byte

Modifica: salvato 10 byte grazie a pawel.boczarski

Una soluzione approssimativa ...

@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)

Prova

@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)
ans([0   182   255])
ans =  196.14

@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)
ans([127   247   103])
ans =  111.05

@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)
ans([0   0   1])
ans =  240.00

@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)
ans([255   165   245])
ans =  305.82

Ottava, 107 byte

La mia soluzione originale (esatta) ...

Codice:

function H=r(c) [b,i]=sort(c);h=60*[6*(i(1)~=3),2,4](i);H=(h(3)-h(2))*(1+(b(3)-b(2))/(b(3)-b(1)))/2+h(2);

Ha spiegato:

function H=r(c)
   [b,i]=sort(c);
   h=60*[6*(i(1)~=3),2,4](i);
   H=(h(3)-h(2))*(1+(b(3)-b(2))/(b(3)-b(1)))/2+h(2);

Questa funzione accetta un vettore contenente i valori R, G, B come input ce ordina l'ingresso in ordine crescente

  • b contiene i valori ordinati [z, y, x]
  • i contiene il piano RGB associato a ciascun valore in b

Il vettore hè popolato con i valori

  • 60*[6, 2, 4]= [360, 120, 240](ma 3 byte in meno)
  • a meno che il valore più basso sia in Blu ( i(1) == 3), nel qual caso il valore della prima tonalità diventa zero
  • quindi utilizzare (i)per riorganizzare hin [h(Z), h(Y), h(X)]ordine

Da lì è solo una trascrizione diretta della formula. Puoi provarlo qui .


Suggerimento: utilizzare la notazione di funzione anonima per spremere più byte: @(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)è dieci byte più breve della definizione con la functionparola chiave.
pawel.boczarski,

@ pawel.boczarski Mi chiedevo se avrei potuto eliminare del tutto l'intestazione della funzione, ma non so se sia legittimo. Ma grazie per il suggerimento! : D
becher

@ pawel.boczarski Ripensandoci, ho ancora bisogno di una r=funzione anonima per poterla chiamare, giusto?
becher

Esistono molte soluzioni in cui vengono pubblicate funzioni anonime. Inoltre, è possibile chiamare la funzione così definita anche in questo modo: (@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360))([127 247 103])oppure sostenere che è possibile utilizzare la ansvariabile subito dopo la definizione della funzione anonima, in modo che l'assegnazione non sia necessaria per il completamento della definizione della funzione. In una sfida ( codegolf.stackexchange.com/questions/54945 ) un handle della funzione di libreria Matlab esistente è stato pubblicato come soluzione completa.
pawel.boczarski,

@ pawel.boczarski Wow, questo è ... solo ... malvagio: DI avrebbe dovuto sapere che Luis sarebbe stato coinvolto. Tornerò al codice originale e lo userò ansnell'esempio. Grazie ancora!
becher

5

Pyth, 55

So che la risposta di @ Sok batte la mia, ma da quando ho finito la mia appena dopo aver postato, ho pensato di pubblicare ancora. Questa è stata la prima volta che ho usato Pyth, quindi sono sicuro di aver fatto degli errori evidenti.

DlZK*120ZRKJSQFNJ=Y+YxQN)=kl@Y1+k/*-leYk+1c-eJ@J1-eJhJ2

L'input dovrebbe essere r, g, b. Puoi provarlo qui .


Non funziona per 255,165,245.
jimmy23013,

5

PowerShell, 232 226 222 161 byte

Vedi la cronologia delle revisioni per le versioni precedenti

$z,$y,$x=($r,$g,$b=$args)|sort
$c=((2,(0,3)[$y-eq$b])[$x-ne$b],1)[$x-eq$g]
$d=((2,(0,3)[$x-eq$b])[$y-ne$b],1)[$y-eq$g]
(($c-$d)*120*(1+($x-$y)/($x-$z))/2+$d*120)

Ciao ragazzo, vediamo se riesco a superare questo. Dato che \nconta lo stesso che ;ho lasciato la linea si interrompe per chiarezza.

La prima riga accetta input come tre $argse li memorizza in $r, $g, $b. Useremo davvero$b più tardi, ma abbiamo bisogno di tutti e tre, quindi le |sortopere funzionano in modo appropriato. Questo rende $z, $y, $xil più piccolo al più grande degli argomenti di input.

Le successive due linee vengono configurate $ce $dutilizzando più chiamate index-in-a-array per impostare i numeri in modo appropriato. Lavorare da fuori, se $xè -equale a $g(vale a dire, il verde era il più grande), abbiamo fissato $c=1... il resto, se $xè -not equal a $b(cioè, blu non era il più grande) $co è 0o 3seconda se blu è stato il secondo più grande ... altro,$c=2 . Set logici simili $d.

Quindi calcoliamo e stampiamo l'output con il seguente, che è solo l'algoritmo della sfida giocato un po '.

(($c-$d)*120*(1+($x-$y)/($x-$z))/2+$d*120)

1
Non conosco PowerShell, quindi correggimi se sbaglio ... Non lo usi $zdurante il calcolo $co $de lo usi solo una volta nel calcolo dell'output, quindi puoi sbarazzartene $zcompletamente e sostituirlo con $a[0]?
Dal

4

Rubino, 117 96 94 byte

Codice:

h=->r,g,b{z,y,x=[r,g,b].sort;v=x-z.to_f;({r=>(g-b)/v,g=>2+(b-r)/v,b=>4+(r-g)/v}[x]%6*60).to_i}
  • 21 byte salvati rimuovendoli () e usando le variabili r, g, b.
  • Prendendo il modulo di 6 per convertire il valore negativo e moltiplicandolo per 60 per convertire in gradi che hanno salvato 2 byte.

Esempi:

irb(main):274:0> h.call 0,182,255
=> 197
irb(main):275:0> h.call 127,247,103
=> 110
irb(main):276:0> h.call 0,0,1
=> 240
irb(main):277:0> h.call 255,165,245
=> 306

3

SWI-Prolog, 133 byte

a(L,H):-L=[R,G,B],max_list(L,X),min_list(L,Y),member(X:I:J:U,[R:G:B:0,G:B:R:2,B:R:G:4]),Z is 60*(U+(I-J)/(X-Y)),(Z<0,H is Z+360;H=Z).

Esempio: a([255,165,245],Hue). usciteHue = 306.666666666666 .

Questo utilizza la seguente formula:

  • Max = max(R,G,B), Min = min(R,G,B) .
  • Se Max = R, U = 0. Altrimenti, se Max = G, U = 2. Altrimenti U = 4.
  • Se Max = Re I = Ge J = B. Altrimenti if Max = G, I = Be J = R. Altro I = Re J = G.
  • Z = U + (I - J)/(Max - Min)
  • Hueè Zo Z + 360se Z < 0.

L'arrotondamento è facoltativo.
jimmy23013,

@ jimmy23013 Aggiornato, grazie.
Fatalizza il

3

Perl 5, 138 132 119 byte

Codice:

($m,$c,$M)=sort@A=($R,$G,$B)=@ARGV;print 60*(6+$M>$m?($G>$c?$B-$R:$B>$c?$R-$G:$G-$B)/($M-$m)+($G>$c?2:$B>$c?4:0):0)%360

Osservazioni:

Sicuramente Perl non può vincere una simile sfida con tutto il golf Pyth'oresque. Ma mi chiedevo se questo fosse possibile solo con 1 passaggio di calcolo. Grazie al modulo che ha funzionato bene. :)

Test:

$ perl hue.pl 0 182 255
197
$ perl hue.pl 127 247 103
110
$ perl hue.pl 0 0 1
240
$ perl hue.pl 255 165 245
307

confrontando con il valore medio invece del massimo rasato alcuni byte. (== contro>)
LukStorms

1

C ++ 276 byte

#include <iostream>
int H(int r,int g,int b){int m,n=120,o=240,l=r>g?r>b?g>b?m=r-b,o=n,n=-n,r-g:m=r-g,r-b:m=b-g,o+=n,n=-n,b-r:g>b?r>b?(m=g-b,o=0,g-r):m=g-r,n=-n,g-b:(m=b-r,o-=n,b-g);return (int)n*((float)l/m+1)/2+o;}int main(){int r,g,b;std::cin>>r>>g>>b;std::cout<<H(r,g,b);}

Un suggerimento: potresti lasciare la Hfunzione da sola nella risposta, poiché in code-golf una funzione autonoma è una risposta legittima, equivalente a un programma completo, vide meta discussione: meta.codegolf.stackexchange.com/questions/2419/… . Questo renderà la tua risposta più competitiva (risparmia 100 byte nel tuo caso). Sei ancora incoraggiato a lasciare la versione "completa" del programma sotto la soluzione per semplificare i test.
pawel.boczarski

Il secondo caso di test 127 247 103restituisce un valore non valido -120anziché 110.
pawel.boczarski,

1

R, 125 byte

Molto simile alla soluzione Octave di beaker. Uscita a virgola mobile.

Codice:

h=function(x){
  o=seq(3)[order(-x)];
  y=c(60*c(6*(o[3]!=3),2,4)[o],x[o]);
  return((y[1]-y[2])*(1+(y[4]-y[5])/(y[4]-y[6]))/2+y[2]);
}

Esempi:

> h(c(0,182,255))
[1] 197.1765
> h(c(127,247,103))
[1] 110
> h(c(0,0,1))
[1] 240
> h(c(255,165,245))
[1] 306.6667

1

Python, 154 byte

def h(c):r=c[:];c.sort();c=c[::-1];x,y,z=c;i,j=[120if n==r[1]else 240if n==r[2]else 0if z==r[2]else 360for n in[x,y]];print ((i-j)*(1+(x-y+0.)/(x-z))/2)+j

Accetta un elenco di valori. Non sono sicuro se questo può essere ulteriormente suddiviso. Qui è ungolfed:

def hue(color):
 rgb=color[:]  # copy list
 color.sort()  # sort list
 color=color[::-1]  # reverse sort
 x,y,z=color   # pull out x,y,z

 # The line 
 #   i,j=[120if n==r[1]else 240if n==r[2]else 0if z==r[2]else 360for n in[x,y]]
 # is basically the following, twice, once for x/hx and the second time for y/hy

 if x==rgb[1]: # if x is green
  hx = 120
 else:
  if x==rgb[2]: # if x is blue
   hx = 240
  else:
   if z==rgb[2]: # if z is blue and x is red
    hx = 0
   else:       # if x is red and y is blue
    hx = 1

 print ((hx-hy)*(1+(x-y+0.)/(x-z))/2)+hy  # calculate, print

0

JavaScript 108

Metodo alternativo.

function H(r,g,b){a=[r,g,b].sort(),M=a[2],c=M-a[0],h=M==r?(g-b)/c%6:M==g?(b-r)/c+2:(r-g)/c+4
return h*60|0;}

JavaScript 194

Utilizzando il metodo di esempio.

Array.prototype.i=[].indexOf
function H(r,g,b,a){a=[r,g,b].sort(),i=[a.i(r),a.i(g),a.i(b)],x=[i[2]?360:0,120,240],hx=x[i.i(2)]|0,hy=x[i.i(1)]|0
return (hx-hy)*(1+(a[2]-a[1])/(a[2]-a[0]))/2+hy|0}

var input = document.getElementById("input").innerHTML;
var output = document.getElementById("output");
var html = "";

input.replace(/(\d+)\,(\d+)\,(\d+)/g, function(m, r, g, b) {
  html += H(r, g, b) + "\n";
});

output.innerHTML = html;
<pre id="input">
0,182,255
127,247,103
0,0,1
255,165,245
</pre>

<pre id="output">

</pre>

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.