Відтінок кольору


23

Вам даються значення RGB кольору. Ваше завдання просте: обчислити відтінок, у найпростішому визначенні.

Скажіть, що канали з найвищим, середнім і найнижчим значенням - це X, Y, Z (які є червоними, зеленими або синіми), а їх значення - x, y, z. Відтінок цього кольору дорівнює (h (X) -h (Y)) * (1 + (xy) / (xz)) / 2 + h (Y), де:

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

Вхід складається з 3 цілих чисел від 0 до 255, які не всі рівні, у будь-якому послідовному порядку. Вихід може бути поплавками або цілими числами, округленими вгору або вниз, що не повинно бути послідовним. Якщо ціла частина виводу дорівнює 0 або 360, ви можете надрукувати будь-яке з них.

Ви не можете викликати вбудовані для перетворення кольорового простору, включаючи неявні перетворення, наприклад, під час маніпулювання зображенням.

Це код-гольф. Найкоротший код виграє.

Приклади

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)

Редагувати

Ви не повинні дотримуватися точної формули, а лише дати той же результат, що і вищевказана формула. Я хотів би також побачити кілька відповідей, що стосуються самої формули.


Чи слід спочатку перетворити з sRGB в лінійну шкалу? Я думаю, що ми повинні, але, здається, нікого поки що не було.
Джон Дворак

@JanDvorak Завдання - обчислити відтінок, у найпростішому визначенні . У цьому випадку "найпростіший" означає, що ви повинні припустити, що введення вже в правильній шкалі, і використовувати точну формулу, подану у запитанні, або що-небудь, що дає такий же результат.
jimmy23013

Але ... 24 bpp зазвичай означає sRGB. Якщо ні, то в специфікації формату (ви) слід вказати інше.
Джон Дворак

@JanDvorak Ви повинні використовувати це визначення для RGB та відтінку.
jimmy23013

9
Слід сказати: huehuehue.
TheDoctor

Відповіді:


6

Піт, 27 байт

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

Демонстрація. Тестовий джгут.

Фомула, взята з Вікіпедії .

По суті, такі дії:

  1. .<QJxQKeSQ: Поверніть найбільше значення на передню частину списку.
  2. -Ft: Візьміть різницю двох інших значень.
  3. -KhSQ: Відняти мінімальне значення від максимального значення.
  4. c: Розділіть 2 на 3.
  5. + ... yJ Додайте двічі індекс максимального значення у списку (0 якщо R, 2 якщо G, 4, якщо B).
  6. % ... 6: Мод 6, щоб виправити проблеми з мінусами.
  7. *60: Помножте на 60, щоб перетворити на градуси та друкувати.

9

C #, 188 210 206 197 191 байт

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 байт та SLuck49 за економію 15!


Оскільки ви використовуєте лише zодин раз у обчисленні виводу, і не використовуєте його в попередніх обчисленнях, ви усуваєте змінну і змінюєте вихід return(int)((c-d)*(1+(x-y)/(double)(x-a[0]))/2+d);, економлячи 4 байти.
Sok

Ви можете фактор 120 з ряду cі dзавдань і в поверненні , як це , 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)/(double)(x-a[0]))/2+d*120);щоб зберегти 4 байта.
SLuck49

Також вам справді потрібен акторський склад double? Якщо це зробити, ви можете використовувати це замість цього, (x-a[0])*1Dщоб зберегти ще 5 байт.
SLuck49

@ SLuck49 Дякую! Так, мені справді потрібен акторський склад, він дає неточні результати інакше, але це *1Dмноження - приємна хитрість!
ProgramFOX

Також (щойно помітив) ви можете відмовитися від використання всіх разом, повністю отримавши кваліфікацію System.Arrayще 6 байт.
SLuck49

8

Pyth, 41 55 53 51 байт

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

Введення очікується у формі r,g,b. Ось пояснення:

                                                        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)

Збережено 4 байти, завдяки @Jakube та @isaacg


@ Jimmy23013 Fixed, спасибі за додатковий тест випадку
Sok

