Znajdź najbliższy trzycyfrowy kolor szesnastkowy

23

W CSS kolory można określić za pomocą „szesnastkowej tripletu” - trzy bajtowej (sześciocyfrowej) liczby szesnastkowej, gdzie każdy bajt reprezentuje czerwony, zielony lub niebieski składnik koloru. Na przykład #FF0000jest całkowicie czerwony i odpowiada rgb(255, 0, 0).

Kolory mogą być również reprezentowane przez notację skróconą, która wykorzystuje trzy cyfry szesnastkowe. Stenografia rozwija się do postaci sześciocyfrowej poprzez duplikowanie każdej cyfry. Na przykład #ABCstaje się #AABBCC.

Ponieważ w skrócie szesnastkowym jest mniej cyfr, można przedstawić mniej kolorów.

Wyzwanie

Napisz program lub funkcję, która pobiera sześciocyfrowy szesnastkowy kod koloru i wyświetla najbliższy trzycyfrowy kod koloru.

Oto przykład:

  • Wpisz kod szesnastkowy: # 28a086
  • Czerwony składnik
    • 0x28 = 40 (dziesiętny)
    • 0x22 = 34
    • 0x33 = 51
    • 0x22 jest bliżej, więc pierwsza cyfra skróconego kodu koloru to 2
  • Zielony składnik
    • 0xa0 = 160
    • 0x99 = 153
    • 0xaa = 170
    • 0x99 jest bliżej, więc drugą cyfrą jest 9
  • Niebieski składnik
    • 0x86 = 134
    • 0x77 = 119
    • 0x88 = 136
    • 0x88 jest bliżej, więc trzecia cyfra to 8
  • Skrócony kod koloru to # 298 (który rozwija się do # 229988)

Twój program lub funkcja musi przyjmować jako dane wejściowe sześciocyfrowy szesnastkowy kod koloru poprzedzony #i wypisywać trzycyfrowy kod koloru poprzedzony znakiem #.

Przykłady

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

Punktacja

To wyzwanie dla golfa, więc wygrywa najkrótsza odpowiedź w twoim języku! Obowiązują standardowe zasady.

wrymug
źródło
1
„sumując różnicę między każdym składnikiem pełnego kodu koloru a odpowiednim składnikiem skróconego kodu koloru” - ta część jest myląca. Nigdzie nie ma dodawania, prawda?
Grzegorz Oledzki
3
Zauważ, że po prostu upuszczając alternatywne cyfry, każdy krótki kolor reprezentuje taką samą liczbę pełnych kolorów, co można uznać za lepsze przedstawienie niż najbliższy kolor.
Neil
6
Widziałem to w piaskownicy, ale zapomniałem wspomnieć, że nie sądzę, że wymaganie #dodania niczego do wyzwania.
Kudłaty
2
Czy możemy wyświetlać małe litery?
Arnauld
2
0x22 to 34, a nie 30
Kruga

Odpowiedzi:

4

JavaScript (ES6), 55 bajtów

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

Wypróbuj online!

Arnauld
źródło
Niezłe użycie toString! Nie zdawałem sobie sprawy, że to może zająć paramix.
wrymug
8

05AB1E , 13 bajtów

ćs2ôH8+17÷hJ«

Wypróbuj online!

W jaki sposób?

ć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
źródło
1
Myślałem też o zrobieniu odpowiedzi N 05AB1E - chyba że coś przeoczyłem, konwersja szesnastkowa w Galaretce zajmuje sporo bajtów!
Nick Kennedy
1
Tak, nie ma wbudowanej funkcji konwersji tekstowej w Jelly.
Jonathan Allan
1
ćdekapitować ” To inny sposób na opisanie tego, lol. : D Ładna odpowiedź, +1 ode mnie.
Kevin Cruijssen
6

Japt , 16 bajtów

r"%w"²_n16_r17Ãg

Wypróbuj lub uruchom wszystkie przypadki testowe

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
Kudłaty
źródło
5

8088 Montaż, IBM PC DOS, 59 58 bajtów

Niezmontowany wykaz:

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 

Samodzielny plik wykonywalny DOS dla komputera PC. Dane wejściowe są przez wiersz poleceń, dane wyjściowe na konsolę.

