Rona warna

23

Anda diberi nilai warna RGB. Tugas Anda sederhana: untuk menghitung rona, dalam definisi paling sederhana.

Katakanlah saluran dengan nilai tertinggi, menengah dan terendah adalah X, Y, Z (yang berwarna merah, hijau atau biru) dan nilainya adalah x, y, z. Rona warna ini adalah (h (X) -h (Y)) * (1 + (xy) / (xz)) / 2 + h (Y), di mana:

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

Input terdiri dari 3 bilangan bulat dari 0 hingga 255 yang tidak semuanya sama, dalam urutan yang konsisten. Outputnya bisa berupa float, atau bilangan bulat dibulatkan ke atas atau ke bawah, yang tidak harus konsisten. Jika bagian integer dari output adalah 0 atau 360, Anda dapat mencetak salah satunya.

Anda tidak dapat memanggil builtin untuk konversi ruang warna, termasuk konversi tersirat seperti saat memanipulasi gambar.

Ini adalah kode-golf. Kode terpendek menang.

Contohnya

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)

Edit

Anda tidak harus mengikuti rumus yang tepat, tetapi hanya harus memberikan hasil yang sama dengan rumus di atas. Saya juga ingin melihat beberapa jawaban menggunakan rumus itu sendiri.

jimmy23013
sumber
Haruskah kita mengonversi dari sRGB ke skala linier terlebih dahulu? Saya pikir kita harus, tetapi tampaknya tidak ada yang sejauh ini.
John Dvorak
@ JanDvorak Tugasnya adalah menghitung rona, dalam definisi paling sederhana . Dalam hal ini, "paling sederhana" berarti Anda harus menganggap input sudah dalam skala yang tepat, dan menggunakan rumus tepat yang diberikan dalam pertanyaan atau apa pun yang memberikan hasil yang sama.
jimmy23013
Tapi ... 24 bpp biasanya berarti sRGB. Jika tidak, spesifikasi format (Anda) harus menentukan sebaliknya.
John Dvorak
@ JanDvorak Anda harus menggunakan definisi ini untuk RGB dan rona.
jimmy23013
9
Harus dikatakan: huehuehue.
TheDoctor

Jawaban:

6

Pyth, 27 byte

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

Demonstrasi. Uji harness.

Fomula diambil dari Wikipedia .

Intinya, langkah-langkahnya adalah:

  1. .<QJxQKeSQ: Roate nilai terbesar ke depan daftar.
  2. -Ft: Ambil perbedaan dari dua nilai lainnya.
  3. -KhSQ: Kurangi nilai minimum dari nilai maksimum.
  4. c: Bagi 2 dengan 3.
  5. + ... yJ Tambahkan dua kali indeks dari nilai maksimum dalam daftar (0 jika R, 2 jika G, 4 jika B).
  6. % ... 6: Mod 6, untuk memperbaiki masalah dengan negatif.
  7. *60: Kalikan dengan 60 untuk mengkonversi ke derajat, dan cetak.
isaacg
sumber
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);}

Terima kasih kepada Sok karena telah menghemat 4 byte dan untuk SLuck49 karena telah menghemat 15!

ProgramFOX
sumber
Karena Anda hanya menggunakan zsatu kali dalam perhitungan output, dan Anda tidak menggunakannya dalam perhitungan sebelumnya, Anda menghapus variabel dan mengubah output return(int)((c-d)*(1+(x-y)/(double)(x-a[0]))/2+d);, menghemat Anda 4 byte.
Sok
Anda dapat memfaktorkan 120 dari cdan dtugas ke dalam pengembalian seperti ini c=x==g?1:(x==b?2:(y==b?3:0)),d=y==g?1:(y==b?2:(x==b?3:0))dan kemudian return(int)((c-d)*120*(1+(x-y)/(double)(x-a[0]))/2+d*120);menyimpan 4 byte.
SLuck49
Juga apakah Anda benar-benar membutuhkan pemeran double? Jika Anda melakukannya, Anda dapat menggunakan ini sebagai gantinya (x-a[0])*1Duntuk menyimpan 5 byte lainnya.
SLuck49
@ SLuck49 Terima kasih! Ya, saya benar-benar membutuhkan para pemain, itu memberikan hasil yang tidak akurat sebaliknya, tetapi *1Dperkalian itu adalah trik yang bagus!
ProgramFOX
Juga (perhatikan) Anda dapat menggunakan semua bersama-sama dengan sepenuhnya memenuhi syarat System.Arrayuntuk 6 byte lainnya.
SLuck49
8

Pyth, 41 55 53 51 byte

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

Masukan diharapkan dalam bentuk r,g,b. Berikut penjelasannya:

                                                        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)

Disimpan 4 byte, terima kasih kepada @Jakube dan @isaacg

