Знайдіть найближчий трицифровий шістнадцятковий колір


23

У CSS кольори можуть бути визначені «шістнадцятковим триплетом» - трибайтовим (шестизначним) шістнадцятковим числом, де кожен байт представляє червоний, зелений або синій компоненти кольору. Наприклад, #FF0000повністю червоний і еквівалентний rgb(255, 0, 0).

Кольори також можуть бути представлені скороченням, що використовує три шістнадцяткові цифри. Скорочення розгортається до шестизначної форми шляхом дублювання кожної цифри. Наприклад, #ABCстає #AABBCC.

Оскільки в шістнадцятковій стенограмі менше цифр, можна зобразити менше кольорів.

Змагання

Напишіть програму або функцію, яка приймає шестизначний шістнадцятковий кольоровий код і виводить найближчий трицифровий колірний код.

Ось приклад:

  • Шістнадцятковий код: # 28a086
  • Червоний компонент
    • 0x28 = 40 (десятковий)
    • 0x22 = 34
    • 0x33 = 51
    • 0x22 ближче, тому перша цифра укороченого кольорового коду дорівнює 2
  • Зелений компонент
    • 0xa0 = 160
    • 0x99 = 153
    • 0xaa = 170
    • 0x99 ближче, тому друга цифра дорівнює 9
  • Синій компонент
    • 0x86 = 134
    • 0x77 = 119
    • 0x88 = 136
    • 0x88 ближче, тому третя цифра дорівнює 8
  • Скорочений код кольору - №298 (який розширюється до # 229988)

Ваша програма чи функція повинні сприймати як введення шість-значний шістнадцятковий код кольору, заздалегідь #створений і виводити тризначний кольоровий код, заздалегідь передбачений #.

Приклади

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

Оцінка балів

Це виклик з гольф-кодом, тому найкоротша відповідь на вашій мові виграє! Діють стандартні правила.


1
"додавання різниці між кожним компонентом повнокольорового коду та відповідним компонентом короткого коду кольору" - ця частина заплутана. Ніде не додається, правда?
Гжегож Оледзкі

3
Зауважте, що якщо ви просто скидаєте альтернативні цифри, то кожен короткий колір являє собою рівну кількість повних кольорів, так що можна вважати кращим представлення, ніж найближчий колір.
Ніл

6
Побачила це в пісочниці, але забула згадати, що я не думаю, що вимагає #додати щось до виклику.
Кудлатий

2
Чи можемо ми вивести малі літери?
Арнольд

2
0х22 - 34, а не 30
Круга

Відповіді:



8

05AB1E , 13 байт

ćs2ôH8+17÷hJ«

Спробуйте в Інтернеті!

Як?

ć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
Я думав над тим, щоб зробити відповідь N 05AB1E - якщо я щось не пропустив, шістнадцяткова конверсія в Jelly займає досить багато байтів!
Нік Кеннеді

1
Так, ніякого вбудованого для будь-яких текстових базових перетворень в Jelly.
Джонатан Аллан

1
" ćобезголовлення " Це ще один спосіб описати це, хаха. : D Хоча приємна відповідь, +1 від мене.
Кевін Круїссен


5

8088 Асамблея, IBM PC DOS, 59 58 байт

Нерозбірний список:

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 

Автономний виконуваний ПК DOS. Введення здійснюється за допомогою командного рядка, вихід - для консолі.

Більшість довжини коду обробляють перетворення необхідного шістнадцяткового рядка вводу-виводу в байти, оскільки машинний код DOS / x86 не має вбудованих для цього.

I / O:

введіть тут опис зображення

Завантажте та протестуйте HEXCLR.COM або 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

Сітківка 0,8,2 , 88 байт

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

Спробуйте в Інтернеті! Посилання включає тестові випадки. Пояснення:

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

Пару шістнадцяткових цифр.

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

Перетворіть кожну цифру окремо в десяткову.

\d+
$*

Перетворіть кожну десяткову цифру в одинакову.

+`1,
,16$*

Закінчіть шістнадцяткове перетворення пари цифр.

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

Додайте 8 і розділіть на 17.

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

Перетворити назад у шістнадцятковий.



3

Python 3 , 72 70 68 байт

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

Спробуйте в Інтернеті!

Це оригінальна відповідь порту Гжегожа Оледзкіса , який я допоміг йому покататися.

Дві функції Python 3 допомагають нам зберігати байти:

  • Ділення з плаваючою комою за замовчуванням
  • Форматування рядкових літералів

-2 байти більше ніж Джонатану Аллану


2
(int(x[i:i+2],16)+8)//17рятує 2
Джонатан Аллан



2

Мова Вольфрама (Mathematica) , 63 48 байт

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

Спробуйте в Інтернеті!

-15 байт завдяки attinat ! Заміна StringJoinз <>і стиснення синтаксису.

  1. RGBColor@#перетворює вхідний рядок у колір форми RGBColor[r, g, b]з трьома аргументами з плаваючою комою в діапазоні 0..1.

  2. Round[15 List @@ %]множить список трьох аргументів на 15 і округляє їх до найближчого цілого числа. Тепер у нас є список трьох цілих значень, що відповідають трьом бажаним шістнадцятковим цифрам.

  3. %~IntegerString~16 перетворює цей список з трьох цілих чисел у список трьох шістнадцяткових рядків по одному символу кожен.

  4. "#"<>%претендує на #персонаж і приєднується до всіх цих символів разом.



2

MathGolf , 19 12 байт

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

Виведіть як список символів. Якщо це не дозволено, yдля приєднання списку символів до рядка потрібно додати додатковий трейлінг .

-7 байт завдяки @maxb , оскільки я подивився повз вбудований ( 2ô_2<\1>]до 2/).

Спробуйте в Інтернеті.

Пояснення:

              # 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 байти

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

EDIT: збережений один байт, оскільки нам не потрібна група символів для другого символу в регулярному виразі (натхненна відповіддю Ніла)

EDIT 2: збережено 2 байти, оскільки синтаксис лямбда-ракети "тире" не потребує дужок навколо аргументу


2
Ви можете зберегти 7 байт, скориставшись вводом stdin та використовуючи -pпрапор та ще 2, використовуючи $&замість аргументу всередині блоку: tio.run/##KypNqvz/…
Jordan

1
@Jordan Дякую! Я не знав про жодне з цих, тому це справжня допомога для майбутніх спроб гольфу
DaveMongoose

1

Пітон 2 ( 109 101 97 85 83 74 байт)

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

"Найближча відстань" обробляється діленням на 17 та округленням.

Покращення:

-8 байт, використовуючи int(...+.5)трюк замістьint(round(...))

-4 байти, використовуючи розуміння списку замість map()

-1 байт жорстким кодуванням # у виході (спасибі @movatica)

-10 байт, не використовуючи re.findall("..",...) на користь явного строкового сплайсингу

-2 байти, не використовуючи розуміння списку, а вираження генератора вбудованого в join (спасибі @movatica)

-1 байт, не зрощуючи :7 закінчення для синьої частини

-9 байт шляхом кращої ітерації кольорів - тобто повторення над індексами, а не фактичними символами (спасибі @movatica)


1
@movatica - ти маєш рацію, додав
Grzegorz Oledzki

1
Збережіть 1 байт шляхом жорсткого кодування '#'замість x[0].
movatica

1
Ви можете пропустити розуміння списку всередині ''.join(...), оскільки він також обробляє вираз генератора. Просто видаліть []і збережіть ще 2 байти :)
movatica

1
Спасибі! range(1,6,2)ще краще з[1,3,5]
Grzegorz Oledzki

1
Джонатан Аллен запропонував інший трюк для округлення у mz Pzthon3 версії. Тут також застосовується: lambda x:'#'+''.join(hex((int(x[i:i+2],16)+8)/17)[2:]for i in[1,3,5])-> 69 байт
movatica

1

Perl 5 -p , 35 34 байти

@nwellnhof врятував байт

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

Спробуйте в Інтернеті!

Читає з STDIN, замінює кожну пару елементів, які не #мають відповідного одного символу, використовуючи метод поділу на 17 для пошуку найближчого, а потім неявно видає ( -p) результат.


1

Python 3, 67 байт

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

Ласкаво просимо. Спробуйте додати опис, пояснення чи посилання до онлайн-перекладача, наприклад, TIO, де ми можемо запустити ваш код. Відповіді, що стосуються лише коду, зазвичай автоматично позначаються як низькоякісні. Дивіться інші відповіді на приклади.
mbomb007

0

Червоний , 103 байти

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

Спробуйте в Інтернеті!

Виявилося, що в поточній версії Linux Red немає hex-to-rgbфункції реалізації, тому я роблю базове перетворення "вручну" :)

Це чудово працює на консолі Red GUI у Windows:

Червоний , 94 байти

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

Вугілля деревне , 22 байти

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

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Пояснення:

#                       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 байт

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

Спробуйте тут.

ПРИМІТКА. Якщо вище посилання піднімається ImportError, перейдіть сюди ; на даний момент помилка на "офіційній" сторінці, і це тимчасове рішення Малтісен . Це посилання може припинити роботу після виправлення офіційного.


0

Четвертий (gforth) , 87 байт

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

Спробуйте в Інтернеті!

Пояснення

  1. Ігнорувати / скорочувати перший символ введення ( #)
  2. Встановіть перекладача в шістнадцятковий режим
  3. Вихід #
  4. Петля 3 рази, в кожній петлі:
    1. Додайте 2 до початкової адреси рядка
    2. Перетворіть наступні два символи в рядку в шістнадцяткове число
    3. Використовуйте поділ і модуль на 17 ( 0x11), щоб отримати найближче значення для скороченого компонента
    4. Вихід без попереднього місця
  5. Поверніть перекладач до десяткового режиму

Пояснення коду

: 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

К4 , 39 байт

Рішення:

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

Пояснення:

Використовується та ж стратегія, як і багато з цих відповідей (тобто додайте 8, розділіть на 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 "#"

Додатково:

  • "#",{x@*16\:a?&/a:abs(17*!16)-16/:x?y}[.Q.nA]@/:3 2#1_- моя оригінальна ідея на 54 байти
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.