Encuentra el color hexadecimal de tres dígitos más cercano

23

En CSS, los colores se pueden especificar mediante un "triplete hexadecimal": un número hexadecimal de tres bytes (seis dígitos) donde cada byte representa los componentes rojo, verde o azul del color. Por ejemplo, #FF0000es completamente rojo y es equivalente a rgb(255, 0, 0).

Los colores también se pueden representar mediante la notación abreviada que utiliza tres dígitos hexadecimales. La taquigrafía se expande a la forma de seis dígitos duplicando cada dígito. Por ejemplo, se #ABCconvierte #AABBCC.

Como hay menos dígitos en la taquigrafía hexadecimal, se pueden representar menos colores.

El reto

Escriba un programa o función que tome un código de color hexadecimal de seis dígitos y genere el código de color de tres dígitos más cercano.

Aquí hay un ejemplo:

  • Código hexadecimal de entrada: # 28a086
  • Componente rojo
    • 0x28 = 40 (decimal)
    • 0x22 = 34
    • 0x33 = 51
    • 0x22 está más cerca, por lo que el primer dígito del código de color acortado es 2
  • Componente verde
    • 0xa0 = 160
    • 0x99 = 153
    • 0xaa = 170
    • 0x99 está más cerca, entonces el segundo dígito es 9
  • Componente azul
    • 0x86 = 134
    • 0x77 = 119
    • 0x88 = 136
    • 0x88 está más cerca, entonces el tercer dígito es 8
  • El código de color acortado es # 298 (que se expande a # 229988)

Su programa o función debe aceptar como entrada un código de color hexadecimal de seis dígitos antepuesto #y generar un código de color de tres dígitos antepuesto #.

Ejemplos

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

Tanteo

Este es un desafío de código de golf, por lo que gana la respuesta más corta en su idioma. Aplican reglas estándar.

wrymug
fuente
1
"sumando la diferencia entre cada componente del código de color completo y el componente correspondiente del código de color abreviado" - esta parte es confusa. No hay adición en ningún lado, ¿verdad?
Grzegorz Oledzki
3
Tenga en cuenta que si simplemente suelta dígitos alternativos, cada color corto representa un número igual de colores completos, por lo que podría considerarse una mejor representación que el color más cercano.
Neil
66
Vi esto en el Sandbox, pero olvidé mencionar que no creo que requiera #agregar nada al desafío.
Shaggy
2
¿Podemos mostrar en minúsculas?
Arnauld
2
0x22 es 34, no 30
Kruga

Respuestas:

4

JavaScript (ES6), 55 bytes

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

Pruébalo en línea!

Arnauld
fuente
Buen uso de toString! No me di cuenta de que podría tomar una raíz radical.
wrymug
8

05AB1E , 13 bytes

ćs2ôH8+17÷hJ«

Pruébalo en línea!

¿Cómo?

ć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
Jonathan Allan
fuente
1
Pensé en hacer la respuesta N 05AB1E también: a menos que me haya perdido algo, ¡la conversión hexadecimal en Jelly toma muchos bytes!
Nick Kennedy
1
Sí, no incorporado para ninguna conversión de base de texto en Jelly.
Jonathan Allan
1
" ćdecapitar " Esa es otra forma de describirlo, jajaja. : D Bonita respuesta, +1 de mi parte.
Kevin Cruijssen
6

Japt , 16 bytes

r"%w"²_n16_r17Ãg

Pruébalo o ejecuta todos los casos de prueba

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
Lanudo
fuente
5

8088 Assembly, IBM PC DOS, 59 58 bytes

Listado sin ensamblar:

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 independiente ejecutable de DOS. La entrada es a través de la línea de comando, la salida es a la consola.

La mayor parte de la longitud del código está manejando la conversión de la E / S de cadena hexadecimal requerida en bytes, ya que el código de máquina DOS / x86 no tiene incorporados para eso.

E / S:

ingrese la descripción de la imagen aquí

Descargue y pruebe HEXCLR.COM , o xxdhexdump:

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..
640 KB
fuente
3

Retina 0.8.2 , 88 bytes

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

Pruébalo en línea! El enlace incluye casos de prueba. Explicación:

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

Empareje los dígitos hexadecimales.

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

Convierta cada dígito por separado a decimal.

\d+
$*

Convierta cada dígito decimal a unario.