Sok
sumber
@ jimmy23013 Tetap, terima kasih untuk test case ekstra
Sok
1
Beberapa golf: m*120d-> *L120, simpan eeJke Kinline untuk menyimpan byte lain.
isaacg
@isaacg Saya tidak tahu Loperator menghasilkan kisaran pada int secara otomatis, setiap hari sepertinya hari shcool: o) Terima kasih!
Sok
8

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

Pengembalian mengapung. Tetapkan ke fungsi yang akan digunakan.

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

Menyimpan 30 byte dengan mengurutkan semuanya ke dalam urutan operator ternary tunggal dan menunggu hingga akhir normal ke 0-360.

Berkat edc65, Vasu Adari, dan produk ETH untuk menghemat lebih banyak byte.

JSFiddle dengan tes. Coba di Firefox.

Jika menghapus deklarasi fungsi h=tidak sah, tambahkan 2 byte.

DankMemes
sumber
Anda dapat menghapus 'var' dan beberapa byte.
Vasu Adari
ES6Fiddle membutuhkan deklarasi var untuk beberapa alasan dan saya tidak menyadari itu tidak perlu sampai saya mencoba ES6 di firefox
DankMemes
1
Anda dapat menyimpan 6 byte dengan mengganti kurung kurawal dengan tanda kurung, tanda koma dengan koma, dan menghapus return. Saya percaya menghapus deklarasi fungsi ( h=) juga legal, sehingga totalnya turun menjadi 100.
ETHproduksi
Ini mungkin obsesif (sekali lagi, bukan semua pegolf yang baik?;)), Tetapi Anda bisa menghemat dua byte lagi dengan menyingkirkan tanda kurung di dalam %6)*60dan mitranya di sisi lain. Selain itu, menggunakan brute force pada penambahan (alih-alih menambahkan 6 di akhir) sebenarnya akan menghemat satu byte pada pengaturan Anda saat ini. (((x==r?(g-b)/m:x==g?2+(b-r)/m:4+(r-g)/m)+6)%6)*60akan menjadi (x==r?6+(g-b)/m:x==g?8+(b-r)/m:10+(r-g)/m)%6*60.
ETHproduksi
1
+1 untuk pengurutan, sangat cerdas, Ini 90 (atau 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

Oktaf, 65 60 50 byte

Sunting: Disimpan 10 byte berkat pawel.boczarski

Solusi perkiraan ...

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

Uji coba

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

Oktaf, 107 byte

Solusi orisinal (tepat) saya ...

Kode:

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

Dijelaskan:

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

Fungsi ini mengambil vektor yang berisi nilai R, G, B sebagai input cdan mengurutkan input dalam urutan menaik

  • b berisi nilai yang diurutkan [z, y, x]
  • i berisi bidang RGB yang terkait dengan setiap nilai dalam b

Vektor hdiisi dengan nilai-nilai

  • 60*[6, 2, 4]= [360, 120, 240](tetapi lebih pendek 3 byte)
  • kecuali nilai terendah dalam i(1) == 3warna Biru ( ), dalam hal ini nilai rona pertama menjadi nol
  • kemudian gunakan (i)untuk mengatur ulang hke [h(Z), h(Y), h(X)]urutan

Dari sana hanya transkripsi formula yang lurus. Anda bisa mencobanya di sini .

gelas kimia
sumber
Petunjuk: gunakan notasi fungsi anonim untuk memeras lebih banyak byte: @(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)sepuluh byte lebih pendek dari definisi dengan functionkata kunci.
pawel.boczarski
@ pawel.boczarski Saya bertanya-tanya apakah saya bisa menghapus fungsi header sama sekali, tapi saya tidak tahu apakah itu sah. Tapi terima kasih atas tipnya! : D
gelas kimia
@ pawel.boczarski Melihat kembali ini, saya masih membutuhkan r=fungsi anonim sebelum menyebutnya, kan?
Gelas kimia
Ada banyak solusi di mana fungsi anonim diposting. Selain itu, Anda dapat memanggil fungsi yang didefinisikan bahkan seperti ini (@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360))([127 247 103]):, atau berpendapat bahwa Anda dapat menggunakan ansvariabel segera setelah fungsi anonim ditentukan, sehingga penugasan tidak perlu untuk menyelesaikan definisi fungsi. Dalam satu tantangan ( codegolf.stackexchange.com/questions/54945 ) menangani fungsi perpustakaan Matlab yang ada diposting sebagai solusi lengkap.
pawel.boczarski
@ pawel.boczarski Wow, itu ... hanya ... jahat: DI seharusnya tahu Luis akan terlibat. Saya akan kembali ke kode asli dan menggunakannya ansdalam sampel. Terima kasih lagi!
Gelas kimia
5

Pyth, 55

