Màu sắc của một màu


23

Bạn được cung cấp các giá trị RGB của một màu. Nhiệm vụ của bạn rất đơn giản: để tính màu sắc, theo định nghĩa đơn giản nhất.

Giả sử các kênh có giá trị cao nhất, trung bình và thấp nhất là X, Y, Z (có màu đỏ, xanh lục hoặc xanh lam) và các giá trị của chúng là x, y, z. Màu sắc của màu này là (h (X) -h (Y)) * (1 + (xy) / (xz)) / 2 + h (Y), trong đó:

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

Đầu vào bao gồm 3 số nguyên từ 0 đến 255 không bằng nhau, theo bất kỳ thứ tự nhất quán nào. Đầu ra có thể là số float hoặc số nguyên được làm tròn lên hoặc xuống, không nhất quán. Nếu phần nguyên của đầu ra là 0 hoặc 360, bạn có thể in một trong số chúng.

Bạn không thể gọi nội trang để chuyển đổi không gian màu, bao gồm các chuyển đổi ngầm định như trong khi thao tác với hình ảnh.

Đây là mã golf. Mã ngắn nhất sẽ thắng.

Ví dụ

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)

Chỉnh sửa

Bạn không phải tuân theo công thức chính xác, mà chỉ phải đưa ra kết quả tương tự như công thức trên. Tôi cũng muốn xem một số câu trả lời chơi golf công thức.


Chúng ta có nên chuyển đổi từ sRGB sang quy mô tuyến tính trước không? Tôi nghĩ rằng chúng ta nên, nhưng dường như không ai có được cho đến nay.
John Dvorak

@JanDvorak Nhiệm vụ là tính toán màu sắc, theo định nghĩa đơn giản nhất . Trong trường hợp này, "đơn giản nhất" có nghĩa là bạn nên cho rằng đầu vào đã ở đúng tỷ lệ và sử dụng công thức chính xác được đưa ra trong câu hỏi hoặc bất cứ điều gì cho kết quả tương tự.
jimmy23013

Nhưng ... 24 bpp thường có nghĩa là sRGB. Nếu không, đặc tả định dạng (bạn) sẽ chỉ định khác.
John Dvorak

@JanDvorak Bạn nên sử dụng định nghĩa này cho RGB và màu sắc.
jimmy23013

9
Nó phải được nói: huehuehue.
TheDoctor

Câu trả lời:


6

Bình thường, 27 byte

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

Trình diễn. Khai thác thử nghiệm.

Fomula lấy từ Wikipedia .

Về cơ bản, các bước là:

  1. .<QJxQKeSQ: Roate giá trị lớn nhất vào phía trước của danh sách.
  2. -Ft: Lấy sự khác biệt của hai giá trị còn lại.
  3. -KhSQ: Trừ giá trị tối thiểu khỏi giá trị tối đa.
  4. c: Chia 2 cho 3.
  5. + ... yJ Thêm hai lần chỉ số của giá trị tối đa trong danh sách (0 nếu R, 2 nếu G, 4 nếu B).
  6. % ... 6: Mod 6, để khắc phục các vấn đề với tiêu cực.
  7. *60: Nhân với 60 để chuyển đổi sang độ và in.

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

Cảm ơn Sok vì đã lưu 4 byte và SLuck49 để lưu 15!


Vì bạn chỉ sử dụng zmột lần trong tính toán đầu ra và bạn không sử dụng nó trong các tính toán trước đó, bạn loại bỏ biến và thay đổi đầu ra thành return(int)((c-d)*(1+(x-y)/(double)(x-a[0]))/2+d);, tiết kiệm cho bạn 4 byte.
Sok

Bạn có thể yếu tố 120 ra khỏi cdbài tập và vào sự trở lại như thế này c=x==g?1:(x==b?2:(y==b?3:0)),d=y==g?1:(y==b?2:(x==b?3:0))và sau đó return(int)((c-d)*120*(1+(x-y)/(double)(x-a[0]))/2+d*120);để tiết kiệm 4 byte.
SLuck49

Ngoài ra bạn có thực sự cần các diễn viên để double? Nếu bạn làm, bạn có thể sử dụng điều này thay vì (x-a[0])*1Dđể lưu thêm 5 byte.
SLuck49

@ SLuck49 Cảm ơn! Vâng, tôi thực sự cần diễn viên, nó cho kết quả không chính xác nếu không, nhưng *1Dphép nhân đó là một mẹo hay!
Chương trìnhFOX

Ngoài ra (chỉ cần chú ý) bạn có thể kết hợp sử dụng tất cả lại với nhau bằng cách đủ điều kiện System.Arraynhận thêm 6 byte.
SLuck49

8

Bình thường 41 55 53 51 byte

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

Đầu vào dự kiến ​​trong mẫu r,g,b. Đây là một lời giải thích:

                                                        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)

Đã lưu 4 byte, nhờ @Jakube và @isaacg


@ jimmy23013 Đã sửa, cảm ơn vì trường hợp thử nghiệm thêm
Sok

