Odcień koloru

23

Otrzymujesz wartości RGB koloru. Twoje zadanie jest proste: obliczyć odcień w najprostszej definicji.

Powiedz, że kanały o najwyższej, środkowej i najniższej wartości to X, Y, Z (które są albo czerwone, zielone lub niebieskie), a ich wartości to x, y, z. Odcień tego koloru to (h (X) -h (Y)) * (1 + (xy) / (xz)) / 2 + h (Y), gdzie:

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

Dane wejściowe składają się z 3 liczb całkowitych od 0 do 255, które nie wszystkie są równe, w dowolnej spójnej kolejności. Wyjściem mogą być zmiennoprzecinkowe lub liczby całkowite zaokrąglone w górę lub w dół, co nie musi być spójne. Jeśli całkowita liczba wyjściowa wynosi 0 lub 360, możesz wydrukować jedną z nich.

Nie można wywoływać wbudowanych funkcji konwersji przestrzeni kolorów, w tym konwersji niejawnych, na przykład podczas manipulacji obrazem.

To jest golf golfowy. Najkrótszy kod wygrywa.

Przykłady

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)

Edytować

Nie musisz stosować się do dokładnej formuły, a jedynie dać taki sam wynik jak powyższa formuła. Chciałbym również zobaczyć niektóre odpowiedzi dotyczące samej formuły.

jimmy23013
źródło
Czy najpierw powinniśmy przekonwertować z sRGB na skalę liniową? Myślę, że powinniśmy, ale wydaje się, że nikt dotąd nie miał.
John Dvorak,
@JanDvorak Zadaniem jest obliczenie odcienia w najprostszej definicji . W tym przypadku „najprostszy” oznacza, że ​​powinieneś założyć, że dane wejściowe są już w odpowiedniej skali i użyć dokładnej formuły podanej w pytaniu lub czegokolwiek, co daje ten sam wynik.
jimmy23013,
Ale ... 24 pb zwykle oznacza sRGB. Jeśli nie, specyfikacja formatu (ty) powinna określać inaczej.
John Dvorak,
@JanDvorak Tej definicji należy użyć dla RGB i odcienia.
jimmy23013,
9
Trzeba powiedzieć: huehuehue.
TheDoctor,

Odpowiedzi:

6

Pyth, 27 bajtów

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

Demonstracja. Uprząż testowa.

Fomula pochodzi z Wikipedii .

Zasadniczo kroki są następujące:

  1. .<QJxQKeSQ: Roate największa wartość na początku listy.
  2. -Ft: Weź różnicę z pozostałych dwóch wartości.
  3. -KhSQ: Odejmij wartość minimalną od wartości maksymalnej.
  4. c: Podziel 2 przez 3.
  5. + ... yJ Dodaj dwukrotnie indeks maksymalnej wartości z listy (0, jeśli R, 2, jeśli G, 4, jeśli B).
  6. % ... 6: Mod 6, aby naprawić problemy z negatywami.
  7. *60: Pomnóż przez 60, aby przeliczyć na stopnie i wydrukować.
isaacg
źródło
9

C #, 188 210 206 197 191 bajtów

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

Dzięki Sok za uratowanie 4 bajtów i SLuck49 za uratowanie 15!

ProgramFOX
źródło
Ponieważ używasz tylko zraz w obliczeniach wyjściowych i nie używasz go w poprzednich obliczeniach, usuwasz zmienną i zmieniasz dane wyjściowe na return(int)((c-d)*(1+(x-y)/(double)(x-a[0]))/2+d);, oszczędzając ci 4 bajty.
Sok
Można współczynnik 120 OUT ci dzadań oraz do zwrotu jak ta c=x==g?1:(x==b?2:(y==b?3:0)),d=y==g?1:(y==b?2:(x==b?3:0)), a następnie return(int)((c-d)*120*(1+(x-y)/(double)(x-a[0]))/2+d*120);zapisać 4 bajty.
SLuck49,
Czy naprawdę potrzebujesz obsady double? Jeśli tak, możesz użyć tego zamiast tego, (x-a[0])*1Daby zapisać kolejne 5 bajtów.
SLuck49,
@ SLuck49 Dzięki! Tak, naprawdę potrzebuję obsady, w przeciwnym razie daje niedokładne wyniki, ale to *1Dpomnożenie jest fajną sztuczką!
ProgramFOX,
Również (właśnie zauważyłem) możesz porzucić używanie wszystkich razem, w pełni kwalifikując się System.Arrayna kolejne 6 bajtów.
SLuck49,
8

Pyth 41 55 53 51 bajtów

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

Dane wejściowe są oczekiwane w formularzu r,g,b. Oto wyjaśnienie:

                                                        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)

Zaoszczędź 4 bajty dzięki @Jakube i @isaacg

