Trouvez la couleur hexadécimale à trois chiffres la plus proche

23

En CSS, les couleurs peuvent être spécifiées par un "triplet hexadécimal" - un nombre hexadécimal à trois octets (six chiffres) où chaque octet représente les composantes rouge, verte ou bleue de la couleur. Par exemple, #FF0000est complètement rouge et équivaut à rgb(255, 0, 0).

Les couleurs peuvent également être représentées par la notation abrégée qui utilise trois chiffres hexadécimaux. La sténographie s'étend à la forme à six chiffres en dupliquant chaque chiffre. Par exemple, #ABCdevient #AABBCC.

Puisqu'il y a moins de chiffres dans le raccourci hexadécimal, moins de couleurs peuvent être représentées.

Le défi

Écrivez un programme ou une fonction qui prend un code couleur hexadécimal à six chiffres et génère le code couleur à trois chiffres le plus proche.

Voici un exemple:

  • Entrez le code hexadécimal: # 28a086
  • Composant rouge
    • 0x28 = 40 (décimal)
    • 0x22 = 34
    • 0x33 = 51
    • 0x22 est plus proche, donc le premier chiffre du code de couleur raccourci est 2
  • Composant vert
    • 0xa0 = 160
    • 0x99 = 153
    • 0xaa = 170
    • 0x99 est plus proche, donc le deuxième chiffre est 9
  • Composant bleu
    • 0x86 = 134
    • 0x77 = 119
    • 0x88 = 136
    • 0x88 est plus proche, donc le troisième chiffre est 8
  • Le code de couleur raccourci est # 298 (qui se développe en # 229988)

Votre programme ou fonction doit accepter comme entrée un code de couleur hexadécimal à six chiffres précédé de #et sortir un code de couleur à trois chiffres précédé de #.

Exemples

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

Notation

Il s'agit d'un défi de code-golf, donc la réponse la plus courte dans votre langue l'emporte! Des règles standard s'appliquent.

wrymug
la source
1
"en additionnant la différence entre chaque composant du code couleur complet et le composant correspondant du code couleur raccourci" - cette partie prête à confusion. Il n'y a aucun ajout nulle part, non?
Grzegorz Oledzki
3
Notez que si vous déposez simplement des chiffres alternatifs, chaque couleur courte représente un nombre égal de couleurs pleines, ce qui pourrait être considéré comme une meilleure représentation que la couleur la plus proche.
Neil
6
J'ai vu cela dans le bac à sable, mais j'ai oublié de mentionner que je ne pense pas que l'exigence #ajoute quelque chose au défi.
Shaggy
2
Pouvons-nous sortir en minuscules?
Arnauld
2
0x22 est 34, pas 30
Kruga

Réponses:

4

JavaScript (ES6), 55 octets

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

Essayez-le en ligne!

Arnauld
la source
Bonne utilisation de toString! Je ne savais pas que cela pouvait prendre un paramètre radix.
wrymug
8

05AB1E , 13 octets

ćs2ôH8+17÷hJ«

Essayez-le en ligne!

Comment?

ć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
la source
1
J'ai aussi pensé à faire la réponse N 05AB1E - à moins que j'aie manqué quelque chose, la conversion hexadécimale dans Jelly prend beaucoup d'octets!
Nick Kennedy
1
Ouais, pas intégré pour les conversions de base textuelles dans Jelly.
Jonathan Allan
1
" ćdécapiter " C'est une autre façon de le décrire, lol. : D Belle réponse cependant, +1 de ma part.
Kevin Cruijssen
6

Japt , 16 octets

r"%w"²_n16_r17Ãg

Essayez-le ou exécutez tous les cas de test

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
Hirsute
la source
5

8088 Assembly, IBM PC DOS, 59 58 octets

Liste non assemblée:

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 

Exécutable PC DOS autonome. L'entrée se fait via la ligne de commande, la sortie est vers la console.

