RGB в Xterm конвертер кольорів


13

256-кольорові термінали, сумісні з Xterm, додають 240 кольорів поверх звичних 16 системних кольорів. Кольори 16-231 використовують 6 рівнів (0, 95, 135, 175, 215, 255) червоного, зеленого та синього кольорів, упорядкованих лексикографічно. Кольори 232-255 - це просто 24 рівня сірого (8 ... 238 на 10с). Щоб краще зрозуміти, про що я говорю, дивіться цю таблицю .

Змагання

Ваша мета - створити програму або функцію, яка приймає в якості значень rgb значення та виводить число, що відповідає найближчому кольору Xterm до цього значення rgb. Оскільки 16 системних кольорів (кольори 0-15) часто настроюються, ви виключаєте їх із цього перетворення.

Щоб краще визначити, який "найближчий" колір, використовуйте відстань на Манхеттені уздовж червоного, зеленого та синього компонентів. Наприклад, на rgb(10, 180, 90)відстані 20 одиниць від rgb(0, 175, 95)(колір 35), оскільки abs(10 - 0) + abs(180 - 175) + abs(90 - 95) == 20. Якщо колір введення однаковий між двома або більше кольорами Xterm, виведіть колір Xterm з найвищим показником.

Приклади

 R   G   B     Xterm
  0   0   0 ==> 16
 95 135   0 ==> 64
255 255 255 ==> 231
238 238 238 ==> 255

 90 133 140 ==> 66
218 215 216 ==> 188
175 177 178 ==> 249

175   0 155 ==> 127
 75  75  75 ==> 239
 23  23  23 ==> 234
115 155 235 ==> 111

