查找最接近的三位数十六进制颜色


23

在CSS中,颜色可以由“十六进制三元组”指定-一个三字节(六位数)的十六进制数字,其中每个字节代表颜色的红色,绿色或蓝色分量。例如,#FF0000完全为红色,等效于rgb(255, 0, 0)

颜色也可以由使用三个十六进制数字的速记符号表示。通过将每个数字重复,速记扩展为六位数字形式。例如,#ABC变为#AABBCC

由于十六进制速记中的位数较少,因此可以表示较少的颜色。

挑战

编写一个采用六位数十六进制颜色代码并输出最接近的三位数颜色代码的程序或函数。

这是一个例子:

  • 输入十六进制代码:#28a086
  • 红色成分
    • 0x28 = 40(十进制)
    • 0x22 = 34
    • 0x33 = 51
    • 0x22更近,因此缩短的颜色代码的第一位是2
  • 绿色成分
    • 0xa0 = 160
    • 0x99 = 153
    • 0xaa = 170
    • 0x99更近,所以第二个数字是9
  • 蓝色成分
    • 0x86 = 134
    • 0x77 = 119
    • 0x88 = 136
    • 0x88更近,所以第三位是8
  • 缩短的颜色代码为#298(扩展为#229988)

您的程序或函数必须接受以开头的六位十六进制颜色代码作为输入,#并输出以前面的三位数颜色代码作为输入#

例子

  • #FF0000→#F00
  • #00FF00→#0F0
  • #D913C4→#D1C
  • #C0DD39→#BD3
  • #28A086→#298
  • #C0CF6F→#BC7

计分

这是一个代码高尔夫挑战赛,因此以您所用语言提供的最短答案很成功!适用标准规则。


1
“将全色代码的每个组成部分与速记颜色代码的相应组成部分之间的差异加在一起”-这部分令人困惑。哪里都没有添加,对不对?
Grzegorz Oledzki

3
请注意,如果仅丢弃替代数字,则每种短颜色代表相等数量的全色,因此可以认为它比最近的颜色具有更好的表示效果。
尼尔

6
在“沙箱”中看到了此消息,但忘了提到我认为不需要#添加任何挑战。
毛茸茸的

2
我们可以小写输出吗?
Arnauld

2
0x22是34,而不是30
克鲁格

Answers:


4

JavaScript(ES6),55个字节

s=>s.replace(/\w./g,x=>(('0x'+x)/17+.5|0).toString(16))

在线尝试!


很好地使用toString!我没有意识到它可能需要一个基数参数。
wrymug

8

05AB1E,13 个字节

ćs2ôH8+17÷hJ«

在线尝试!

怎么样?

ćs2ôH8+17÷hJ« | string, S   e.g. stack: "#B23F08"
ć             | decapitate              "B23F08", "#"
 s            | swap                    "#", "B23F08"
  2           | two                     "#", "B23F08", 2
   ô          | chuncks                 "#", ["B2", "3F", "08"]
    H         | from hexadecimal        "#", [178, 63, 8]
     8        | eight                   "#", [178, 63, 8], 8
      +       | add                     "#", [186, 71, 16]
       17     | seventeen               "#", [186, 71, 16], 17
         ÷    | integer divide          "#", [10, 4, 0]
          h   | to hexadecimal          "#", ["A", "4", "0"]
           J  | join                    "#", "A40"
            « | concatenate             "#A40"
              | print top of stack

1
我也考虑过要N 05AB1E答案-除非我错过了某些事情,否则果冻中的十六进制转换会占用很多字节!
尼克·肯尼迪

1
是的,Jelly中没有任何基于文本的基本转换内置。
乔纳森·艾伦

1
ć斩首 ”是另一种描述方式,大声笑。:D好的答案,但我+1。
凯文·克鲁伊森

6

Japt,16字节

r"%w"²_n16_r17Ãg

尝试运行所有测试用例

