Trova il colore esadecimale a tre cifre più vicino


23

Nel CSS, i colori possono essere specificati da una "tripletta esadecimale" - un numero esadecimale a tre byte (sei cifre) in cui ogni byte rappresenta i componenti rosso, verde o blu del colore. Ad esempio, #FF0000è completamente rosso ed è equivalente a rgb(255, 0, 0).

I colori possono anche essere rappresentati dalla notazione abbreviata che utilizza tre cifre esadecimali. La scorciatoia si espande nella forma di sei cifre duplicando ogni cifra. Ad esempio, #ABCdiventa #AABBCC.

Poiché nella stenografia esadecimale sono presenti meno cifre, è possibile rappresentare un numero inferiore di colori.

La sfida

Scrivi un programma o una funzione che accetta un codice colore esadecimale a sei cifre e genera il codice colore a tre cifre più vicino.

Ecco un esempio:

  • Immettere il codice esadecimale: # 28a086
  • Componente rosso
    • 0x28 = 40 (decimale)
    • 0x22 = 34
    • 0x33 = 51
    • 0x22 è più vicino, quindi la prima cifra del codice colore abbreviato è 2
  • Componente verde
    • 0xa0 = 160
    • 0x99 = 153
    • 0xaa = 170
    • 0x99 è più vicino, quindi la seconda cifra è 9
  • Componente blu
    • 0x86 = 134
    • 0x77 = 119
    • 0x88 = 136
    • 0x88 è più vicino, quindi la terza cifra è 8
  • Il codice colore abbreviato è # 298 (che si espande in # 229988)

Il programma o la funzione deve accettare come input un codice colore esadecimale a sei cifre anteposto #e un codice colore a tre cifre anteposto #.

Esempi

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

punteggio

Questa è una sfida di code-golf, quindi vince la risposta più breve nella tua lingua! Si applicano le regole standard.


1
"sommando la differenza tra ogni componente del codice colore completo e il componente corrispondente del codice colore abbreviato" - questa parte è confusa. Non è possibile aggiungere altrove, giusto?
— Grzegorz Oledzki,

3
Si noti che se si rilasciano semplicemente cifre alternate, ciascun colore corto rappresenta un numero uguale di colori pieni, in modo da poter considerare una rappresentazione migliore del colore più vicino.
— Neil,

6
L'ho visto nella Sandbox ma ho dimenticato di dire che non penso che richiedere di #aggiungere qualcosa alla sfida.
— Shaggy,

2
Possiamo produrre in minuscolo?
— Arnauld,

2
0x22 è 34, non 30
— Kruga

Risposte:


4

JavaScript (ES6), 55 byte

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

Provalo online!


Buon uso di toString! Non mi ero reso conto che ci sarebbe voluto un radix param.
— Wrymug

8

05AB1E , 13 byte

ćs2ôH8+17÷hJ«

Provalo online!

Come?

ć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
Ho pensato di fare anche la risposta N 05AB1E: a meno che non mi sia perso qualcosa, la conversione esadecimale in Jelly richiede parecchi byte!
— Nick Kennedy il

1
Sì, nessun built-in per eventuali conversioni testuali di base in Jelly.
— Jonathan Allan,

1
" ćdecapitare " Questo è un altro modo per descriverlo, lol. : D Bella risposta però, +1 da parte mia.
— Kevin Cruijssen,

6

Japt , 16 byte

r"%w"²_n16_r17Ãg

Provalo o esegui tutti i casi di 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

5

8088 Assembly, IBM PC DOS, 59 58 byte

Elenco non assemblato:

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 

Eseguibile DOS per PC autonomo. L'input avviene tramite riga di comando, l'output è console.

La maggior parte della lunghezza del codice sta gestendo la conversione dell'I / O della stringa esadecimale richiesta in byte, poiché il codice macchina DOS / x86 non ha built-in per questo.

I / O:

inserisci qui la descrizione dell'immagine

Scarica e prova 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..

3

Retina 0.8.2 , 88 byte

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

Provalo online! Il link include casi di test. Spiegazione:

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

Associare le cifre esadecimali.

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

Converti ogni cifra separatamente in decimale.

\d+
$*

Converti ogni cifra decimale in unaria.