Saya tahu jawaban Sok mengalahkan saya, tetapi karena saya menyelesaikan jawaban saya tepat setelah dia diposting, saya pikir saya masih akan memposting. Ini adalah pertama kalinya saya menggunakan Pyth jadi saya yakin saya membuat beberapa kesalahan yang jelas.

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

Input diharapkan r, g, b. Anda bisa mencobanya di sini .

Berirama
sumber
Tidak berhasil 255,165,245.
jimmy23013
5

PowerShell, 232 226 222 161 Bytes

Lihat riwayat revisi untuk versi sebelumnya

$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, mari kita lihat apakah saya bisa berjalan melalui ini. Karena \ndihitung sama dengan ;saya meninggalkan garis istirahat untuk kejelasan.

Baris pertama mengambil input sebanyak tiga $argsdan menyimpannya $r, $g, $b. Kami benar-benar hanya akan menggunakan $bnanti, tetapi kami membutuhkan ketiganya agar |sortbekerja dengan tepat. Ini membuat $z, $y, $xargumen input input terkecil hingga terbesar.

Pengaturan dua baris berikutnya $cdan $ddengan menggunakan beberapa panggilan indeks-ke-an-array untuk mengatur angka-angka dengan tepat. Bekerja dari luar, kalau $xada-eq ual ke $g(yaitu, hijau adalah yang terbesar), kami menetapkan $c=1... lain, jika $xadalah -not equal ke $b(yaitu, biru itu bukan yang terbesar) $cadalah baik 0atau 3tergantung jika biru adalah yang terbesar kedua ... yang lain $c=2,. Set logika serupa $d.

Kami kemudian menghitung dan mencetak output dengan yang berikut, yang hanya merupakan algoritma dari tantangan golf sedikit.

(($c-$d)*120*(1+($x-$y)/($x-$z))/2+$d*120)
AdmBorkBork
sumber
1
Saya tidak tahu PowerShell, jadi koreksi saya jika saya salah ... Anda tidak menggunakan $zsaat menghitung $catau $d, dan Anda hanya menggunakannya sekali dalam perhitungan output, jadi bisakah Anda menyingkirkan $zseluruhnya dan menggantinya dengan $a[0]?
Sok
4

Rubi, 117 96 94 byte

Kode:

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}
  • Disimpan 21 byte dengan menghapus ()dan menggunakan variabel r, g, b.
  • Mengambil modulus 6 untuk mengonversi nilai negatif dan mengalikannya dengan 60 untuk mengonversi ke derajat yang menghemat 2 byte.

Contoh:

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

Contoh: a([255,165,245],Hue).keluaranHue = 306.666666666666 .

Ini menggunakan rumus berikut:

  • Max = max(R,G,B), Min = min(R,G,B).
  • Jika Max = R, U = 0. Lain jika Max = G, U = 2. Lain U = 4.
  • Jika Max = R, I = Gdan J = B. Jika tidak Max = G, I = Bdan J = R. Lain I = Rdan J = G.
  • Z = U + (I - J)/(Max - Min)
  • Hueapakah Zatau Z + 360jika Z < 0.
Fatalisasi
sumber
Pembulatan adalah opsional.
jimmy23013
@ jimmy23013 Diperbarui, terima kasih.
Fatalkan
3

Perl 5, 138 132 119 byte

Kode:

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

Komentar:

Tentunya Perl tidak dapat memenangkan tantangan seperti itu dengan semua golf Pyth'oresque. Tetapi saya bertanya-tanya apakah ini mungkin dilakukan hanya dengan 1 langkah perhitungan. Berkat modulus yang bekerja dengan baik. :)

Uji:

$ 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
sumber
membandingkan dengan nilai tengah bukannya maksimum yang dicukur beberapa byte. (== versus>)
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);}
EvgeniyZh
sumber
Sebuah petunjuk: Anda dapat meninggalkan Hfungsi sendirian dalam jawabannya, seperti pada kode-golf fungsi mandiri adalah jawaban yang sah, setara dengan program penuh, vide meta diskusi: meta.codegolf.stackexchange.com/questions/2419/… . Ini akan membuat jawaban Anda lebih kompetitif (hemat 100 byte untuk casing Anda). Anda masih didorong untuk meninggalkan versi "penuh" program di bawah solusi untuk menyederhanakan pengujian.
pawel.boczarski
Kasus uji kedua 127 247 103menghasilkan nilai yang tidak valid, -120bukan 110.
pawel.boczarski
1

R, 125 byte

Sangat mirip dengan solusi Oktaf pengocok. Output titik mengambang.

Kode:

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

Contoh:

> 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
sumber
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

Menerima daftar nilai. Tidak yakin apakah ini dapat diuraikan lebih lanjut. Ini dia 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
Zaxvo
sumber
0

JavaScript 108

Metode alternatif.

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

Menggunakan metode contoh.

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
sumber