r"%w"²_n16_r17Ãg     :Implicit input of string
r                    :Replace
 "%w"                :RegEx /\w/g
     ²               :Duplicate, giving /\w\w/g
      _              :Pass each match through a function
       n16           :  Convert to decimal
          _          :  Pass through the following function, and convert back to hex
           r17       :    Round to the nearest multiple of 17
              Ã      :  End function
               g     :  Get first character

5

8088组装件,IBM PC DOS, 59 58个字节

未组装的清单:

BE 0082     MOV  SI, 82H    ; SI to begining of input string 
AC          LODSB           ; load first '#' char into AL 
B4 0E       MOV  AH, 0EH    ; BIOS display char function  
CD 10       INT  10H        ; call BIOS 
B3 11       MOV  BL, 17     ; set up for divide by 17 
B9 0304     MOV  CX, 0304H  ; hex byte loop counter (CH=3), shift counter (CL=4) 
        LOOP_BYTE: 
AD          LODSW           ; load next two ASCII hex chars into AX 
B7 02       MOV  BH, 2      ; hex chars loop counter
        LOOP_ALPHA:
2C 30       SUB  AL, '0'    ; convert from ASCII 
3C 0A       CMP  AL, 10     ; is digit > 10 (A-F)? 
7C 02       JL   NOT_ALPHA  ; if not, jump to next char
2C 07       SUB  AL, 7      ; ASCII adjust alpha char to binary 
        NOT_ALPHA: 
86 E0       XCHG AH, AL     ; swap first and second chars 
FE CF       DEC  BH         ; decrement loop counter
75 F2       JNZ  LOOP_ALPHA ; loop to next hex char
D2 E0       SHL  AL, CL     ; shift low nibble to high nibble 
02 C4       ADD  AL, AH     ; add first and second nibbles
32 E4       XOR  AH, AH     ; clear AH for add/division
05 0008     ADD  AX, 8      ; add 0.5 (8/16) to round (with overflow) 
F6 F3       DIV  BL         ; divide by 17 
3C 0A       CMP  AL, 10     ; is digit > 10? 
7C 02       JL   DISP_CHAR  ; if not, jump to display digit 
04 07       ADD  AL, 7      ; binary adjust alpha char to ASCII 
        DISP_CHAR: 
04 30       ADD  AL, '0'    ; convert to ASCII 
B4 0E       MOV  AH, 0EH    ; BIOS display char function  
CD 10       INT  10H        ; call BIOS 
FE CD       DEC  CH         ; decrement loop counter 
75 D4       JNZ  LOOP_BYTE  ; loop to next hex byte
C3          RET             ; return to DOS 

独立PC DOS可执行文件。输入是通过命令行,输出是通过控制台。

大多数代码长度都在处理所需的十六进制字符串I / O转换为字节,因为DOS / x86机器代码没有内置的内置代码。

输入/输出:

在此处输入图片说明

下载并测试HEXCLR.COMxxdhexdump:

0000000: be82 00ac b40e cd10 b311 b904 03ad b702  ................
0000010: 2c30 3c0a 7c02 2c07 86e0 fecf 75f2 d2e0  ,0<.|.,.....u...
0000020: 02c4 32e4 0508 00f6 f33c 0a7c 0204 0704  ..2......<.|....
0000030: 30b4 0ecd 10fe cd75 d4c3                 0......u..

3

视网膜0.8.2,88字节

(\w)(.)
$1,$2;
[A-F]
1$&
T`L`d
\d+
$*
+`1,
,16$*
,
8$*
(1{17})*1*;
$#1;
T`d`L`1\d
B\B|;

在线尝试!链接包括测试用例。说明:

(\w)(.)
$1,$2;

配对十六进制数字。

[A-F]
1$&
T`L`d

将每个数字分别转换为十进制。

\d+
$*

将每个十进制数字转换为一进制。

+`1,
,16$*

完成数字对的十六进制转换。

,
8$*
(1{17})*1*;
$#1;

加8并除以17。

T`d`L`1\d
B\B|;

转换回十六进制。






2

Wolfram语言(Mathematica)63 48字节

