Bir rengin tonu


23

Size bir rengin RGB değerleri verilir. Senin görevin basit: en basit tanımıyla, tonu hesaplamak için.

En yüksek, orta ve en düşük değere sahip kanalların X, Y, Z (kırmızı, yeşil veya mavi olan) ve değerlerinin x, y, z olduğunu söyleyin. Bu rengin tonu (h (X) -h (Y)) * (1 + (xy) / (xz)) / 2 + h (Y), burada:

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

Girdi, herhangi bir tutarlı düzende, tamamen eşit olmayan, 0 ile 255 arasında 3 tamsayıdan oluşur. Çıktı, tutarlı olması gerekmeyen yüzer veya tam sayılar ya da aşağı yuvarlanmış olabilir. Çıktının tamsayı kısmı 0 veya 360 ise, ikisinden birini yazdırabilirsiniz.

Bir görüntüyü işlerken olduğu gibi örtük dönüştürmeler de dahil olmak üzere, renk alanı dönüşümleri için yerleşikleri çağıramazsınız.

Bu kod golfü. En kısa kod kazanır.

Örnekler

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)

Düzenle

Tam formülü izlemeniz gerekmez, ancak yalnızca yukarıdaki formüldeki aynı sonucu vermeniz gerekir. Formülün kendisiyle ilgili bazı cevapları da görmek isterim.


Önce sRGB'den lineer ölçeğe dönüştürmeli miyiz? Sanırım yapmalıyız, ama şimdiye kadar kimse yok gibi görünüyor.
John Dvorak

@JanDvorak Görev, en basit tanımıyla renk tonunu hesaplamak . Bu durumda, "en basit", girişin zaten doğru ölçekte olduğunu varsaymanız ve soruda verilen formülü veya aynı sonucu veren herhangi bir şeyi kullanmanız gerektiği anlamına gelir.
jimmy23013 19:15

Ancak ... 24 bpp genellikle sRGB anlamına gelir. Aksi takdirde, format belirtimi (siz) aksi belirtilmelidir.
John Dvorak

@JanDvorak Bu tanımı RGB ve renk tonu için kullanmalısınız .
jimmy23013

9
Söylenmesi gerekir: huehuehue.
Doktor

Yanıtlar:


6

Pyth, 27 bayt

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

Gösteri. Test kablo demeti.

Fomula Vikipedi'den alınmıştır .

Temelde, adımlar şunlardır:

  1. .<QJxQKeSQ: En büyük değeri listenin önüne yönlendir.
  2. -Ft: Diğer iki değerin farkını alın.
  3. -KhSQ: Minimum değeri maksimum değerden çıkarın.
  4. c: 2'ye 3'e bölün.
  5. + ... yJ Listedeki maksimum değerin endeksini iki kez ekleyin (R ise 2, G ise 4, B ise 4).
  6. % ... 6: Mod 6, olumsuzluklarla ilgili sorunları gidermek için.
  7. *60: Derecelere dönüştürmek için 60 ile çarpın ve yazdırın.

9

C #, 188 210 206 197 191 bayt

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

4 byte'ı kaydettiği için Sok'e ve 15'i kaydettiği için SLuck49'a teşekkürler!


zÇıktı hesaplamasında yalnızca bir kez kullandığınız ve önceki hesaplamalarda kullanmadığınız için, değişkeni ortadan kaldırır ve çıktısını değiştirerek return(int)((c-d)*(1+(x-y)/(double)(x-a[0]))/2+d);4 bayttan tasarruf edersiniz.
Sok

120'den cve datamalardan ve bunun gibi geri dönüşe faktörü c=x==g?1:(x==b?2:(y==b?3:0)),d=y==g?1:(y==b?2:(x==b?3:0))ve return(int)((c-d)*120*(1+(x-y)/(double)(x-a[0]))/2+d*120);4 bayttan tasarruf edebilirsiniz.
SLuck49

Ayrıca oyuncu kadrosuna gerçekten ihtiyacın var doublemı? Bunu yaparsanız, (x-a[0])*1Dbaşka bir 5 bayt kaydetmek için bunu kullanabilirsiniz .
SLuck49

@ SLuck49 Teşekkürler! Evet, aslında oyuncu kadrosuna ihtiyacım var, aksi takdirde yanlış sonuçlar veriyor, ancak bu *1Dçarpma iyi bir numara!
ProgramFOX

Ayrıca (sadece farkedilmiş) ayrıca System.Array6 bayt için tam hak kazanarak hepsini bir arada bırakabilirsiniz .
SLuck49

8

Pyth, 41 55 53 51 bayt

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

Formda girdi bekleniyor r,g,b. İşte bir açıklama:

                                                        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)