+`1,
,16$*

Termina la conversione esadecimale della coppia di cifre.

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

Aggiungi 8 e dividi per 17.

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

Converti indietro in esadecimale.






2

Wolfram Language (Mathematica) , 63 48 byte

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

Provalo online!

-15 byte grazie ad attinat ! Sostituendo StringJoincon <>e comprimendo la sintassi.

  1. RGBColor@#converte la stringa di input in un colore del modulo RGBColor[r, g, b]con tre argomenti in virgola mobile nell'intervallo 0..1.

  2. Round[15 List @@ %]moltiplica l'elenco di tre argomenti per 15 e li arrotonda al numero intero più vicino. Ora abbiamo un elenco di tre valori interi corrispondenti alle tre cifre esadecimali desiderate.

  3. %~IntegerString~16 converte questo elenco di tre numeri interi in un elenco di tre stringhe esadecimali di un carattere ciascuna.

  4. "#"<>%antepone un #personaggio e unisce tutti questi personaggi.



2

MathGolf , 19 12 byte

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

Output come elenco di caratteri. Se ciò non è consentito, yè necessario aggiungere un finale aggiuntivo per unire l'elenco di caratteri a una stringa.

-7 byte grazie a @maxb , poiché ho guardato oltre un builtin ( 2ô_2<\1>]to 2/).

Provalo online.

Spiegazione:

╞              # 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

Rubino (2.5.3), 45 , 44 , 42 byte

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

EDIT: salvato un byte perché non abbiamo bisogno di un gruppo di caratteri per il secondo carattere nella regex (ispirato alla risposta di Neil)

EDIT 2: salvato 2 byte perché la sintassi del razzo lambda non ha bisogno di parentesi attorno all'argomento


2
Puoi salvare 7 byte prendendo input su stdin e usando la -pbandiera e altri 2 usando $&invece di un argomento all'interno del blocco: tio.run/##KypNqvz/…
— Jordan

1
@Jordan Grazie! Non ne sapevo nessuno dei due, quindi è un vero aiuto per i futuri tentativi di golf
— DaveMongoose,

1

Python 2 ( 109 101 97 85 83 74 byte)

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

La "distanza più vicina" viene gestita per divisione per 17 e arrotondamento.

miglioramenti:

-8 byte usando il int(...+.5)trucco invece diint(round(...))

-4 byte utilizzando la comprensione dell'elenco anziché map()

-1 byte tramite #hardcoding nell'output (grazie @movatica)

-10 byte non usando re.findall("..",...)a favore della giunzione di stringa esplicita

-2 byte non usando la comprensione dell'elenco, ma un'espressione del generatore inline in join(grazie @movatica)

-1 byte non giuntando la :7fine per la parte blu

-9 byte mediante una migliore iterazione sui colori - ovvero iterando sugli indici, non sui caratteri effettivi (grazie @movatica)


1
@movatica - hai ragione, l'ho aggiunto
— Grzegorz Oledzki il

1
Salva 1 byte tramite hardcoding '#'anziché x[0].
— movatica,

1
È possibile saltare la comprensione dell'elenco all'interno ''.join(...), poiché gestisce anche un'espressione del generatore. Basta rimuovere []e salvare altri 2 byte :)
— movatica, il

1
Grazie! range(1,6,2)è ancora meglio con[1,3,5]
— Grzegorz Oledzki

1
Jonathan Allen ha proposto un trucco diverso per l'arrotondamento nella versione mz Pzthon3. Si applica anche qui: lambda x:'#'+''.join(hex((int(x[i:i+2],16)+8)/17)[2:]for i in[1,3,5])-> 69 byte
— movatica

1

Perl 5 -p , 35 34 byte

@nwellnhof ha salvato un byte

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

Provalo online!

Legge da STDIN, sostituisce ogni coppia di elementi che non è #con il singolo carattere appropriato usando la divisione per 17 metodo per trovare il più vicino, quindi genera implicitamente ( -p) il risultato.


1

Python 3, 67 byte

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

Benvenuto. Valuta la possibilità di aggiungere una descrizione, una spiegazione o un link a un interprete online, come TIO, dove possiamo eseguire il tuo codice. Le risposte di solo codice tendono ad essere contrassegnate automaticamente come di bassa qualità. Vedi altre risposte esistenti per esempi.
— mbomb007,

0

Rosso , 103 byte

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

Provalo online!

Si è scoperto che l'attuale versione Linux di Red non ha un'implementazione della hex-to-rgbfunzione, ecco perché faccio la conversione di base "manualmente" :)

Funziona bene nella console della GUI rossa su Windows:

Rosso , 94 byte

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

Carbone , 22 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. Spiegazione:

#                       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 byte

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

Provalo qui.

NOTA: Nel caso in cui il link sopra sollevi un ImportError, vai qui ; c'è attualmente un bug nella pagina "ufficiale", e questa è una soluzione temporanea di Maltysen . Questo collegamento potrebbe smettere di funzionare dopo che quello ufficiale è stato corretto.


0

Forth (gforth) , 87 byte

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

Provalo online!

Spiegazione

  1. Ignora / tronca il primo carattere di input ( #)
  2. Impostare l'interprete in modalità esadecimale
  3. Produzione #
  4. Ripeti 3 volte, in ciascun ciclo:
    1. Aggiungi 2 all'indirizzo stringa iniziale
    2. Converti i successivi 2 caratteri in stringa in un numero esadecimale
    3. Utilizzare divisione e modulo per 17 ( 0x11) per ottenere il valore più vicino per il componente abbreviato
    4. Uscita senza spazio precedente
  5. Riporta l'interprete in modalità decimale

Spiegazione del codice

: 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 byte

Soluzione:

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

Spiegazione:

Utilizza la stessa strategia di molte di queste risposte (ovvero aggiungi 8, dividi per 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_- la mia idea originale per 54 byte
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.