Większość długości kodu obsługuje konwersję wymaganych szesnastkowych operacji we / wy na bajty, ponieważ kod maszynowy DOS / x86 nie ma do tego wbudowanych funkcji.

I / O:

wprowadź opis zdjęcia tutaj

Pobierz i przetestuj HEXCLR.COM lub 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
źródło
3

Retina 0.8.2 , 88 bajtów

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

Wypróbuj online! Link zawiera przypadki testowe. Wyjaśnienie:

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

Sparuj cyfry szesnastkowe.

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

Przelicz każdą cyfrę osobno na dziesiętną.

\d+
$*

Konwertuj każdą cyfrę dziesiętną na unarną.

+`1,
,16$*

Zakończ konwersję szesnastkową pary cyfr.

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

Dodaj 8 i podziel przez 17.

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

Konwertuj z powrotem na szesnastkowy.

Neil
źródło
3

Python 3 , 72 70 68 bajtów

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

Wypróbuj online!

To jest fragment oryginalnej odpowiedzi Grzegorza Oledzkisa , która pomogła mu grać w golfa.

Dwie funkcje Python 3 pomagają nam oszczędzać bajty:

  • Domyślnie podział zmiennoprzecinkowy
  • Sformatuj literały łańcuchowe

-2 bajki dzięki dla Jonathana Allana

movatica
źródło
2
(int(x[i:i+2],16)+8)//17saves 2
Jonathan Allan
2

Wolfram Language (Mathematica) , 63 48 bajtów

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

Wypróbuj online!

-15 bajtów dzięki attinat ! Wymiana StringJoinz <>i kompresji składnię.

  1. RGBColor@# konwertuje łańcuch wejściowy na kolor formularza RGBColor[r, g, b] pomocą trzech argumentów zmiennoprzecinkowych z zakresu 0..1.

  2. Round[15 List @@ %]mnoży listę trzech argumentów przez 15 i zaokrągla je do najbliższej liczby całkowitej. Mamy teraz listę trzech wartości całkowitych odpowiadających trzem pożądanym cyfrom szesnastkowym.

  3. %~IntegerString~16 konwertuje tę listę trzech liczb całkowitych na listę trzech ciągów szesnastkowych po jednym znaku.

  4. "#"<>%przygotowuje #postać i łączy wszystkie te postacie razem.

rzymski
źródło
1
48 bajtów
attinat
2

MathGolf , 19 12 bajtów

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

Dane wyjściowe jako lista znaków. Jeśli nie jest to dozwolone, ynależy dodać dodatkowy znak końcowy , aby dołączyć listę znaków do łańcucha.

-7 bajtów dzięki @maxb , ponieważ obejrzałem wbudowane ( 2ô_2<\1>]do 2/).

Wypróbuj online.

Wyjaśnienie:

              # 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
źródło
2

Ruby (2.5.3), 45 , 44 , 42 bajtów

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

EDYCJA: zapisano jeden bajt, ponieważ nie potrzebujemy grupy znaków dla drugiej postaci w wyrażeniu regularnym (zainspirowany odpowiedzią Neila)

EDYCJA 2: zapisano 2 bajty, ponieważ składnia rakiety dash rakieta nie potrzebuje nawiasów wokół argumentu

DaveMongoose
źródło
2
Możesz zapisać 7 bajtów, przyjmując dane wejściowe na stdin i używając -pflagi, a kolejne 2, używając $&zamiast argumentu w bloku: tio.run/##KypNqvz/…
Jordan
1
@Jordan Thanks! Nie wiedziałem o żadnym z nich, więc jest to prawdziwa pomoc dla przyszłych prób gry w golfa
DaveMongoose
1

Python 2 ( 109 101 97 85 83 74 bajty)

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

„Najbliższa odległość” jest obsługiwana przez podzielenie przez 17 i zaokrąglenie.

Ulepszenia:

-8 bajtów przy użyciu int(...+.5)lewy zamiastint(round(...))

-4 bajty przy użyciu zrozumienia listy zamiast map()

-1 bajt przez hardcoding #na wyjściu (dzięki @movatica)

-10 bajtów, nie używając re.findall("..",...)jawnego łączenia ciągów

-2 bajty, nie używając rozumienia listy, ale wbudowane wyrażenie generatora w join(dzięki @movatica)

-1 bajt, nie łącząc :7 zakończenia części niebieskiej

-9 bajtów dzięki lepszej iteracji po kolorach - tj. Iteracji po indeksach, a nie rzeczywistych znakach (dzięki @movatica)

Grzegorz Oledzki
źródło
1
@movatica - masz rację, dodał
Grzegorz Oledzki
1
Zaoszczędź 1 bajt na stałe, '#'zamiast x[0].
movatica
1
Możesz pominąć rozumienie listy wewnątrz ''.join(...), ponieważ obsługuje ona również wyrażenie generatora. Po prostu usuń []i zapisz 2 kolejne bajty :)
movatica
1
Dzięki! range(1,6,2)jest jeszcze lepszy z[1,3,5]
Grzegorz Oledzki
1
Jonathan Allen zaproponował inną sztuczkę zaokrąglania w wersji mz Pzthon3. Dotyczy to również: lambda x:'#'+''.join(hex((int(x[i:i+2],16)+8)/17)[2:]for i in[1,3,5])-> 69 bajtów
movatica
1

Perl 5 -p , 35 34 bajtów

@nwellnhof zapisał bajt

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

Wypróbuj online!

Odczytuje ze STDIN, zastępuje każdą parę elementów, która nie #ma odpowiedniego pojedynczego znaku, stosując metodę dzielenia przez 17 w celu znalezienia najbliższego, a następnie domyślnie wyprowadza ( -p) wynik.

Xcali
źródło
1

Python 3, 67 bajtów

f=lambda x:(f(x[:-2])if x[3:]else"#")+f'{(int(x[-2:],16)+8)//17:X}'
GSy
źródło
Witamy. Zastanów się nad dodaniem opisu, objaśnienia lub linku do tłumacza internetowego, takiego jak TIO, w którym możemy uruchomić Twój kod. Odpowiedzi zawierające tylko kod zwykle są automatycznie oznaczane jako niskiej jakości. Przykłady można znaleźć w innych istniejących odpowiedziach.
mbomb007
0

Czerwony , 103 bajty

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

Wypróbuj online!

Okazało się, że obecna wersja Linuksa Red nie ma implementacji hex-to-rgbfunkcji, dlatego podstawową konwersję wykonuję „ręcznie” :)

Działa to dobrze w czerwonej konsoli GUI w systemie Windows:

Czerwony , 94 bajty

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 Iwanow
źródło
0

Węgiel drzewny , 22 bajty

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

Wypróbuj online! Link jest do pełnej wersji kodu. Wyjaśnienie:

#                       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
źródło
0

Pyth , 20 bajtów

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

Wypróbuj tutaj.

UWAGA: W przypadku gdy powyższy link podnosi ImportError, przejdź tutaj ; obecnie na „oficjalnej” stronie występuje błąd, który jest tymczasowym rozwiązaniem firmy Maltysen . Ten link może przestać działać po naprawieniu oficjalnego.

Erik the Outgolfer
źródło
0

Dalej (gforth) , 87 bajtów

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

Wypróbuj online!

Wyjaśnienie

  1. Zignoruj ​​/ obetnij pierwszy znak input ( #)
  2. Ustaw interpreter na tryb szesnastkowy
  3. Wydajność #
  4. Pętla 3 razy, w każdej pętli:
    1. Dodaj 2 do adresu początkowego ciągu
    2. Konwertuj kolejne 2 znaki w ciągu na liczbę szesnastkową
    3. Użyj dzielenia i modułu przez 17 ( 0x11), aby uzyskać najbliższą wartość dla skróconego komponentu
    4. Wyjście bez poprzedniej spacji
  5. Ustaw interpreter z powrotem w tryb dziesiętny

Wyjaśnienie kodu

: 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
źródło
0

K4 , 39 bajtów

Rozwiązanie:

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

Wyjaśnienie:

Używa tej samej strategii, co wiele z tych odpowiedzi (tj. Dodaj 8, podziel przez 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 "#"

Dodatkowy:

  • "#",{x@*16\:a?&/a:abs(17*!16)-16/:x?y}[.Q.nA]@/:3 2#1_- mój oryginalny pomysł na 54 bajty
Streetster
źródło