1
Một vài golf: m*120d-> *L120, lưu eeJvào Knội tuyến để lưu một byte khác.
isaacg

@isaacg Tôi không biết Ltoán tử tự động tạo một phạm vi trên một int, mỗi ngày là một ngày shcool có vẻ như: o) Cảm ơn!
Sok

8

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

Trả lại phao. Gán cho một chức năng để sử dụng.

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

Đã lưu 30 byte bằng cách nội tuyến mọi thứ vào một chuỗi toán tử ternary duy nhất và đợi cho đến khi kết thúc bình thường hóa thành 0-360.

Cảm ơn edc65, Vasu Adari và ETHproductions để lưu nhiều byte hơn.

JSFiddle với các bài kiểm tra. Hãy thử trong Firefox.

Nếu loại bỏ khai báo hàm h=là không hợp pháp, thêm 2 byte.


Bạn có thể xóa 'var' và một số byte.
Vasu Adari

ES6Fiddle cần khai báo var vì một số lý do và tôi đã không nhận ra điều đó là không cần thiết cho đến khi tôi thử ES6 trong firefox
DankMeme

1
Bạn có thể lưu 6 byte bằng cách thay thế dấu ngoặc nhọn bằng dấu ngoặc đơn, dấu chấm phẩy bằng dấu phẩy và xóa return. Tôi tin rằng việc xóa khai báo hàm ( h=) cũng là hợp pháp, nâng tổng số xuống còn 100.
Sản phẩm ETH

Điều này có thể gây ám ảnh (sau đó một lần nữa, không phải tất cả những người chơi golf giỏi ?;)), Nhưng bạn có thể tiết kiệm thêm hai byte bằng cách loại bỏ dấu ngoặc đơn %6)*60và đối tác của nó ở phía bên kia. Ngoài ra, sử dụng sức mạnh vũ phu cho phần bổ sung (thay vì thêm 6 ở cuối) sẽ thực sự tiết kiệm một byte so với thiết lập hiện tại của bạn. (((x==r?(g-b)/m:x==g?2+(b-r)/m:4+(r-g)/m)+6)%6)*60sẽ trở thành (x==r?6+(g-b)/m:x==g?8+(b-r)/m:10+(r-g)/m)%6*60.
Sản phẩm ETH

1
+1 cho loại, rất thông minh, Đây là 90 (hoặc 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

Octave, 65 60 50 byte

Chỉnh sửa: Đã lưu 10 byte nhờ pawel.boczarski

Một giải pháp gần đúng ...

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

Chạy thử nghiệm

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

Octave, 107 byte

Giải pháp ban đầu (chính xác-ish) của tôi ...

Mã số:

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

Giải thích:

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

Hàm này lấy một vectơ chứa các giá trị R, G, B làm đầu vào cvà sắp xếp đầu vào theo thứ tự tăng dần

  • b chứa các giá trị được sắp xếp [z, y, x]
  • i chứa mặt phẳng RGB được liên kết với mỗi giá trị trong b

Vectơ hđược điền với các giá trị

  • 60*[6, 2, 4]= [360, 120, 240](nhưng ngắn hơn 3 byte)
  • trừ khi giá trị thấp nhất là màu xanh lam ( i(1) == 3), trong trường hợp đó, giá trị màu đầu tiên trở thành 0
  • sau đó sử dụng (i)để sắp xếp lại hthành [h(Z), h(Y), h(X)]trật tự

Từ đó, nó chỉ là một phiên âm thẳng của công thức. Bạn có thể thử nó ở đây .


Gợi ý: sử dụng ký hiệu hàm ẩn danh để nén nhiều byte hơn: @(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)ngắn hơn mười byte so với định nghĩa với functiontừ khóa.
pawel.boczarski

@ pawel.boczarski Tôi đã tự hỏi liệu tôi có thể loại bỏ hoàn toàn tiêu đề chức năng không, nhưng tôi không biết liệu điều đó có hợp pháp không. Nhưng cảm ơn về tiền boa! : D
cốc

@ pawel.boczarski Nhìn lại điều này, tôi vẫn cần một r=chức năng ẩn danh để gọi nó, phải không?
cốc

Có nhiều giải pháp mà chức năng ẩn danh được đăng. Hơn nữa, bạn có thể gọi hàm được định nghĩa như thế này: (@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360))([127 247 103])hoặc tranh luận rằng bạn có thể sử dụng ansbiến ngay sau khi hàm ẩn danh được xác định, do đó việc gán định nghĩa là không cần thiết để hoàn thành định nghĩa hàm. Trong một thử thách ( codegolf.stackexchange.com/questions/54945 ), một chức năng của thư viện Matlab hiện có đã được đăng dưới dạng giải pháp đầy đủ.
pawel.boczarski

@ pawel.boczarski Wow, đó là ... chỉ là ... ác: DI nên biết Luis sẽ tham gia. Tôi sẽ trở lại mã gốc và sử dụng anstrong mẫu. Cảm ơn một lần nữa!
cốc

5

Bình thường, 55

