Finden Sie die nächstgelegene dreistellige Hex-Farbe


23

In CSS können Farben durch ein "Hexadezimaltripel" angegeben werden - eine hexadezimale Zahl mit drei Bytes (sechs Stellen), wobei jedes Byte die roten, grünen oder blauen Komponenten der Farbe darstellt. Zum Beispiel #FF0000ist komplett rot und entspricht rgb(255, 0, 0).

Farben können auch durch die Kurzschreibweise dargestellt werden, die drei hexadezimale Ziffern verwendet. Die Kurzschrift wird durch Duplizieren jeder Ziffer zur sechsstelligen Form erweitert. Zum Beispiel #ABCwird #AABBCC.

Da die hexadezimale Kurzschrift weniger Ziffern enthält, können weniger Farben dargestellt werden.

Die Herausforderung

Schreiben Sie ein Programm oder eine Funktion, die einen sechsstelligen hexadezimalen Farbcode verwendet und den nächsten dreistelligen Farbcode ausgibt.

Hier ist ein Beispiel:

  • Hex-Code eingeben: # 28a086
  • Rote Komponente
    • 0x28 = 40 (dezimal)
    • 0x22 = 34
    • 0x33 = 51
    • 0x22 ist näher, daher ist die erste Ziffer des verkürzten Farbcodes 2
  • Grüne Komponente
    • 0xa0 = 160
    • 0x99 = 153
    • 0xaa = 170
    • 0x99 ist näher, also ist die zweite Ziffer 9
  • Blaue Komponente
    • 0x86 = 134
    • 0x77 = 119
    • 0x88 = 136
    • 0x88 ist näher, also ist die dritte Ziffer 8
  • Der verkürzte Farbcode lautet # 298 (erweitert auf # 229988).

Ihr Programm oder Ihre Funktion muss einen sechsstelligen hexadezimalen Farbcode als Eingabe akzeptieren und einen dreistelligen Farbcode als Eingabe #ausgeben# .

Beispiele

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

Wertung

Dies ist eine Code-Golf-Herausforderung, daher gewinnt die kürzeste Antwort in Ihrer Sprache! Es gelten Standardregeln.


1
"Addieren der Differenz zwischen jeder Komponente des Vollfarbcodes und der entsprechenden Komponente des Kurzfarbcodes" - dieser Teil ist verwirrend. Es gibt nirgendwo etwas hinzuzufügen, oder?
Grzegorz Oledzki

3
Beachten Sie, dass, wenn Sie einfach alternative Ziffern löschen, jede kurze Farbe eine gleiche Anzahl von Vollfarben darstellt, sodass eine bessere Darstellung als die nächste Farbe in Betracht gezogen werden kann.
Neil

6
Ich habe das in der Sandbox gesehen, habe aber vergessen zu erwähnen, dass ich nicht denke, dass ich das benötige # zusätzlichen Herausforderungen gibt.
Shaggy

2
Dürfen wir in Kleinbuchstaben ausgeben?
Arnauld

2
0x22 ist 34, nicht 30
Kruga

Antworten:



8

05AB1E , 13 Bytes

ćs2ôH8+17÷hJ«

Probieren Sie es online!

Wie?

ć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
Ich dachte auch darüber nach, N 05AB1E zu beantworten - es sei denn, ich habe etwas verpasst, dauert die hexadezimale Konvertierung in Jelly ziemlich viele Bytes!
Nick Kennedy

1
Ja, in Jelly ist keine Textkonvertierung integriert.
Jonathan Allan

1
" ćdekapitieren " Das ist eine andere Art, es zu beschreiben, lol. : D Schöne Antwort, +1 von mir.
Kevin Cruijssen

6

Japt , 16 Bytes

r"%w"²_n16_r17Ãg

Probieren Sie es aus oder führen Sie alle Testfälle aus

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 Bytes

Zerlegte Auflistung:

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 

Standalone-PC-DOS-Programm. Die Eingabe erfolgt über die Befehlszeile, die Ausgabe erfolgt an die Konsole.

Der größte Teil der Codelänge übernimmt die Konvertierung der erforderlichen hexadezimalen Zeichenfolgen-E / A in Bytes, da der DOS / x86-Computercode hierfür keine integrierten Funktionen enthält.

I / O:

Bildbeschreibung hier eingeben

Laden und testen Sie HEXCLR.COM oder 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 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|;

Probieren Sie es online! Link enthält Testfälle. Erläuterung:

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

Koppeln Sie die Hex-Ziffern.

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

Wandle jede Ziffer einzeln in eine Dezimalzahl um.

\d+
$*

Wandle jede Dezimalstelle in eine unäre um.

