Xterm 색상 변환기에 RGB


13

256 색 Xterm 호환 터미널은 일반적인 16 가지 시스템 색 위에 240 색을 추가합니다. 색상 16-231은 6 단계 (0, 95, 135, 175, 215, 255)의 빨강, 녹색 및 파랑을 사전 식 순서로 사용합니다. 색상 232-255는 단순히 24 단계 회색 (8 ... 238 x 10 초)입니다. 내가 말하는 것에 대한 더 나은 아이디어를 얻으려면 이 표를 참조하십시오 .

도전

목표는 입력 값으로 rgb 값을 가져와 해당 rgb 값에 가장 가까운 Xterm 색상에 해당하는 숫자를 출력하는 프로그램 또는 함수를 만드는 것입니다. 16 개의 시스템 색상 (0-15 색상)은 종종 사용자 정의 할 수 있으므로이 변환에서 제외됩니다.

"가장 가까운"색상을 더 잘 정의하려면 빨강, 녹색 및 파랑 구성 요소를 따라 맨해튼 거리 를 사용하십시오 . 예를 들어, (컬러 35) rgb(10, 180, 90)에서 20 단위 떨어져 rgb(0, 175, 95)있기 때문 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

하스켈 , 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색상은 해당 색상이 사용하는 값을 포함합니다. 두 번째는 회색 값을 반복하여 세 개의 슬롯에 모두 넣습니다. 그런 다음 우편 번호 (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 색상을 생성하는 데 예상보다 많은 문제가있었습니다! 나는 그 지역에서 당당 하게 겸손하게 준비 될 준비가되어 있습니다 . 나는 기본 변환을 일종의 압축으로 사용 했지만 루비에서 그렇게하는 유일한 방법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
BTW, 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")
    }
}

TIO

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), 202192157150 (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
문제는 테스트에 의해 정의 된 것이 아니며 (예로 명확하게 표시되어 있음) 대신 새 테스트를 추가하십시오.
Ton Hospel

1
@TonHospel 나는 지금 버그를 수정하고 -3 바이트를 삭감했지만 답변 주셔서 감사합니다
PrincePolka
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.