Найти ближайший трехзначный шестнадцатеричный цвет


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
0x22 - это 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 Assembly, 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

Wolfram Language (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

Рубин (2.5.3), 45 , 44 , 42 байта

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

РЕДАКТИРОВАТЬ: сохранил один байт, потому что нам не нужна группа символов для второго символа в регулярном выражении (вдохновленный ответом Нила)

РЕДАКТИРОВАТЬ 2: сохранил 2 байта, потому что синтаксис лямбда-тире ракеты не требует скобок вокруг аргумента


2
Вы можете сэкономить 7 байтов, взяв ввод в stdin и используя -pфлаг и еще 2, используя $&вместо аргумента внутри блока: tio.run/##KypNqvz/…
— Джордан,

1
@ Джордан Спасибо! Я не знал ни об одном из них, так что это реальная помощь для будущих попыток игры в гольф
— DaveMongoose

1

Python 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 - ты прав, добавил это
— Гжегож Оледзки

1
Сохраните 1 байт путем жесткого кодирования '#'вместо x[0].
— Моватика

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

1
Благодарность! range(1,6,2)еще лучше с[1,3,5]
— Гжегож 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, перейдите сюда ; в настоящее время есть ошибка на официальной странице, и это временное решение от Maltysen . Эта ссылка может перестать работать после исправления официальной.


0

Forth (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. Преобразуйте следующие 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.