Tôi biết câu trả lời của @ Sok đánh bại tôi, nhưng vì tôi đã hoàn thành câu trả lời của mình ngay sau khi anh ấy / cô ấy đăng bài, tôi nghĩ tôi vẫn sẽ đăng. Đây là lần đầu tiên tôi sử dụng Pyth nên tôi chắc chắn mình đã mắc một số sai lầm rõ ràng.

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

Đầu vào dự kiến ​​sẽ được r, g, b. Bạn có thể thử nó ở đây .


Không làm việc cho 255,165,245.
jimmy23013

5

PowerShell, 232 226 222 161 byte

Xem lịch sử sửa đổi cho các phiên bản trước

$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 boy, hãy xem tôi có thể đi qua đây không. Kể từ khi \nđếm giống như ;tôi rời khỏi dòng ngắt cho rõ ràng.

Dòng đầu tiên lấy đầu vào là ba $argsvà lưu trữ chúng vào $r, $g, $b. Chúng tôi thực sự sẽ chỉ sử dụng $bsau này, nhưng chúng tôi cần cả ba để các |sortcông trình phù hợp. Điều này làm cho $z, $y, $xcác đối số đầu vào nhỏ nhất đến lớn nhất.

Hai dòng tiếp theo thiết lập $c$dbằng cách sử dụng nhiều lệnh gọi thành một mảng để đặt các số một cách thích hợp. Làm việc từ bên ngoài vào, nếu $x-equal đến $g(ví dụ, màu xanh lá cây là lớn nhất), chúng tôi đặt $c=1... else, nếu $x-not equal đến $b(ví dụ, màu xanh không phải là lớn nhất) $clà một trong hai 0hoặc 3tuỳ nếu màu xanh là lớn thứ hai ... khác , $c=2. Bộ logic tương tự $d.

Sau đó, chúng tôi tính toán và in kết quả đầu ra với phần sau, đây chỉ là thuật toán từ thử thách được chơi một chút.

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

1
Tôi không biết PowerShell, vì vậy hãy sửa cho tôi nếu tôi sai ... Bạn không sử dụng $zkhi tính toán $c$d, và bạn chỉ sử dụng nó một lần trong tính toán đầu ra, vì vậy bạn có thể loại bỏ $zhoàn toàn và thay thế bằng $a[0]không?
Sok

4

Ruby, 117 96 94 byte

Mã số:

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}
  • Đã lưu 21 byte bằng cách loại bỏ ()và sử dụng các biến r, g, b.
  • Lấy mô đun 6 để chuyển đổi giá trị âm và nhân nó với 60 để chuyển đổi thành độ đã lưu 2 byte.

Ví dụ:

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

Ví dụ: a([255,165,245],Hue).đầu raHue = 306.666666666666 .

Điều này sử dụng công thức sau đây:

  • Max = max(R,G,B), Min = min(R,G,B).
  • Nếu Max = R, U = 0. Khác nếu Max = G, U = 2. Khác U = 4.
  • Nếu Max = R, I = GJ = B. Khác nếu Max = G, I = BJ = R. Khác I = RJ = G.
  • Z = U + (I - J)/(Max - Min)
  • HueZhoặc Z + 360nếu Z < 0.

Làm tròn là tùy chọn.
jimmy23013

@ jimmy23013 Cập nhật, cảm ơn.
Gây tử vong vào 23/8/2015

3

Perl 5, 138 132 119 byte

Mã số:

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

Nhận xét:

Chắc chắn Perl không thể chiến thắng thử thách như vậy với tất cả các môn đánh gôn của Pyth'oresque. Nhưng tôi tự hỏi nếu điều này có thể làm được chỉ với 1 bước tính toán. Nhờ các mô-đun làm việc độc đáo. :)

Kiểm tra:

$ 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

so với giá trị trung bình thay vì cạo tối đa một số byte. (== so với>)
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);}

Một gợi ý: bạn có thể để Hchức năng một mình trong câu trả lời, vì trong code-golf, hàm độc lập là một câu trả lời hợp pháp, tương đương với một chương trình đầy đủ, thảo luận về vide meta: meta.codegolf.stackexchange.com/questions/2419/ . Điều này sẽ làm cho câu trả lời của bạn cạnh tranh hơn (tiết kiệm 100 byte trong trường hợp của bạn). Bạn vẫn được khuyến khích để lại phiên bản "đầy đủ" của chương trình theo giải pháp để đơn giản hóa việc kiểm tra.
pawel.boczarski

Trường hợp thử nghiệm thứ hai 127 247 103mang lại giá trị không hợp lệ -120thay vì 110.
pawel.boczarski

1

R, 125 byte

Rất giống với giải pháp Octave của beaker. Đầu ra điểm nổi.

Mã số:

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

Ví dụ:

> 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

Chấp nhận một danh sách các giá trị. Không chắc chắn nếu điều này có thể được chia nhỏ hơn nữa. Đây là vô căn cứ:

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

Phương pháp luân phiên.

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

Sử dụng phương pháp ví dụ.

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>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.