@Jakube ve @isaacg sayesinde 4 byte kurtarıldı


@ jimmy23013 Sabit, ekstra test davası için teşekkürler
Sok

1
Birkaç golf: m*120d-> *L120, başka bir bayttan tasarruf eeJetmek için Ksatıra kaydedin.
isaacg

@ isaacg LOperatörün otomatik olarak int üzerinde bir seri oluşturduğunu bilmiyordum , her gün göründüğü bir shcool günü: o) Teşekkürler!
Sok

8

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

Yüzenleri döndürür. Kullanılacak bir işleve atayın.

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

Her şeyi tek bir üçlü operatör sırasına sokarak ve 0-360 normale kadar normalleşmeyi bekleyerek 30 bayt kurtardı.

Edc65, Vasu Adari ve ETH sunumları sayesinde daha fazla bayt tasarrufu sağlıyor.

JSFiddle testleri ile. Firefox'ta deneyin.

İşlev bildirimini kaldırmak h=yasal değilse, 2 bayt ekleyin.


'Var' ve bazı baytları kaldırabilirsiniz.
Vasu Adari

ES6Fiddle bazı nedenlerden dolayı var bildirgesine ihtiyaç duyuyor ve ES6'yı firefox'ta deneyene kadar gerekli olmadığını fark etmemiştim
DankMemes 26.05.2005

1
Kıvrımlı parantezleri parantezlerle, noktalı virgülleri virgüllerle değiştirerek ve kaldırarak 6 bayt tasarruf edebilirsiniz return. Fonksiyon bildiriminin ( h=) kaldırılmasının da yasal olduğuna inanıyorum , toplamı 100'e
düşürüyoruz.

Bu saplantılı olabilir (o zaman yine, tüm iyi golfçüler değil mi?;)), Ancak %6)*60diğer taraftaki parantezden ve eşinden kurtularak iki bayttan tasarruf edebilirsiniz . Ayrıca, ekleme işleminde kaba kuvvet kullanmak (sonunda 6 eklemek yerine), geçerli kurulumunuzda bir bayttan tasarruf sağlar. (((x==r?(g-b)/m:x==g?2+(b-r)/m:4+(r-g)/m)+6)%6)*60olur (x==r?6+(g-b)/m:x==g?8+(b-r)/m:10+(r-g)/m)%6*60.
ETHproductions 2

1
Sıralama için +1, çok zeki, Bu 90 (veya 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 bayt

Düzenleme: pawel.boczarski sayesinde 10 bayt kaydedildi

Yaklaşık bir çözüm ...

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

Test sürüşü

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

Orijinal (kesin) çözümüm ...

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

Açıklaması:

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

Bu işlev giriş olarak R, G, B değerlerini içeren bir vektör alır cve girişi artan düzende sıralar

  • b sıralanmış değerleri içerir [z, y, x]
  • i b'deki her değerle ilişkilendirilmiş RGB düzlemini içerir

Vektör h, değerlerle doldurulur

  • 60*[6, 2, 4]= [360, 120, 240](ancak 3 bayt daha kısa)
  • en düşük değer Mavi ( i(1) == 3) değilse, bu durumda ilk renk tonu sıfır olur
  • sonra sırayla (i)yeniden düzenlemek hiçin kullanın[h(Z), h(Y), h(X)]

Oradan formülün sadece düz bir çevirisi. Burada deneyebilirsiniz .


İpucu: daha fazla bayt sıkmak için adsız işlev gösterimi kullanın: anahtar @(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)sözcükle tanımdan on bayt daha kısadır function.
pawel.boczarski 28:15

@ pawel.boczarski Tamamen işlev başlığını tamamen kaldırabilir miyim diye merak ediyordum, ama bunun yasal olup olmadığını bilmiyorum. Ama bahşiş için teşekkürler! : D
kabı

@ pawel.boczarski Buna dönüp baktığımda, onu r=çağırmak için hala adsız bir işleve ihtiyacım var, değil mi?
kabı

Anonim işlevlerin kaydedildiği birçok çözüm vardır. Ayrıca, bunun gibi tanımlanmış işlevi çağırabilirsiniz: (@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360))([127 247 103])veya ansanonim işlev tanımlandıktan hemen sonra değişkeni kullanabileceğinizi iddia edebilir , böylece işlev tanımının tamamlanması için atama gerekli değildir. Tek bir zorlamada ( codegolf.stackexchange.com/questions/54945 ) mevcut bir Matlab kütüphane işlevinin tam çözümü olarak tanıtıldı .
pawel.boczarski 28:15

