Konverter Warna RGB ke Xterm

13

Terminal 256-warna yang kompatibel dengan Xterm menambahkan 240 warna di atas 16 warna sistem yang biasa. Warna 16-231 menggunakan 6 level (0, 95, 135, 175, 215, 255) merah, hijau, dan biru, dipesan secara leksikografis. Warna 232-255 hanya 24 tingkat abu-abu (8 ... 238 kali 10 detik). Untuk mendapatkan ide yang lebih baik tentang apa yang saya bicarakan, lihat tabel ini .

Tantangan

Tujuan Anda adalah membuat program atau fungsi yang mengambil, sebagai input, nilai rgb, dan menampilkan angka yang sesuai dengan warna Xterm terdekat dengan nilai rgb itu. Karena 16 warna sistem (warna 0-15) sering kali dapat disesuaikan, Anda akan mengecualikannya dari konversi ini.

Untuk lebih menentukan apa warna "terdekat", gunakan jarak Manhattan di sepanjang komponen merah, hijau, dan biru. Misalnya, rgb(10, 180, 90)berjarak 20 unit dari rgb(0, 175, 95)(warna 35) karena abs(10 - 0) + abs(180 - 175) + abs(90 - 95) == 20. Jika warna input sama antara dua atau lebih warna Xterm, output warna Xterm dengan indeks tertinggi.

Contohnya

 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

Aturan

  • Celah standar dilarang
  • Program atau fungsi Anda diizinkan untuk mengambil nilai rgb dalam format apa pun yang wajar, termasuk:
    • Pisahkan argumen untuk merah, hijau, dan biru
    • Daftar, tuple, kamus, atau yang serupa
    • String atau stdin yang dipisahkan oleh pembatas
    • Warna hex (misalnya #ff8000)
  • Anda dapat mengasumsikan bahwa semua nilai r, g, dan b, akan berupa bilangan bulat antara 0 dan 255.
  • Karena 16 warna sistem harus dikeluarkan dari pemetaan, semua output harus dalam kisaran 16 ... 255.

Ini , jadi kode terpendek menang.

Beefster
sumber

Jawaban:

4

Haskell , 132 byte

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

Cobalah online!

Mengambil input sebagai daftar bilangan bulat [red, green, blue] .

Implementasi yang cukup mudah. Pertama-tama saya membuat daftar warna Xterm yang kami gunakan dengan dua pemahaman daftar yang disatukan. Yang pertama menangani warna 16-231 dengan iterasi tiga vyang berisi nilai-nilai warna yang digunakan. Yang kedua hanya mengulangi nilai abu-abu dan menempatkannya di ketiga slot. Lalu saya indeks dengan zip (mulai dari 16) dan membuat pasangan dengan jarak manhattan (dinegasikan) dan indeks itu dan mengambil maksimum. Saya menggunakan maksimum karena kami mengikat indeks terbesar dan cara ini menghemat satu tambahan -.

pengguna1472751
sumber
3

Ruby , 280 180 166 164 155 byte

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

Cobalah online!

Sebuah lambda mengambil warna input sebagai array bilangan bulat.

Saya memiliki lebih banyak kesulitan menghasilkan warna Xterm daripada yang saya harapkan! Saya siap dikalahkan secara memalukan di area itu. Saya menggunakan konversi basis sebagai jenis kompresi, tetapi satu-satunya cara saya tahu untuk melakukannya di Ruby adalah melaluiInteger#to_s yang sedikit canggung.

-100 byte: Baca masalah lebih hati-hati, dan abaikan 16 warna sistem ^ _ ^;

-14 byte: Gunakan konversi basis tangan alih-alih .to_s(6)

-2 byte: Lewati tanda kurung siku saat mendeklarasikan array

-9 byte: Buat daftar warna Xterm hanya dengan satu map; ini juga menyimpan tanda plus dan sepasang parens.

->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
}
benj2240
sumber
1
BTW, Anda tidak perlu memetakan ke 16 warna sistem. Mungkin saya harus menjelaskannya dalam deskripsi.
Beefster
Ooh, itu akan sedikit membantu saya! Saya benar-benar merindukan hal itu dalam kata-kata asli.
benj2240
1

Kotlin , 299 290 267 265 byte

(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

Yg diperindahkan

(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

Uji

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

TIO

TryItOnline

jrtapsell
sumber
1

Batch, 266 byte

@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
Neil
sumber
1

Stax , 41 byte

¬ÿ▒ú╘Σt∙Æ9φ☻ùí&BQq═IÜH∩Å╧♥f⌠óH]╨⌡≤@■Q‼Hr¼

Jalankan dan debug online!

Versi ASCII 50 byte:

"4GOW_g"{52-5*m3|^24{A*vv]3*m+{;\{E:-m|+mc|m|IH16+
Weijun Zhou
sumber
1

C (gcc), 202 192 157 150 (141 disadap) 138 134 byte

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

Terima kasih @ceilingcat

Cobalah online!

PrincePolka
sumber
1
Masalahnya tidak ditentukan oleh tes (yang jelas diberi label sebagai contoh), jadi silakan dapatkan tes baru yang ditambahkan.
Ton Hospel
1
@TonHospel Saya memperbaiki bug sekarang dan mengurangi -3 byte, tapi terima kasih atas jawabannya
PrincePolka