"#"<>Round[15List@@RGBColor@#]~IntegerString~16&

在线尝试!

-15字节感谢attinat!更换StringJoin<>和压缩的语法。

  1. RGBColor@#将输入的字符串转换为RGBColor[r, g, b]具有三个浮点参数的形式的颜色,范围为0..1。

  2. Round[15 List @@ %]将三个参数的列表乘以15,然后将它们四舍五入为最接近的整数。现在,我们有一个与三个所需的十六进制数字相对应的三个整数值的列表。

  3. %~IntegerString~16 将这个由三个整数组成的列表转换为三个由一个字符组成的十六进制字符串的列表。

  4. "#"<>%前置一个#字符并将所有这些字符连接在一起。



2

MathGolf19 12 字节

╞2/¢8+F/¢'#▌

输出为字符列表。如果不允许这样做,y则必须添加其他尾随以将字符列表连接到字符串。

由于使用了@maxb,因此-7个字节,因为我经过了内置(2ô_2<\1>]to 2/)。

在线尝试。

说明:

              # Remove the first character from the (implicit) input-string
 2/            # Split the string into parts of size 2
   ¢           # Convert each part from hexadecimal to integer
    8+         # Add 8 to each integer
      F/       # Integer-divide each integer by 17
        ¢      # Then convert back from integer to hexadecimal
         '#▌  '# Prepend '#' in front of the list
               # (which is output implicitly as result)

2

红宝石(2.5.3),4544,42个字节

->a{a.gsub(/\w./){|b|"%X"%((8+b.hex)/17)}}

编辑:保存了一个字节,因为我们不需要在正则表达式中的第二个字符使用字符组(受尼尔的回答启发)

编辑2:保存2个字节,因为破折号火箭lambda语法不需要在参数周围使用括号


2
通过在stdin上输入并使用-p标志可以节省7个字节,$&而在块内使用而不是参数可以节省另外2 个字节:tio.run/##KypNqvz/…
约旦

1
@乔丹谢谢!我什么都不知道,所以这对将来打高尔夫球
很有帮助

1

蟒2(109 101 97 85 83个 74字节)

lambda x:'#'+''.join(hex(int(int(x[i:i+2],16)/17.+.5))[2:]for i in[1,3,5])

“最近距离”通过除以17并四舍五入来处理。

改进之处:

使用int(...+.5)技巧而不是-8个字节int(round(...))

通过使用列表理解而不是-4字节 map()

通过#在输出中进行硬编码来获得-1字节(感谢@movatica)

-10字节,不使用re.findall("..",...)显式String拼接

通过不使用列表join推导来获得-2字节,而是使用内联生成器表达式(感谢@movatica)

-1字节,不剪接:7蓝色部分的结尾

通过更好的颜色迭代来实现-9个字节-即遍历索引,而不是实际字符(感谢@movatica)


1
@movatica-您是对的,添加了它
Grzegorz Oledzki

1
通过硬编码'#'而不是节省1个字节x[0]
movatica

1
您可以跳过内部的列表理解''.join(...),因为它也处理生成器表达式。只需删除,[]然后再保存2个字节即可:)
movatica

1
谢谢!range(1,6,2)甚至更好[1,3,5]
Grzegorz Oledzki

1
乔纳森·艾伦(Jonathan Allen)为mz Pzthon3版本中的四舍五入提出了另一种技巧。它也适用于此:lambda x:'#'+''.join(hex((int(x[i:i+2],16)+8)/17)[2:]for i in[1,3,5])-> 69字节
movatica

1

Perl 5中 -p35个 34字节

@nwellnhof保存了一个字节

s|\w.|sprintf'%X',.5+(hex$&)/17|ge

在线尝试!

从STDIN读取,#使用除以17的方法替换不正确的单个字符的每对项,以找到最接近的项,然后隐式输出(-p)结果。


1

Python 3,67个字节

f=lambda x:(f(x[:-2])if x[3:]else"#")+f'{(int(x[-2:],16)+8)//17:X}'

欢迎。考虑添加描述,解释或链接到在线解释器,例如TIO,我们可以在其中运行您的代码。纯代码答案往往会自动标记为低质量。有关示例,请参见其他现有答案。
mbomb007