+`1,
,16$*

Termine la conversión hexadecimal del par de dígitos.

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

Suma 8 y divide entre 17.

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

Convertir de nuevo a hexadecimal.

Neil
fuente
3

Python 3 , 72 70 68 bytes

lambda x:'#'+''.join(f"{(int(x[i:i+2],16)+8)//17:X}"for i in(1,3,5))

Pruébalo en línea!

Esta es una respuesta original del puerto de Grzegorz Oledzkis , que le ayudé a jugar golf.

Dos características de Python 3 nos ayudan a guardar bytes:

  • División de punto flotante por defecto
  • Formatear literales de cadena

-2 bytes gracias a Jonathan Allan

movatica
fuente
2
(int(x[i:i+2],16)+8)//17salva 2
Jonathan Allan
2

Wolfram Language (Mathematica) , 63 48 bytes

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

Pruébalo en línea!

-15 bytes gracias a attinat ! Sustitución StringJoincon <>y comprimiendo la sintaxis.

  1. RGBColor@#convierte la cadena de entrada a un color del formulario RGBColor[r, g, b]con tres argumentos de punto flotante en el rango 0..1.

  2. Round[15 List @@ %]multiplica la lista de tres argumentos por 15 y los redondea al entero más cercano. Ahora tenemos una lista de tres valores enteros correspondientes a los tres dígitos hexadecimales deseados.

  3. %~IntegerString~16 convierte esta lista de tres enteros en una lista de tres cadenas hexadecimales de un carácter cada una.

  4. "#"<>%antepone un #personaje y une todos estos personajes juntos.

romano
fuente
1
48 bytes
attinat
2

MathGolf , 19 12 bytes

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

Salida como lista de caracteres. Si esto no está permitido, yse debe agregar un seguimiento adicional para unir la lista de caracteres a una cadena.

-7 bytes gracias a @maxb , ya que miré más allá de un incorporado ( 2ô_2<\1>]a 2/).

Pruébalo en línea.

Explicación:

              # 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)
Kevin Cruijssen
fuente
2

Ruby (2.5.3), 45 , 44 , 42 bytes

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

EDITAR: guardado un byte porque no necesitamos un grupo de caracteres para el segundo carácter en la expresión regular (inspirado en la respuesta de Neil)

EDIT 2: se guardaron 2 bytes porque la sintaxis lambda dash rocket no necesita corchetes alrededor del argumento

DaveMongoose
fuente
2
Puede guardar 7 bytes tomando datos en stdin y usando la -pbandera y otros 2 usando en $&lugar de un argumento dentro del bloque: tio.run/##KypNqvz/…
Jordania
1
@ Jordan Gracias! No conocía ninguno de esos, así que es una verdadera ayuda para futuros intentos de golf
DaveMongoose
1

Python 2 ( 109 101 97 85 83 74 bytes)

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

La "distancia más cercana" se maneja por división por 17 y redondeo.

Mejoras:

-8 bytes usando el int(...+.5)truco en lugar deint(round(...))

-4 bytes utilizando la comprensión de la lista en lugar de map()

-1 byte mediante codificación #en la salida (gracias @movatica)

-10 bytes al no utilizar re.findall("..",...)a favor de un empalme explícito de cadenas

-2 bytes al no usar la comprensión de la lista, sino una expresión de generador en línea en join(gracias @movatica)

-1 byte al no empalmar el :7final de la parte azul

-9 bytes por mejor iteración sobre colores, es decir, iteración sobre índices, no caracteres reales (gracias @movatica)

Grzegorz Oledzki
fuente
1
@movatica - tienes razón, lo agregó
Grzegorz Oledzki
1
Ahorre 1 byte codificando en '#'lugar de x[0].
movatica
1
Puede omitir la comprensión de la lista ''.join(...), ya que también maneja una expresión generadora. Simplemente elimine []y guarde 2 bytes más :)
movatica
1
¡Gracias! range(1,6,2)es aún mejor con[1,3,5]
Grzegorz Oledzki
1
Jonathan Allen propuso un truco diferente para redondear en la versión mz Pzthon3. También se aplica aquí: lambda x:'#'+''.join(hex((int(x[i:i+2],16)+8)/17)[2:]for i in[1,3,5])-> 69 bytes
movatica
1

Perl 5 -p , 35 34 bytes

@nwellnhof guardó un byte

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

Pruébalo en línea!

Lee desde STDIN, reemplaza cada par de elementos que no están #con el carácter único apropiado usando el método de división por 17 para encontrar el más cercano, luego, de manera implícita, genera ( -p) el resultado.

Xcali
fuente
1

Python 3, 67 bytes

f=lambda x:(f(x[:-2])if x[3:]else"#")+f'{(int(x[-2:],16)+8)//17:X}'
GSy
fuente
Bienvenido. Considere agregar una descripción, explicación o enlace a un intérprete en línea, como TIO, donde podemos ejecutar su código. Las respuestas de solo código tienden a marcarse automáticamente como de baja calidad. Ver otras respuestas existentes para ejemplos.
mbomb007
0

Rojo , 103 bytes

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

Pruébalo en línea!

Resultó que la versión actual de Red de Linux no tiene una implementación de la hex-to-rgbfunción, por eso hago la conversión de base "manualmente" :)

Esto funciona bien en la consola Red GUI en Windows:

Rojo , 94 bytes

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

Carbón de leña , 22 bytes

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

Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:

#                       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
Neil
fuente
0

Pyth , 20 bytes

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

Pruébalo aquí

NOTA: En caso de que el enlace anterior genere un ImportError, vaya aquí ; Actualmente hay un error en la página "oficial", y esta es una solución temporal de Maltysen . Este enlace puede dejar de funcionar después de que se corrija el oficial.

Erik el Outgolfer
fuente
0

Adelante (gforth) , 87 bytes

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

Pruébalo en línea!

Explicación

  1. Ignorar / truncar el primer carácter de input ( #)
  2. Establecer intérprete en modo hexadecimal
  3. Salida #
  4. Bucle 3 veces, en cada bucle:
    1. Agregue 2 a la dirección de inicio de la cadena
    2. Convierta los siguientes 2 caracteres en cadena a un número hexadecimal
    3. Use la división y el módulo por 17 ( 0x11) para obtener el valor más cercano para el componente acortado
    4. Salida sin espacio anterior
  5. Establecer el intérprete nuevamente en modo decimal

Explicación del Código

: 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
reffu
fuente
0

K4 , 39 bytes

Solución:

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

Explicación:

Utiliza la misma estrategia que muchas de estas respuestas (es decir, agregue 8, divida por 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 "#"

Extra:

  • "#",{x@*16\:a?&/a:abs(17*!16)-16/:x?y}[.Q.nA]@/:3 2#1_- mi idea original para 54 bytes
callejero
fuente