Chuyển đổi màu từ RGB sang Xterm


13

Thiết bị đầu cuối tương thích Xterm 256 màu thêm 240 màu trên 16 màu hệ thống thông thường. Màu sắc 16-231 sử dụng 6 cấp độ (0, 95, 135, 175, 215, 255) màu đỏ, xanh lá cây và xanh dương, được sắp xếp theo thứ tự từ vựng. Màu sắc 232-255 chỉ đơn giản là 24 cấp độ màu xám (8 ... 238 x 10 giây). Để hiểu rõ hơn về những gì tôi đang nói, hãy xem bảng này .

Các thách thức

Mục tiêu của bạn là tạo ra một chương trình hoặc chức năng, làm đầu vào, giá trị rgb và xuất số tương ứng với màu Xterm gần nhất với giá trị rgb đó. Vì 16 màu hệ thống (màu 0-15) thường có thể tùy chỉnh, bạn sẽ loại trừ chúng khỏi chuyển đổi này.

Để xác định rõ hơn màu "gần nhất" là gì, hãy sử dụng khoảng cách Manhattan dọc theo các thành phần màu đỏ, xanh lá cây và xanh dương. Ví dụ, cách rgb(10, 180, 90)20 đơn vị rgb(0, 175, 95)(màu 35) bởi vì abs(10 - 0) + abs(180 - 175) + abs(90 - 95) == 20. Nếu màu đầu vào bằng nhau giữa hai hoặc nhiều màu Xterm, hãy xuất màu Xterm với chỉ số cao nhất.

Ví dụ

 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

Quy tắc

  • Sơ hở tiêu chuẩn bị cấm
  • Chương trình hoặc chức năng của bạn được phép lấy các giá trị rgb ở bất kỳ định dạng hợp lý nào, bao gồm:
    • Các đối số riêng biệt cho màu đỏ, xanh lá cây và xanh dương
    • Một danh sách, tuple, từ điển hoặc tương tự
    • Chuỗi phân tách hoặc stdin phân tách
    • Màu lục (ví dụ #ff8000)
  • Bạn có thể giả sử rằng tất cả các giá trị r, g và b, sẽ là các số nguyên trong khoảng từ 0 đến 255.
  • Vì 16 màu hệ thống sẽ bị loại trừ khỏi ánh xạ, tất cả các kết quả đầu ra phải nằm trong phạm vi 16 ... 255.

Đây là , vì vậy mã ngắn nhất sẽ thắng.

Câu trả lời:


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

Hãy thử trực tuyến!

Lấy đầu vào dưới dạng danh sách các số nguyên [red, green, blue] .

Thực hiện khá đơn giản. Đầu tiên tôi xây dựng một danh sách các màu Xterm mà chúng ta đang sử dụng với hai cách hiểu danh sách được nối với nhau. Cái đầu tiên xử lý các màu 16-231 bằng cách lặp ba lần trong vđó chứa các giá trị mà các màu đó sử dụng. Cái thứ hai chỉ lặp lại các giá trị màu xám và đặt chúng vào cả ba vị trí. Sau đó, tôi lập chỉ mục cho nó bằng zip (bắt đầu từ 16) và tạo một cặp với khoảng cách manhattan (phủ định) và chỉ số đó và lấy tối đa. Tôi đã sử dụng tối đa vì chúng tôi đang phá vỡ chỉ số lớn nhất và cách này giúp tôi tiết kiệm thêm một lần -.


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}

Hãy thử trực tuyến!

Một lambda lấy màu đầu vào là một mảng các số nguyên.

Tôi gặp nhiều khó khăn hơn khi tạo màu Xterm hơn tôi mong đợi! Tôi đang chuẩn bị để được outgolfed xấu hổ một cách khiêm tốn trong khu vực đó. Tôi đã sử dụng chuyển đổi cơ sở như một loại nén, nhưng cách duy nhất tôi biết để làm như vậy trong Ruby là thông quaInteger#to_s một chút khó xử.

-100 byte: Đọc kỹ vấn đề hơn và bỏ qua 16 màu hệ thống ^ _ ^;

-14 byte: Sử dụng chuyển đổi cơ sở tay thay vì .to_s(6)

-2 byte: Bỏ qua dấu ngoặc vuông khi khai báo mảng

-9 byte: Tạo danh sách các màu Xterm chỉ với một map; điều này cũng lưu một dấu cộng và một cặp 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
}

1
BTW, Bạn không cần ánh xạ tới 16 màu hệ thống. Có lẽ tôi nên làm cho điều đó rõ ràng hơn trong mô tả.
Beefster

Ồ, điều đó sẽ giúp tôi khá nhiều! Tôi chắc chắn đã bỏ lỡ điều đó trong từ ngữ câu hỏi ban đầu.
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

Làm đẹp

(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

Kiểm tra

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

Dùng thử


1

Hàng loạt, 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


1

C (gcc), 202 192 157 150 (141 lỗi) 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;}

Cảm ơn @ceilingcat

Hãy thử trực tuyến!


1
Vấn đề không được xác định bởi các bài kiểm tra (được dán nhãn rõ ràng làm ví dụ), vì vậy vui lòng nhận thêm một bài kiểm tra mới.
TonMedel

1
@TonHeach Tôi đã sửa lỗi bây giờ và cắt giảm -3 byte, nhưng cảm ơn vì câu trả lời
PrincePolka
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.