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.