La majeure partie de la longueur du code gère la conversion des E / S de chaîne hexadécimale requises en octets, car le code machine DOS / x86 n'a pas de fonction intégrée pour cela.

E / S:

entrez la description de l'image ici

Téléchargez et testez HEXCLR.COM , ou 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 Ko
la source
3

Retina 0.8.2 , 88 octets

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

Essayez-le en ligne! Le lien inclut des cas de test. Explication:

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

Associez les chiffres hexadécimaux.

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

Convertissez chaque chiffre séparément en décimal.

\d+
$*

Convertissez chaque chiffre décimal en unaire.

+`1,
,16$*

Terminez la conversion hexadécimale de la paire de chiffres.

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

Additionnez 8 et divisez par 17.

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

Reconvertissez en hexadécimal.

Neil
la source
3

Python 3 , 72 70 68 octets

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

Essayez-le en ligne!

Il s'agit d'un port de Grzegorz Oledzkis réponse originale , que je l'ai aidé à jouer au golf.

Deux fonctionnalités de Python 3 nous aident à économiser des octets:

  • Division en virgule flottante par défaut
  • Format des littéraux de chaîne

-2 octets merci à Jonathan Allan

movatica
la source
2
(int(x[i:i+2],16)+8)//17enregistre 2
Jonathan Allan
2

Wolfram Language (Mathematica) , 63 48 octets

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

Essayez-le en ligne!

-15 octets grâce à attinat ! Le remplacement StringJoinavec <>et la compression de la syntaxe.

  1. RGBColor@#convertit la chaîne d'entrée en une couleur du formulaire RGBColor[r, g, b]avec trois arguments à virgule flottante dans la plage 0..1.

  2. Round[15 List @@ %]multiplie la liste de trois arguments par 15 et les arrondit à l'entier le plus proche. Nous avons maintenant une liste de trois valeurs entières correspondant aux trois chiffres hexadécimaux souhaités.

  3. %~IntegerString~16 convertit cette liste de trois entiers en une liste de trois chaînes hexadécimales d'un caractère chacune.

  4. "#"<>%ajoute un #caractère et joint tous ces caractères.

romain
la source
1
48 octets
attinat
2

MathGolf , 19 12 octets

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

Sortie sous forme de liste de caractères. Si cela n'est pas autorisé, une fin supplémentaire ydoit être ajoutée pour joindre la liste de caractères à une chaîne.

-7 octets grâce à @maxb , puisque j'ai regardé au-delà d'un builtin ( 2ô_2<\1>]to 2/).

Essayez-le en ligne.

Explication:

              # 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
la source
2

Ruby (2.5.3), 45 , 44 , 42 octets

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

EDIT: enregistré un octet parce que nous n'avons pas besoin d'un groupe de caractères pour le deuxième caractère dans l'expression régulière (inspiré par la réponse de Neil)

EDIT 2: économisé 2 octets car la syntaxe lambda de la fusée de tiret n'a pas besoin de crochets autour de l'argument

DaveMongoose
la source
2
Vous pouvez économiser 7 octets en prenant une entrée sur stdin et en utilisant le -pdrapeau et 2 autres en utilisant à la $&place d'un argument à l'intérieur du bloc: tio.run/##KypNqvz/…
Jordan
1
@Jordan Merci! Je ne connaissais aucun de ceux-là, c'est donc une réelle aide pour les futures tentatives de golf
DaveMongoose
1

Python 2 ( 109 101 97 85 83 74 octets)

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

La "distance la plus proche" est traitée par division par 17 et arrondie.

Améliorations:

-8 octets en utilisant l' int(...+.5)astuce au lieu deint(round(...))

-4 octets en utilisant la compréhension de liste au lieu de map()

-1 octet par codage #en dur dans la sortie (merci @movatica)

-10 octets en n'utilisant pas re.findall("..",...)en faveur d'un épissage de chaîne explicite

-2 octets en n'utilisant pas la compréhension de liste, mais une expression de générateur en ligne dans join(merci @movatica)

-1 octet en ne collant pas la :7fin de la partie bleue

-9 octets par une meilleure itération sur les couleurs - ie itération sur les index, pas sur les caractères réels (merci @movatica)

Grzegorz Oledzki
la source
1
@movatica - vous avez raison, l'a ajouté
Grzegorz Oledzki
1
Économisez 1 octet en codant en dur '#'au lieu de x[0].
movatica
1
Vous pouvez ignorer la compréhension de la liste à l'intérieur ''.join(...), car elle gère également une expression de générateur. Supprimez simplement le []et enregistrez 2 octets supplémentaires :)
movatica
1
Merci! range(1,6,2)c'est encore mieux avec[1,3,5]
Grzegorz Oledzki
1
Jonathan Allen a proposé une astuce différente pour l'arrondi dans la version mz Pzthon3. Cela s'applique également ici: lambda x:'#'+''.join(hex((int(x[i:i+2],16)+8)/17)[2:]for i in[1,3,5])-> 69 octets
movatica
1

Perl 5 -p , 35 34 octets

@nwellnhof a enregistré un octet

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

Essayez-le en ligne!

Lit à partir de STDIN, remplace chaque paire d'éléments qui n'est pas #avec le caractère unique approprié en utilisant la méthode de division par 17 pour trouver le plus proche, puis sort implicitement ( -p) le résultat.

Xcali
la source
1

Python 3, 67 octets

f=lambda x:(f(x[:-2])if x[3:]else"#")+f'{(int(x[-2:],16)+8)//17:X}'
GSy
la source
Bienvenue. Pensez à ajouter une description, une explication ou un lien vers un interprète en ligne, tel que TIO où nous pouvons exécuter votre code. Les réponses uniquement codées ont tendance à être automatiquement signalées comme de faible qualité. Voir d'autres réponses existantes pour des exemples.
mbomb007
0

Rouge , 103 octets

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

Essayez-le en ligne!

Il s'est avéré que la version Linux actuelle de Red n'a pas d'implémentation de la hex-to-rgbfonction, c'est pourquoi je fais la conversion de base "manuellement" :)

Cela fonctionne bien dans la console GUI rouge sous Windows:

Rouge , 94 octets

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
la source
0

Fusain , 22 octets

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

Essayez-le en ligne! Le lien est vers la version détaillée du code. Explication:

#                       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
la source
0

Pyth , 20 octets

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

Essayez-le ici.

REMARQUE: Si le lien ci-dessus soulève un ImportError, allez ici à la place; il y a actuellement un bug dans la page "officielle", et c'est une solution temporaire de Maltysen . Ce lien peut cesser de fonctionner une fois que le lien officiel est corrigé.

Erik le Outgolfer
la source
0

Forth (gforth) , 87 octets

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

Essayez-le en ligne!

Explication

  1. Ignorer / tronquer le premier caractère de input ( #)
  2. Mettre l'interpréteur en mode hexadécimal
  3. Sortie #
  4. Boucle 3 fois, dans chaque boucle:
    1. Ajouter 2 à l'adresse de début de la chaîne
    2. Convertir les 2 caractères suivants de la chaîne en un nombre hexadécimal
    3. Utilisez la division et le module par 17 ( 0x11) pour obtenir la valeur la plus proche pour le composant raccourci
    4. Sortie sans espace précédent
  5. Rétablir l'interpréteur en mode décimal

Explication du code

: 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
la source
0

K4 , 39 octets

Solution:

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

Explication:

Utilise la même stratégie que beaucoup de ces réponses (c.-à-d. Ajouter 8, diviser par 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 "#"

Supplémentaire:

  • "#",{x@*16\:a?&/a:abs(17*!16)-16/:x?y}[.Q.nA]@/:3 2#1_- mon idée originale pour 54 octets
streetster
la source