0

红色,103字节

func[c][r: to 1 c to #1 rejoin reverse collect[loop 3[keep to-hex/size r % 256 + 8 / 17 1 r: r / 256]]]

在线尝试!

原来,当前的Red Linux版本没有该hex-to-rgb功能的实现,这就是为什么我要“手动”进行基本转换的原因:)

在Windows 的Red GUI控制台中,这可以正常工作:

红色,94字节

f: func[c][r: hex-to-rgb c to #1 rejoin collect[repeat n 3[keep to-hex/size r/:n + 8 / 17 1]]]


0

木炭,22字节

#F⪪⮌…⮌S⁶¦²⍘÷⁺⁸⍘ι¹⁶¦¹⁷φ

在线尝试!链接是详细版本的代码。说明:

#                       Literal `#`
      S                 Input string
     ⮌                  Reversed
    …  ⁶                Truncated to length 6
   ⮌                    Reversed
  ⪪      ²              Split into pairs of characters
 F                      Loop over each pair
               ι        Current pair
              ⍘ ¹⁶      Convert from base 16
            ⁺⁸          Add 8
           ÷       ¹⁷   Integer divide by 17
          ⍘          φ  Convert to large base
                        Implicitly print


0

Pyth,20个字节

+\#sm.H/+8id16 17c3t

在这里尝试。

注意:如果以上链接引发ImportError,请转至此处;否则,请转到此处。当前在“官方”页面上有一个错误,这是Maltysen的临时解决方案。官方版本确定后,此链接可能会停止工作。


0

第四位(gforth),87字节

: f d>s 1- hex ." #"3. do 2 + dup 2 s>number d>s 17 /mod swap 8 > - 1 .r loop decimal ;

在线尝试!

说明

  1. 忽略/截断输入(#)的第一个字符
  2. 将解释器设置为十六进制模式
  3. 输出量 #
  4. 循环3次,每个循环中:
    1. 将2加到字串起始地址
    2. 将字符串中的后2个字符转换为十六进制数字
    3. 使用除法和模块除以17(0x11)以获得缩短的组件的最接近值
    4. 输出没有前空格
  5. 将解释器设置回十进制模式

代码说明

: f                    \ start a new word definition
  d>s                  \ convert double-length int to single-length (cheaper drop)
  1- hex               \ subtract 1 from string address, set current base to 10
  ." #"                \ output #
  3. do                \ start a loop from 0 to 2 (inclusive)
    2 + dup            \ add 2 to string starting address and duplicate
    2 s>number         \ parse the next 2 characters to a hexadecimal value
    d>s                \ convert result to single-length value
    17 / mod           \ get the quotient and remainder of dividing by 17
    swap               \ move the remainder to the top of the stack
    8 > -              \ if remainder is greater than 8, add 1 to quotient
    1 .r               \ output result (as hexadecimal) with no space
  loop                 \ end the loop
  decimal              \ set interpreter back to base 10 (decimal)
;                      \ end the word definition


0

K4,39个字节

解:

"#",{x@_1%17%8+16/:x?y}[.Q.nA]@/:3 2#1_

说明:

使用与许多这些答案相同的策略(即加8,除以17):

"#",{x@_1%17%8+16/:x?y}[.Q.nA]@/:3 2#1_ / the solution
                                     1_ / drop first character
                                 3 2#   / reshape as 3x2 (e.g. "FF", "00", "00")
                              @/:       / apply each-right to left lambda
    {                 }[     ]          / lambda with first argument populated
                        .Q.nA           / "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                   x?y                  / get index of hex character, e.g. "AA" => 10 10
               16/:                     / convert from base-16
             8+                         / add 8
          17%                           / 17 divided by...
        1%                              / 1 divided by...
       _                                / floor
     x@                                 / index into .Q.nA to get hex character
"#",                                    / prepend "#"

额外:

  • "#",{x@*16\:a?&/a:abs(17*!16)-16/:x?y}[.Q.nA]@/:3 2#1_-我最初的想法是54个字节
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.