1
Кілька гольфів: m*120d-> *L120, збережіть eeJв Kрядку, щоб зберегти ще один байт.
isaacg

@isaacg Я не знав, що Lоператор генерував діапазон на int автоматично, кожен день - shcool день, здається: o) Дякую!
Sok

8

Javascript (ES6), 145 115 108 100 97 90 байт

Повертається плаває. Призначте функцію для використання.

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

Збережено 30 байт, об'єднавши все в одну потрійну послідовність операторів і дочекавшись кінця, щоб нормалізуватися до 0-360.

Завдяки edc65, Vasu Adari та ETHproductions зберегли ще більше байтів.

JSFiddle з тестами. Спробуйте в Firefox.

Якщо видалення декларації функції h=не є законним, додайте 2 байти.


Ви можете видалити 'var' та деякі байти.
Васу Адарі

ES6Fiddle чомусь потребує декларації var, і я не усвідомлював, що це не потрібно, поки я не спробував ES6 в firefox
DankMemes

1
Ви можете зберегти 6 байт, замінивши фігурні дужки на круглі дужки, крапку з комою з комою та видаливши return. Я вважаю, що видалення декларації функції ( h=) також є законним, а загальна сума знижується до 100.
ETHproductions,

Це може бути нав’язливим (тоді, знову ж, чи не всі хороші гравці в гольф?)), Але ви могли б зберегти ще два байти, позбувшись дужок у %6)*60та його партнера з іншого боку. Також використання грубої сили для додавання (замість того, щоб додати 6 в кінці) фактично збереже один байт над вашою поточною установкою. (((x==r?(g-b)/m:x==g?2+(b-r)/m:4+(r-g)/m)+6)%6)*60став би (x==r?6+(g-b)/m:x==g?8+(b-r)/m:10+(r-g)/m)%6*60.
ETHproductions

1
+1 для сорту, дуже розумний, Це 90 (або 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

Октава, 65 60 50 байт

Редагувати: Збережено 10 байт завдяки pawel.boczarski

Наближене рішення ...

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

Тестовий запуск

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

Октава, 107 байт

Моє оригінальне (точно-іш) рішення ...

Код:

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

Пояснили:

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

Ця функція приймає вектор, що містить значення R, G, B як вхід, cі сортує вхід у порядку зростання

  • b містить відсортовані значення [z, y, x]
  • i містить площину RGB, пов'язану з кожним значенням в b

Вектор hзаповнений значеннями

  • 60*[6, 2, 4]= [360, 120, 240](але на 3 байти коротше)
  • за винятком випадків, коли найменше значення є синім ( i(1) == 3), у цьому випадку перше значення відтінку стає нульовим
  • потім використовуйте (i)для перестановки hв [h(Z), h(Y), h(X)]порядку

Звідси це просто пряма транскрипція формули. Ви можете спробувати тут .


Підказка: використовуйте позначення анонімної функції, щоб видавити більше байтів: @(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)на десять байтів коротше, ніж визначення з functionключовим словом.
pawel.boczarski

@ pawel.boczarski Мені було цікаво, чи можу я взагалі покінчити із заголовком функції, але не знаю, чи це законно. Але дякую за пораду! : D
стаканчик

@ pawel.boczarski Озираючись на це, мені все одно потрібна r=функція перед анонімною функцією, щоб викликати її, правда?
стаканчик

Є багато рішень, де розміщуються анонімні функції. Більше того, ви можете назвати так визначену функцію навіть так: (@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360))([127 247 103])або стверджувати, що ви можете використовувати ansзмінну відразу після того, як анонімна функція була визначена, так що призначення не є необхідним для повного визначення функції. В одному виклику ( codegolf.stackexchange.com/questions/54945 ) ручка існуючої функції бібліотеки Matlab була розміщена як повне рішення.
pawel.boczarski

@ pawel.boczarski Ого, це ... просто ... зло: DI повинен був знати, що Луїс буде причетний. Я повернусь до початкового коду та використаю ansу зразку. Знову дякую!
стаканчик

5

