RGB到Xterm色彩转换器


13

256色Xterm兼容终端在通常的16种系统颜色之上增加了240种颜色。颜色16-231使用6级(0、95、135、175、215、255)红色,绿色和蓝色(按字典顺序排列)。颜色232-255仅是24级灰度(8 ... 238 x 10s)。要更好地了解我在说什么,请参阅此表

挑战

您的目标是制作一个程序或函数,将rgb值作为输入,并输出与该rgb值最接近的Xterm颜色对应的数字。由于通常可以自定义16种系统颜色(颜色0-15),因此您将无法将它们从此转换中排除。

为了更好地定义“最接近的”颜色是什么,请沿红色,绿色和蓝色分量使用曼哈顿距离。例如,rgb(10, 180, 90)距离rgb(0, 175, 95)(颜色35)20个单位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值,包括:
    • 红色,绿色和蓝色的单独参数
    • 列表,元组,字典或类似内容
    • 分隔符分隔的字符串或标准输入
    • 十六进制颜色(例如#ff8000
  • 您可以假设所有r,g和b值都是0到255之间的整数。
  • 由于将从映射中排除16种系统颜色,因此所有输出应在16 ... 255范围内。

这是,因此最短的代码获胜。

Answers:


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开始)对其进行索引,并与曼哈顿距离(取反)和该索引配对,并采用最大值。我使用了maximum,因为我们在最大的索引上决胜局,这样可以为我节省一个额外的空间-


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}

在线尝试!

以输入颜色为整数数组的lambda。

我在生成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 '18

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

蒂奥

在线试用


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'3

1
@TonHospel我现在修复了错误并缩减了-3个字节,但感谢您的回答
PrincePolka
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.