Оттенок цвета


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.
Доктор

Ответы:


6

Pyth, 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 байта.
Сок

Вы можете фактор 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 Исправлено, спасибо за дополнительный контрольный пример
Sok

1
Пара гольфов: m*120d-> *L120, сохранить eeJв Kстроке, чтобы сохранить еще один байт.
Исаак

@isaacg Я не знал, что Lоператор автоматически генерирует диапазон для int, каждый день - школьный, кажется: o) Спасибо!
Сок

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 Wow, это ... просто ... зло: я должен был знать, что Луис будет вовлечен. Я вернусь к исходному коду и буду использовать его ansв примере. Еще раз спасибо!
мензурка

5

Pyth, 55

Я знаю, что ответ @ Sok превосходит мой, но так как я закончил свой, сразу после того, как он / она опубликовал сообщение, я подумал, что все равно оставлю сообщение. Это был мой первый раз, когда я использовал 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с помощью нескольких вызовов index-in-a-array для установки чисел соответствующим образом. Работать извне, если $xэто -eqнеобходимо$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]?
Сок

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-Пролог, 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 . Else 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'oreque. Но я задавался вопросом, возможно ли это сделать только с одним шагом вычисления. Благодаря модулю, который хорошо сработал. :)

Тест:

$ 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функцию в ответе одну, так как в code-golf автономная функция - это правильный ответ, эквивалентный полной программе, см. Мета-обсуждение: 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

Python, 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.