Sok
źródło
@ jimmy23013 Naprawiono, dziękuję za dodatkowy przypadek testowy
Sok
1
Kilka golfów: m*120d-> *L120, zapisz eeJdo Kinline, aby zapisać kolejny bajt.
isaacg,
@isaacg Nie wiedziałem, że Loperator automatycznie wygenerował zakres na int, każdy dzień wydaje się świstym dniem: o) Dzięki!
Sok
8

JavaScript (ES6), 145 115 108 100 97 90 bajtów

Zwraca liczbę zmiennoprzecinkową. Przypisz do funkcji, której chcesz użyć.

(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)

Zaoszczędzono 30 bajtów, umieszczając wszystko w jednej sekwencji operatora trójskładnikowego i czekając do końca na normalizację do 0-360.

Dzięki edc65, Vasu Adari i produktom ETH dla oszczędności jeszcze większej liczby bajtów.

JSFiddle z testami. Wypróbuj w przeglądarce Firefox.

Jeśli usunięcie deklaracji funkcji h=jest niezgodne z prawem, dodaj 2 bajty.

DankMemes
źródło
Możesz usunąć „var” i niektóre bajty.
Vasu Adari,
ES6Fiddle z jakiegoś powodu potrzebuje deklaracji var i nie zdawałem sobie sprawy, że nie było to konieczne, dopóki nie wypróbowałem ES6 w
firefoxie
1
Możesz zapisać 6 bajtów, zastępując nawiasy klamrowe nawiasami, średnik przecinkiem i usuwając return. h=
Wydaje
Może to być obsesyjne (z drugiej strony, czyż nie wszyscy są dobrymi golfistami?;)), Ale można zaoszczędzić jeszcze dwa bajty, pozbywając się nawiasu %6)*60i partnera po drugiej stronie. Ponadto użycie brutalnej siły przy dodawaniu (zamiast dodawania 6 na końcu) pozwoliłoby zaoszczędzić jeden bajt w stosunku do bieżącej konfiguracji. (((x==r?(g-b)/m:x==g?2+(b-r)/m:4+(r-g)/m)+6)%6)*60stałby się (x==r?6+(g-b)/m:x==g?8+(b-r)/m:10+(r-g)/m)%6*60.
ETHprodukcje
1
+1 za sortowanie, bardzo sprytne, To jest 90 (lub 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

Oktawa, 65 60 50 bajtów

Edycja: Zapisane 10 bajtów dzięki pawel.boczarski

Przybliżone rozwiązanie ...

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

Testowe uruchomienie

@(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

Oktawa, 107 bajtów

Moje oryginalne (dokładnie takie) rozwiązanie ...

Kod:

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

Wyjaśnił:

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

Ta funkcja przyjmuje na wejściu wektor zawierający wartości R, G, B ci sortuje dane wejściowe w porządku rosnącym

  • b zawiera posortowane wartości [z, y, x]
  • i zawiera płaszczyznę RGB związaną z każdą wartością w b

Wektor hjest zapełniany wartościami

  • 60*[6, 2, 4]= [360, 120, 240](ale 3 bajty krótsze)
  • chyba że najniższą wartością jest Blue ( i(1) == 3), w którym to przypadku pierwsza wartość odcienia staje się zero
  • następnie użyj, (i)aby zmienić kolejność hw [h(Z), h(Y), h(X)]kolejności

Stamtąd jest to prosta transkrypcja formuły. Możesz spróbować tutaj .

zlewka
źródło
Wskazówka: użyj anonimowej notacji funkcji, aby wycisnąć więcej bajtów: @(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)jest dziesięć bajtów krótszych niż definicja ze functionsłowem kluczowym.
pawel.boczarski
@ pawel.boczarski Zastanawiałem się, czy mógłbym całkowicie pozbyć się nagłówka funkcji, ale nie wiem, czy to prawda. Ale dziękuję za wskazówkę! : D
zlewka
@ pawel.boczarski Patrząc wstecz, wciąż potrzebuję r=przed anonimową funkcją, aby ją nazwać, prawda?
zlewka
Istnieje wiele rozwiązań, w których wysyłane są anonimowe funkcje. Co więcej, możesz wywołać tak zdefiniowaną funkcję nawet w ten sposób: (@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360))([127 247 103])lub argumentować, że możesz użyć anszmiennej zaraz po zdefiniowaniu funkcji anonimowej, aby przypisanie nie było konieczne do zakończenia definicji funkcji. W jednym z wyzwań ( codegolf.stackexchange.com/questions/54945 ) uchwyt istniejącej funkcji biblioteki Matlaba został opublikowany jako pełne rozwiązanie.
pawel.boczarski
@ pawel.boczarski Wow, to ... po prostu ... zło: DI powinien wiedzieć, że Luis będzie w to zamieszany. Powrócę do pierwotnego kodu i użyję go answ próbce. Dzięki jeszcze raz!
zlewka
5

Pyth, 55

Wiem, że odpowiedź @ Soka przewyższa moją, ale ponieważ skończyłem moją zaraz po tym, jak on / ona opublikował, pomyślałem, że nadal będę pisać. To był mój pierwszy raz w Pythonie, więc jestem pewien, że popełniłem oczywiste błędy.

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

Dane wejściowe powinny być r, g, b. Możesz spróbować tutaj .

Rhyzomatic
źródło
Nie działa dla 255,165,245.
jimmy23013,
5

PowerShell, 232 226 222 161 bajtów

Zobacz historię zmian poprzednich wersji

$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)