Піта, 55

Я знаю, що відповідь @ Сока б'є мою, але оскільки я закінчив шахту відразу після того, як він / вона опублікував, я подумав, що все-таки допишу. Це вперше я використовував Pyth, тому я впевнений, що я допустив явні помилки.

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

Вхід, як очікується, буде r, g, b. Ви можете спробувати тут .


Не працює для 255,165,245.
jimmy23013

5

PowerShell, 232 226 222 161 байт

Перегляньте історію версій попередніх версій

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

О, хлопче, подивимось, чи зможу я пройти через це. Оскільки \nрахує те саме, що ;я залишив, рядок переривається для ясності.

Перший рядок приймає дані як три $argsі зберігає їх $r, $g, $b. Ми насправді будемо використовувати лише $bпізніше, але нам потрібні всі три, щоб |sortробота працювала належним чином. Це робить$z, $y, $x найменший за величиною вхідних аргументів.

Налаштування наступних двох рядків $cта $dвикористання декількох дзвінків індексу в масив для встановлення чисел відповідно. Робота з зовнішньої сторони в, якщо $xце -eqUAL до $g(тобто, зелений був найбільшим), ми встановлюємо $c=1... ще, якщо $xє -nВЗ eякост до $b(тобто, синій не найбільший) $cабо 0або в 3залежності , якщо синій був другим по величині ... ще, $c=2. Подібні логічні набори $d.

Тоді ми обчислюємо та друкуємо вихід із наступним, що є лише алгоритмом, який випробовували.

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

1
Я не знаю PowerShell, тому виправте мене, якщо я помиляюся ... Ви не використовуєте $zпід час обчислення $cабо $d, і ви використовуєте його лише один раз у підрахунку виводу, щоб ви могли $zповністю позбутися і замінити його $a[0]?
Sok

4

Рубі, 117 96 94 байт

Код:

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 байт, видаливши () та використання змінних r, g, b.
  • Беручи модуль 6 для перетворення негативного значення та множення його на 60 для перетворення на градуси, які зберегли 2 байти.

Приклади:

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 байти

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

Приклад: a([255,165,245],Hue).виходиHue = 306.666666666666 .

Для цього використовується наступна формула:

  • Max = max(R,G,B), Min = min(R,G,B).
  • Якщо Max = R, U = 0. Інакше , якщо Max = G, U = 2. Інше U = 4.
  • Якщо Max = R, I = Gі J = B. Інакше , якщо Max = G, I = Bі J = R. Інше I = Rі J = G.
  • Z = U + (I - J)/(Max - Min)
  • Hueє Zабо Z + 360якщо Z < 0.

Округлення необов’язкове.
jimmy23013

@ jimmy23013 Оновлено, дякую.
Фаталізувати

3

Perl 5, 138 132 119 байт

Код:

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

Зауваження:

Безумовно, Perl не зможе перемогти такий виклик зі всіма гольфами в Pyth'oresque. Але мені цікаво, чи можна це зробити лише за 1 крок розрахунку. Завдяки модулю, який добре вийшов. :)

Тест:

$ 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

1

C ++ 276 байт

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

Підказка: ви можете залишити Hфункцію самостійно у відповіді, так як у коді-гольф автономна функція - це законна відповідь, рівнозначна повній програмі, дивіться мета дискусії: meta.codegolf.stackexchange.com/questions/2419/… . Це зробить вашу відповідь більш конкурентоспроможною (збережіть у вашому випадку 100 байт). Вам все ж рекомендується залишити "повну" версію програми під рішенням для спрощення тестування.
pawel.boczarski

Другий тестовий випадок 127 247 103дає недійсне значення -120замість 110.
pawel.boczarski

1

R, 125 байт

Дуже схожий на розчин склянки Octave. Вихід з плаваючою комою.

Код:

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

Приклади:

> 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

Пітон, 154 байти

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

Приймає список значень. Не впевнений, чи можна це далі розбити. Ось це невольф:

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

Альтернативний метод.

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

Використовуючи прикладний метод.

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>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.