@ pawel.boczarski Vay, bu ... sadece ... kötülük: DI, Luis'in dahil olacağını bilmeliydi. Özgün koda döneceğim ansve örnekte kullanacağım . Tekrar teşekkürler!
kabı

5

Pyth, 55

@ Sok'un cevabının benimkiyi attığını biliyorum, ancak yayınlanmasından hemen sonra benimkiyi bitirdiğimden, hala göndereceğimi düşündüm. Bu Pyth'i ilk kez kullanıyordu, bu yüzden bazı açık hatalar yaptığımdan eminim.

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

Giriş olması bekleniyor r, g, b. Burada deneyebilirsiniz .


İçin çalışmıyor 255,165,245.
jimmy23013

5

PowerShell, 232 226 222 161 Bayt

Önceki sürümler için revizyon geçmişine bakın

$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 evlat, bakalım bu işte yürüyebilir miyim. Beri bıraktığım \ngibi sayıldığından ;netlik için çizgiyi kırar.

İlk satır girişi üç olarak alır $argsve depolar $r, $g, $b. Gerçekten sadece $bdaha sonra kullanacağız , ancak üç çalışana da ihtiyacımız var |sort. Bu $z, $y, $xgirdi argümanlarının en küçüğünden en büyüğüne yapar .

Sonraki iki satır kurulum $cve $duygun rakamları ayarlamak için birden fazla dizin içine-bir-dizi mesajlar kullanarak. Eğer içinde dışarıdan çalışmak $xolduğunu -equal için $g(yani yeşil büyük oldu), biz set $c=1... Başka, eğer $xolduğunu -not equal için $b(yani mavi büyük değildi) $cya edilir 0ya 3mavi ikinci büyük olsaydı bağlı ... başka $c=2,. Benzer mantık kümeleri $d.

Daha sonra çıktısını aşağıdakilerle hesaplıyor ve yazdırıyoruz, bu sadece bir miktar golf mücadelesinin algoritmasıdır.

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

1
PowerShell'i tanımıyorum, bu yüzden hatalıysam beni düzeltin ... $zHesaplama yaparken kullanmazsınız $cya $dda çıktı hesaplamasında sadece bir kez kullanırsınız, bu yüzden $ztamamen kurtulup değiştirebilir $a[0]misiniz?
Sok

4

Ruby, 117 96 94 bayt

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}
  • ()R, g, b değişkenlerini kaldırarak ve kullanarak 21 bayt kaydedildi .
  • Negatif değeri dönüştürmek için 6 modülünü almak ve 2 bayt kazandıran derecelere dönüştürmek için 60 ile çarpmak.

Örnekler:

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 bayt

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

Örnek: a([255,165,245],Hue).çıktılarHue = 306.666666666666 .

Bu, aşağıdaki formülü kullanır:

  • Max = max(R,G,B), Min = min(R,G,B).
  • Eğer Max = R, U = 0. Else if Max = G, U = 2. Else U = 4.
  • Eğer Max = R, I = Gve J = B. Başka ise Max = G, I = Bve J = R. Else I = Rve J = G.
  • Z = U + (I - J)/(Max - Min)
  • Hueya Zda Z + 360eğer Z < 0.

Yuvarlama isteğe bağlıdır.
jimmy23013

@ jimmy23013 Güncelleme, teşekkürler.
15’te

3

Perl 5, 138 132 119 bayt

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

Uyarılar:

Kuşkusuz Perl, tüm Pyth'oresque golf oynamalarıyla bu mücadeleyi kazanamaz. Ancak bunun sadece 1 hesaplama adımıyla yapılıp yapılmadığını merak ettim. Güzelce çalışan modül sayesinde. :)

Ölçek:

$ 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

en fazla traş yerine orta değere göre bazı bayt tıraş. (==
vers

1

C ++ 276 bayt

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

Bir ipucu: Hkod- golf'da bağımsız bir fonksiyon, tam bir programla eşdeğer, meşru bir cevap olduğu gibi, meta-tartışmasında: meta.codegolf.stackexchange.com/questions/2419/… . Bu, cevabınızı daha rekabetçi hale getirecektir (davanızda 100 bayt tasarruf edin). Testin basitleştirilmesi için hala programın "tam" versiyonunu çözüm altında bırakmanız önerilir.
pawel.boczarski 28:15

İkinci test durumu yerine 127 247 103geçersiz değer verir . -120110
pawel.boczarski 28:15

1

R, 125 bayt

Beaker'in Octave çözümüne çok benzer. Kayan nokta çıkışı.

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

Örnekler:

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

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

Bir değer listesini kabul eder. Bunun daha da bozulabileceğinden emin değilim. İşte asılsız:

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

Alternatif yöntem

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

Örnek metodu kullanarak.

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>

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.