+`1,
,16$*

Beenden Sie die hexadezimale Konvertierung des Ziffernpaares.

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

Addiere 8 und dividiere durch 17.

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

Zurück in hexadezimal konvertieren.






2

Wolfram Language (Mathematica) , 63 48 Bytes

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

Probieren Sie es online!

-15 bytes dank attinat ! Ersetzen StringJoinmit <>und Komprimieren der Syntax.

  1. RGBColor@#konvertiert die Eingabezeichenfolge in eine Farbe des Formulars RGBColor[r, g, b]mit drei Gleitkommaargumenten im Bereich 0..1.

  2. Round[15 List @@ %]multipliziert die Liste der drei Argumente mit 15 und rundet sie auf die nächste Ganzzahl. Wir haben jetzt eine Liste mit drei Ganzzahlwerten, die den drei gewünschten hexadezimalen Ziffern entsprechen.

  3. %~IntegerString~16 konvertiert diese Liste mit drei ganzen Zahlen in eine Liste mit drei hexadezimalen Zeichenfolgen mit jeweils einem Zeichen.

  4. "#"<>%Stellt ein #Zeichen voran und fügt alle diese Zeichen zusammen.



2

MathGolf , 19 12 Bytes

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

Ausgabe als Zeichenliste. Wenn dies nicht zulässig ist, muss ein zusätzliches Trailing yhinzugefügt werden, um die Zeichenliste mit einer Zeichenfolge zu verknüpfen.

-7 Bytes dank @maxb , da ich an einem Builtin ( 2ô_2<\1>]to 2/) vorbei geschaut habe .

Probieren Sie es online aus.

Erläuterung:

              # 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

Ruby (2.5.3), 45 , 44 , 42 Bytes

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

BEARBEITEN: ein Byte gespeichert, da wir keine Zeichengruppe für das zweite Zeichen im Regex benötigen (inspiriert von Neils Antwort)

BEARBEITEN 2: 2 Bytes gespart, da die Lambda-Syntax der Bindestrichrakete keine Klammern um das Argument benötigt


2
Sie können 7 Bytes einsparen, indem Sie stdin eingeben und das -pFlag und 2 weitere Bytes verwenden, indem Sie $&anstelle eines Arguments im Block Folgendes verwenden
Jordan

1
@ Jordan Danke! Ich wusste nichts davon und das ist eine echte Hilfe für zukünftige
Golfversuche

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

Die "nächste Distanz" wird durch Division durch 17 und Rundung behandelt.

Verbesserungen:

-8 Bytes mit dem int(...+.5) Trick stattint(round(...))

-4 Bytes unter Verwendung des Listenverständnisses anstelle von map()

-1 Byte durch Hardcodierung # in der ausgabe (danke @movatica)

-10 Bytes, indem Sie nicht verwenden re.findall("..",...) expliziter String-Spleiß verwendet wird

-2 Bytes, indem kein Listenverständnis verwendet wird, sondern ein Ausdruck des Inline-Generators in join(danke @movatica)

-1 Byte, indem die :7Endung für den blauen Teil nicht gespleißt wird

-9 Bytes durch bessere Iteration über Farben - dh Iteration über Indizes, nicht über tatsächliche Zeichen (danke @movatica)


1
@movatica - Sie haben Recht, fügte es hinzu
Grzegorz Oledzki

1
Sparen Sie 1 Byte durch Hardcoding '#'statt x[0].
Movatica

1
Sie können das Listenverständnis darin überspringen ''.join(...), da es auch einen Generatorausdruck behandelt. Entfernen Sie einfach die []und speichern Sie 2 weitere Bytes :)
Movatica

1
Vielen Dank! range(1,6,2)ist noch besser mit[1,3,5]
Grzegorz Oledzki

1
Jonathan Allen schlug einen anderen Trick zum Runden in der mz Pzthon3-Version vor. lambda x:'#'+''.join(hex((int(x[i:i+2],16)+8)/17)[2:]for i in[1,3,5])
Dies

1

Perl 5 -p , 35 34 Bytes

@nwellnhof hat ein Byte gespeichert

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

Probieren Sie es online!

Liest aus STDIN, ersetzt jedes Elementpaar, das nicht #mit dem entsprechenden Einzelzeichen versehen ist, und verwendet die Methode zum Ermitteln der nächsten Division durch 17. Anschließend wird implizit -pdas Ergebnis ausgegeben ( ).


1

Python 3, 67 Bytes

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

Herzlich willkommen. Erwägen Sie, eine Beschreibung, Erklärung oder einen Link zu einem Online-Interpreter wie TIO hinzuzufügen, über den wir Ihren Code ausführen können. Nur-Code-Antworten werden in der Regel automatisch als minderwertig gekennzeichnet. Beispiele finden Sie in anderen vorhandenen Antworten.
mbomb007

0

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

Probieren Sie es online!

Es stellte sich heraus, dass die aktuelle Linux-Version von Red keine Implementierung der hex-to-rgbFunktion hat, deshalb mache ich die Basiskonvertierung "manuell" :)

Dies funktioniert problemlos in der Red GUI-Konsole unter Windows:

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


0

Holzkohle , 22 Bytes

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

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Erläuterung:

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

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

Probieren Sie es hier aus.

HINWEIS: Wenn der obige Link einen auslöst ImportError, klicken Sie stattdessen hier . Es gibt derzeit einen Fehler auf der "offiziellen" Seite, und dies ist eine vorübergehende Lösung von Maltysen . Dieser Link funktioniert möglicherweise nicht mehr, nachdem der offizielle behoben wurde.


0

Viertens (gviertens) , 87 Bytes

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

Probieren Sie es online!

Erläuterung

  1. Erstes Zeichen der Eingabe ignorieren / abschneiden ( #)
  2. Stellen Sie den Interpreter auf den Hexadezimalmodus ein
  3. Ausgabe #
  4. Dreimal in jeder Schleife wiederholen:
    1. Addiere 2 zur Anfangsadresse der Zeichenkette
    2. Konvertieren Sie die nächsten 2 Zeichen in einer Zeichenfolge in eine Hexadezimalzahl
    3. Verwenden Sie Division und Modul durch 17 (0x11 ), um den nächstgelegenen Wert für die verkürzte Komponente zu erhalten
    4. Ausgabe ohne vorangestelltes Leerzeichen
  5. Stellen Sie den Interpreter wieder auf den Dezimalmodus ein

Code-Erklärung

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

Lösung:

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

Erläuterung:

Verwendet dieselbe Strategie wie viele dieser Antworten (dh addiere 8, dividiere durch 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_- meine ursprüngliche Idee für 54 Bytes
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.