Правила

  • Стандартні лазівки заборонені
  • Вашій програмі або функції дозволено приймати значення rgb у будь-якому розумному форматі, включаючи:
    • Окремі аргументи для червоного, зеленого та синього кольорів
    • Список, кортеж, словник тощо
    • Рядок або stdin, розділений роздільником
    • Шестигранні кольори (наприклад #ff8000)
  • Можна припустити, що всі значення r, g і b будуть цілими числами від 0 до 255.
  • Оскільки 16 системних кольорів повинні бути виключені з відображення, всі виходи повинні бути в діапазоні 16 ... 255.

Це , тому найкоротший код виграє.

Відповіді:


4

Haskell , 132 байти

v=0:[95,135..255]
f c=snd$maximum[(-sum(abs<$>zipWith(-)c x),i)|(i,x)<-zip[16..]$[[r,g,b]|r<-v,g<-v,b<-v]++[[g,g,g]|g<-[8,18..238]]]

Спробуйте в Інтернеті!

Вводиться як список цілих чисел [red, green, blue].

Досить просто реалізація. Спочатку я будую список кольорів Xterm, який ми використовуємо з двома списками, об'єднаними разом. Перший з яких обробляє кольори 16-231 шляхом потрійної ітерації, над vякою містяться значення, які використовують ці кольори. Другий просто перебирає сірі значення та розміщує їх у всіх трьох слотах. Потім я його індексую за допомогою zip (починаючи з 16) і складаю пару з відстані на Манхеттені (заперечується) і цим індексом і беру максимум. Я використав максимум, тому що ми перериваємо найбільший індекс, і це заощаджує мені одну додаткову -.


3

Рубі , 280 180 166 164 155 байт

->c{d=0,95,135,175,215,255
a=(0..239).map{|n|n<216?[d[n/36],d[(n%36)/6],d[n%6]]:[n*10-2152]*3}.map{|t|t.zip(c).map{|a,b|(a-b).abs}.sum}
a.rindex(a.min)+16}

Спробуйте в Інтернеті!

Лямбда, що приймає вхідний колір як масив цілих чисел.

У мене було більше проблем із створенням кольорів Xterm, ніж я очікував! Я готовий бути outgolfed приголомшливо скромно в цій області. Я використовував базове перетворення як вид стиснення, але єдиний спосіб, який я знаю, зробити це в Ruby, це черезInteger#to_s який трохи незручно.

-100 байт: уважніше прочитайте проблему та ігноруйте 16 системних кольорів ^ _ ^;

-14 байт: Використовуйте конверсію вручну замість .to_s(6)

-2 байти: пропустити квадратні дужки при оголошенні масиву

-9 байт: Створити список кольорів Xterm лише одним map; це також економить знак плюс і пару паронів.

->c{
  d=0,95,135,175,215,255                 # d is the set of possible RGB values
  a=(0..239).map{|n|                     # Create the array of Xterm triplets
    n<216 ? [d[n/36],d[(n%36)/6],d[n%6]] # Convert x from base 6 to base d, or
          : [n*10-2152]*3                #   create a uniform triplet
  }.map{|t|
    t.zip(c).map{|a,b|(a-b).abs}.sum     # Map from triplets to Manhattan distance
  }
  a.rindex(a.min) +                      # Find the last index of the lowest distance
  16                                     # Offset for the exluded system colors
}

1
До речі, вам не потрібно зіставляти 16 системних кольорів. Можливо, я повинен зробити це зрозумілішим в описі.
Beefster

Ой, це мені дуже допоможе! Я, безумовно, пропустив це в початковій редакції питання.
benj2240

1

Котлін , 299 290 267 265 байт

(16..255).associate{it to if(it<232)(it-16).let{i->listOf(0,95,135,175,215,255).let{l->listOf(l[i/36],l[(i/6)%6],l[i%6])}}else(8..238 step 10).toList()[it-232].let{listOf(it,it,it)}}.minBy{(k,v)->(it.zip(v).map{(a,b)->kotlin.math.abs(a-b)}.sum()*256)+(256-k)}!!.key

Прикрасили

(16..255).associate {
    it to if (it < 232) (it - 16).let { i ->
            listOf(0, 95, 135, 175, 215, 255).let { l ->
                listOf(
                        l[i / 36],
                        l[(i / 6) % 6],
                        l[i % 6])
            }
        } else (8..238 step 10).toList()[it - 232].let { listOf(it, it, it) }
}.minBy { (k, v) ->
    (it.zip(v).map { (a, b) -> kotlin.math.abs(a - b) }.sum() * 256) + (256 - k)
}!!.key

Тест

data class Test(val r: Int, val g: Int, val b: Int, val out: Int)

val test = listOf(
        Test(0, 0, 0, 16),
        Test(95, 135, 0, 64),
        Test(255, 255, 255, 231),
        Test(238, 238, 238, 255),

        Test(90, 133, 140, 66),
        Test(218, 215, 216, 188),
        Test(175, 177, 178, 249),

        Test(175, 0, 155, 127),
        Test(75, 75, 75, 239),
        Test(23, 23, 23, 234),
        Test(115, 155, 235, 111)
)
fun z(it:List<Int>): Int =
(16..255).associate{it to if(it<232)(it-16).let{i->listOf(0,95,135,175,215,255).let{l->listOf(l[i/36],l[(i/6)%6],l[i%6])}}else(8..238 step 10).toList()[it-232].let{listOf(it,it,it)}}.minBy{(k,v)->(it.zip(v).map{(a,b)->kotlin.math.abs(a-b)}.sum()*256)+(256-k)}!!.key

fun main(args: Array<String>) {
    for (i in test) {
        val r = z(listOf(i.r, i.g, i.b))
        println("$i ${i.out} ==> $r")
    }
}

ТІО

TryItOnline


1

Пакетна, 266 байт

@set/ax=15,m=999
@set s=for %%b in (0 95 135 175 215 255)do @
@%s:b=r%%s:b=g%%s%call:c %* %%r %%g %%b
@for /l %%g in (8,10,238)do @call:c %* %%g %%g %%g
@echo %n%
:c
@set/ax+=1,r=%4-%1,g=%5-%2,b=%6-%3
@set/ad=%r:-=%+%g:-=%+%b:-=%
@if %d% leq %m% set/an=x,m=d


1

C (gcc), 202 192 157 150 (141 помилка) 138 134 байти

l,m,t,i;a(c,x){x=abs(c-=i>215?i*10-2152:x*40+!!x*55);}f(r,g,b){for(i=l=240;i--;t=a(r,i/36)+a(g,i/6%6)+a(b,i%6),t<l?l=t,m=i:1);i=m+16;}

Дякую @ceilingcat

Спробуйте в Інтернеті!


1
Проблема не визначається тестами (які чітко позначені як приклади), тому, будь ласка, додайте новий тест замість цього.
Тон Євангелія

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