Hoo chłopcze, zobaczmy, czy dam radę przez to przejść. Ponieważ \nliczy się tak samo, jak ;zostawiłem, linia łamie się dla jasności.

Pierwszy wiersz przyjmuje dane wejściowe jako trzy $argsi zapisuje je w $r, $g, $b. Naprawdę będziemy używać $bdopiero później, ale potrzebujemy wszystkich trzech, więc wszystko |sortdziała poprawnie. To sprawia, że $z, $y, $xod najmniejszych do największych argumentów wejściowych.

Kolejne dwie linie ustawiają $ci $dza pomocą wielu wywołań indeksu do tablicy, aby odpowiednio ustawić liczby. Praca z zewnątrz w, jeśli $xjest -eqseksualnego do $g(czyli zielony był największy), ustawiamy $c=1... else, jeśli $xjest -not equal do $b(czyli niebieski nie był największy) $cjest albo 0czy 3w zależności czy niebieski był drugim co do wielkości ... indziej $c=2. Podobne zestawy logiczne $d.

Następnie obliczamy i drukujemy dane wyjściowe w następujący sposób, który jest tylko algorytmem gry w golfa.

(($c-$d)*120*(1+($x-$y)/($x-$z))/2+$d*120)
AdmBorkBork
źródło
1
Nie znam PowerShell, więc popraw mnie, jeśli się mylę ... Nie używasz $zpodczas obliczania $club $d, i używasz go tylko raz w obliczeniach wyjściowych, więc możesz się go $zcałkowicie pozbyć i zastąpić $a[0]?
Sok
4

Ruby, 117 96 94 bajtów

Kod:

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}
  • Zaoszczędzono 21 bajtów poprzez usunięcie ()i użycie zmiennych r, g, b.
  • Przyjmowanie modułu 6 w celu konwersji wartości ujemnej i pomnożenie go przez 60 w celu konwersji na stopnie, które pozwoliły zaoszczędzić 2 bajty.

Przykłady:

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
Vasu Adari
źródło
3

SWI-Prolog, 133 bajty

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

Przykład: a([255,165,245],Hue). wyjściaHue = 306.666666666666 .

Wykorzystuje się następującą formułę:

  • Max = max(R,G,B), Min = min(R,G,B).
  • Jeśli Max = R, U = 0. Else if Max = G, U = 2. Indziej U = 4.
  • Jeśli Max = R, I = Gi J = B. Else if Max = G, I = Bi J = R. W przeciwnym razie I = Ri J = G.
  • Z = U + (I - J)/(Max - Min)
  • Huejest albo Zalbo Z + 360jeśli Z < 0.
Fatalizować
źródło
Zaokrąglanie jest opcjonalne.
jimmy23013,
@ jimmy23013 Zaktualizowano, dziękuję.
Fatalize
3

Perl 5, 138 132 119 bajtów

Kod:

($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

Uwagi:

Z pewnością Perl nie może wygrać takiego wyzwania z całym golfem w Pyth'oresque. Ale zastanawiałem się, czy można to zrobić tylko z 1 krokiem obliczeniowym. Dzięki modułowi, który dobrze się sprawdził. :)

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
LukStorms
źródło
w porównaniu do wartości środkowej zamiast maksymalnej wygolonej niektóre bajty. (== versus>)
LukStorms
1

C ++ 276 bajtów

#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);}
EvgeniyZh
źródło
Podpowiedź: możesz opuścić Hfunkcję sama odpowiedź, jak w code-golf funkcja samodzielna jest uzasadniony odpowiedź ekwiwalent pełnego programu vide meta dyskusja: meta.codegolf.stackexchange.com/questions/2419/... . To sprawi, że twoja odpowiedź będzie bardziej konkurencyjna (w twoim przypadku zaoszczędź 100 bajtów). Nadal zachęcamy do pozostawienia „pełnej” wersji programu pod rozwiązaniem, aby uprościć testowanie.
pawel.boczarski
Drugi przypadek testowy 127 247 103zwraca niepoprawną wartość -120zamiast 110.
pawel.boczarski
1

R, 125 bajtów

Bardzo podobny do roztworu Octave zlewki. Wyjście zmiennoprzecinkowe.

Kod:

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

Przykłady:

> 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
popojan
źródło
1

Python, 154 bajty

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

Akceptuje listę wartości. Nie jestem pewien, czy można to dalej rozbić. Tutaj nie jest golfem:

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
Zaxvo
źródło
0

JavaScript 108

Metoda alternatywna.

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

Przy użyciu przykładowej metody.

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>

wolfhammer
źródło