Дополнительные цвета


26

Учитывая ввод цвета в #rrggbbшестнадцатеричном формате, выведите его дополнение RGB в том же формате.

Дополнение RGB R 2 G 2 B 2 любого цвета R 1 G 1 B 1 определяется как цвет со значением R 2 255 - R 1 , значением B 2 255 - B 1 и значением G 2 255 - G 1 .

Шестнадцатеричные цифры могут быть прописными (# FFAA20) или строчными (# ffaa20). Случай ввода и вывода не обязательно должен быть согласованным (поэтому вы можете использовать ввод в нижнем регистре, но вывод в верхнем и наоборот).

Поскольку это , выигрывает самый короткий код в байтах.

Тестовые (обратите внимание , что с момента предоставления вашей программы / функционировать свой собственный выход должен привести к первоначальному входу (это инволютивное ), тестовые примеры должны работать в обоих направлениях):

In/Out   Out/In
----------------
#ffffff  #000000
#abcdef  #543210
#badcab  #452354
#133742  #ecc8bd
#a1b2c3  #5e4d3c
#7f7f80  #80807f

2
Извините, но sRGB не работает таким образом. Сначала вы должны преобразовать в линейное пространство, в котором нет шестнадцатеричных кодов.
Джон Дворжак

2
@JanDvorak Ну хорошо. Состояние вызова будет отражать мое невежество, так как я не могу изменить это сейчас. : P
Дверная ручка

Однако усреднение двух значений в sRGB может стать достойной отдельной задачей. sRGB = RGB ^ 0,45 в большей части диапазона, но линейный в нижней части диапазона.
Джон Дворак

Ответы:


17

Pyth, 9 8 байт

Спасибо @isaacg за -1 байт!

sXz.HM16

Вычитание значения определенного цвета из 255 эквивалентно вычитанию каждой из шестнадцатеричных цифр из 15. Скажем, число равно 16a + b . Тогда значение числа, созданного путем вычитания его цифр из 15, равно 16 (15-a) + (15-b) = 255 - (16a + b) .

sXz.HM16     implicit: z=input()
      16      
   .HM        map hex representation over range
   .HM16     '0123456789abcdef'
  z           the input string
 X            Translate characters in x1 present in x2 to reversed x2
              that is, '0' becomes f, '1' becomes 'e', and so on.
              The initial '#' is unchanged.
s             That produced a list, so join into a string by reducing +

Попробуй это здесь . Тестирование.


Хороший ответ! Я позаимствовал вашу идею использовать '0123456789abcdef'для преобразования в гекс (вместо dec2hexфункции)
Луис Мендо

Я думаю, что ваша ссылка неверна. ( Copy-paste FTW. )
PurkkaKoodari

@ Pietu1998 Упс; Я исправлю это.
lirtosiast

Это Uне нужно - оно неявно заполнено M.
Исаак

6

Сетчатка, 13 10 байт

T`w`G-A9-0

Код состоит из трех частей, разделенных backticks ( `): Tуказывает режим транслитерации, который заменяет каждый символ во второй части соответствующим символом в третьей части.

wтакой же, как традиционные регулярные выражения \w, или _0-9A-Za-z, который расширяется до _0123456789ABCDEFGH....

Вторая часть расширена GFEDCBA9876543210, благодаря изящной способности Retina расширяться в обратном порядке. Поместите их друг на друга, и мы получим:

_0123456789ABCDEFGH...
GFEDCBA987654321000...
 ^^^^^^^^^^^^^^^^

Обратите внимание, что последний символ, 0повторяется, чтобы соответствовать длине более длинной строки, но мы заботимся только о шестнадцатеричных символах, показанных символами вставки.

Спасибо Мартину Бюттнеру за предложенный подход.

Попробуйте тестовый набор онлайн.


4

Marbelous, 41 байт

00@0
\\]]\/
-W/\@0
-W
~~
<A+700
+O//]]
+O

Онлайн переводчик здесь. Ввод должен быть в верхнем регистре.

объяснение

00И ]]на дне будет получать первый символ ( #) , и он будет падать на дно и выводиться прежде всего.

Первые 3 строки представляют собой цикл для извлечения всех оставшихся символов.

Сначала мы должны преобразовать шестнадцатеричные символы в 0-15, выполнив x -= 48, x -= x > 9 ? 7 : 0(так как 'A' - '9'это 8).

Чтобы найти дополнение, нам просто нужно преобразовать каждую цифру xв 15-x. Это эквивалентно (для 8-битных значений) (~x)+16 = ~(x-16).

Наконец, мы должны преобразовать эти числа обратно в шестнадцатеричные цифры x += x > 9 ? 7 : 0, x += 48.

Так что теперь у нас есть x -= 48, x -= x > 9 ? 7 : 0, x = ~(x - 16), x += x > 9 ? 7 : 0, x += 48.

Обратите внимание, что если мы удалим выражение с первым троичным оператором, то введенные цифры A- Fприведут к отрицательному x после отрицания.

Таким образом, мы можем изменить предыдущее выражение на:, x -= 48, x -= 16, x = ~x, x += (x > 9 || x < 0) ? 7 : 0, x += 48что равно x -= 64, x = ~x, x += (x > 9 || x < 0) ? 7 : 0, x += 48.

Приведенный выше код является просто реализацией последнего выражения. -Wесть x -= 32и +Oесть x += 24. Поскольку в Marbelous используется 8-разрядная арифметика без знака, условие <Aраспространяется как на случай, так x > 9и на x < 0.


Вы создали Marbelous?
Rɪᴋᴇʀ

@RikerW Marbelous был создан / реализован несколькими пользователями PPCG, включая меня: см. Здесь .
es1024

Хорошо. Спасибо, что дал мне знать.
Rɪᴋᴇʀ

4

JavaScript ES6, 61 байт 66 68 48 53 64

Экономит немало байтов благодаря @ Cᴏɴᴏʀ O'Bʀɪᴇɴ, @NinjaBearMonkey и @nderscore

s=>"#"+(1e5+(8**8+~('0x'+s.slice(1))).toString(16)).slice(-6)

Использует преимущества автоматического набора типов. Исправление нулей убило количество байтов


Используйте eval(`0x${s.slice(1)}`)вместоparseInt
Конор О'Брайен

@ CᴏɴᴏʀO'Bʀɪᴇɴ Это такая же длина?
PurkkaKoodari

@ CᴏɴᴏʀO'Bʀɪᴇɴ спасибо, я использовал - вместо eval, который сохранил еще больше байтов
Downgoat

Ой, забыл про автоматическое приведение типа: D
Конор О'Брайен

Попробуйте это с вводом #FFFFFF. Возвращает #0.
Конор О'Брайен

4

JavaScript ES6, 63 58 52 49 байт

c=>c.replace(/\w/g,x=>(15-`0x${x}`).toString(16))

Спасибо nderscore за сохранение 11 байтов!


-5 байт:c=>"#"+[...c].map(x=>"fedcba9876543210"[+('0x'+x)]).join``
nderscore

@ Точно, уже думал об этом :) Спасибо. Собирался им пользоваться, но с "eval".
nicael

1
ах, у меня есть еще один -6:c=>c.replace(/\w/g,x=>"fedcba9876543210"[+('0x'+x)])
nderscore

3

Джольф, 17 байт

pq#-w^88C Li1~560
pq                pad
         _Li1     the input, w/out the first char
        C    ~5   parsed as a base-16 integer (~5 = 16)
    w^88          8 ^ 8 - 1 (the magic number)
   -              subtract the parsed input from said number
  #               convert result to hexadecimal
               60 pad the result with 6 0's

Попробуй это здесь! , Набор тестов (Использовать полный прогон, который в настоящее время работает.)


3

Юлия, 74 49 байт

h->"#"join([hex(15-parse(Int,i,16))for i=h[2:7]])

Довольно долго на данный момент, но это начало. Это лямбда-функция, которая принимает строку и возвращает строку. Вывод будет в нижнем регистре, но ввод может быть в любом.

Как отметил Томас , вычитание каждого двухзначного цветового компонента из 255 эквивалентно вычитанию каждой отдельной цифры в шестнадцатеричном вводе из 15. Зацикливая входную строку, исключая первую #, мы преобразуем 15 - проанализированный разряд в шестнадцатеричный. Мы присоединяемся ко всем этим, затем придерживаемся #и называем это хорошим.


3

Japt , 35 32 22 20 16 15 байт

¡Y?(F-XnG)sG :X

Объяснение:

¡                 //Take input and map (shortcut to "Um@"). Input should in the form of "#123456"
 Y?               //if Y is not 0, then return (F-XnG)sG, otherwise last step...
    F-XnG           //Subtract X, converted from hexadecimal (G is 16) to decimal, from 15
          sG        //convert decimal to hexadecimal
             :X   //...otherwise return X unchanged (happens only with #, the first char)

Хороший! Я видел это прошлой ночью и сказал себе: «Завтра я помогу сыграть в гольф». Но сейчас вы играете в гольф дальше, чем я думал. :)
ETHproductions

2

Perl, 30 байт

включает +1 для -p

s/\w/sprintf"%x",15&~hex$&/eg

использование: echo #000000 | perl -p file.pl
или echo #000000 | perl -pe 's/\w/sprintf"%x",15&~hex$&/eg'.


2

MATL , 21 байт

35,5Y216,j6L)!16ZA-)h

При этом используется версия 6.0.0 языка / компилятора, которая является более ранней, чем проблема.

Входные цифры должны быть в верхнем регистре.

пример

Это было выполнено в Октаве:

>> matl
 > 35,5Y216,j6L)!16ZA-)h
 >
> #FFAA20
#0055DF

Изменить (12 июня 2016 г.)

Код теперь можно попробовать онлайн . Запятые должны быть заменены пробелами, и 6Lот того 4L, чтобы соответствовать изменениям в языке.

объяснение

35,             % number literal: ASCII code of '#'
5Y2             % '0123456789ABCDEF'
16,             % number literal
j               % input string
6L)             % remove first element
!               % transpose
16ZA            % convert from hex to dec
-               % subtract from 16
)               % index into '0123456789ABCDEF' to convert back to hex
h               % prepend 35, which gets automatically converted into '#'

1

Pyth, 20 19 байтов

1 байт благодаря xnor .

%"#%06x"-t^8 8itz16

Попробуйте онлайн. Тестирование.

объяснение

  • z это вход
  • tz удаляет #
  • itz16 разбирает как шестнадцатеричное число
  • t^8 8рассчитывает 8 8 - 1
  • -t^8 8itz16рассчитывает 8 8 - 1 - вход
  • %"#%06x"-t^2 24itz16 форматирует его в шестнадцатеричную строку, дополненную нулями, и добавляет #

Как насчет 8 ^ 8 для 2 ^ 24?
xnor

1

Haskell, 85 байт

Мое первое представление, оно, вероятно, будет самым длинным (85 байт), но эй, ты должен начать где-нибудь. В Хаскеле:

import Numeric;f=('#':).concatMap((flip showHex)"".(15-).fst.head.readHex.(:[])).tail

Он использует то же самое вычитание из 15 трюков, что и другие люди.

Я также попытался использовать printf вместе с другим трюком (вычесть 8 ^ 8 - 1), и он работает в ghci, но по какой-то причине он не компилируется:

g=printf "#%06x" .(8^8-1-).fst.head.readHex.tail

Если бы кто-то мог сделать эту работу, это было бы здорово!


Добро пожаловать в Программирование головоломок и Code Golf. Это очень хорошие ответы (лучше, чем я мог сделать в Хаскеле!). Тем не менее, существует общий формат ответов для задач по коду-гольфу, который позволяет фрагменту таблицы лидеров поместить ваш ответ в таблицу лидеров. Я отредактирую это для вас; Вы можете принять или отклонить редактирование.
wizzwizz4

Чтобы ответить на комментарии других пользователей, введите @username.
wizzwizz4

@ wizzwizz4 Большое спасибо за вашу помощь.
1

В любой момент! Вы хотите попробовать свои силы? Проанализируйте свой стул и строку «Карта» для кривой Гильберта - мои любимые, хотя кривая Гильберта действительно сложна.
wizzwizz4

@ wizzwizz4 Конечно, я посмотрю, что я могу сделать.
1

1

Mathematica, 69 60 байт

"#"<>IntegerString[8^8-#~StringDrop~1~FromDigits~16-1,16,6]&

Еще раз, это обработка строки, которая убивает меня здесь.


1

C 94 байта

t(char*b){for(int i;i=*b;++b)*b=i>96&i<103?150-i:i>64&i<71|i>47&i<54?118-i:i>53&i<58?111-i:i;}

Функция принимает массив символов, возвращает обратное значение. Производит заглавные буквы для ответа. Код переворачивает каждый шестнадцатеричный символ ASCII в обратный, если он действителен, игнорирует его в противном случае.


Вы можете сэкономить место, объявив iперед функцией глобально :i;
Лиам

1

𝔼𝕊𝕄𝕚𝕟 2, 18 символов / 34 байта

ïē/\w⌿,↪(ḏ-`ᶍ⦃$}”ⓧ

Try it here (Firefox only).

Использование версии, созданной после испытания.

объяснение

ïē/\w⌿,↪(ḏ-`ᶍ⦃$}”ⓧ // implicit: ï=input, ḏ=15
ïē/\w⌿,             // replace all alphanumeric chars in ï with:
       ↪(ḏ-`ᶍ⦃$}”ⓧ // (15 - char's decimal form) converted to hex
                    // implicit output

Неконкурентное решение, 15 символов / 29 байт

ïē/\w⌿,↪(ḏ-`ᶍ⦃$}”ⓧ

Использует транслитерацию.


Можете ли вы также добавить конкурентоспособную версию, чтобы мы могли видеть, как складывается язык?
lirtosiast

Конечно. Смотрите новое редактирование.
Mama Fun Roll

Хорошее использование символа APL .
lirtosiast

Хе-хе, этот символ был тем, который имел больше всего смысла /g.
Мама Fun Roll

1

Питон, 96

x=input()
print("#")
for i in range(3):
    print(hex(255-int(x[(1+2*i)]+x[(2+2*i)],16))[2:4])

Первый код гольф, пожалуйста, дайте мнение :)


Вам разрешено требовать ввода быть "quotes"кстати, так что input()работает. Вам не нужны перевод строки и отступ в цикле for, и он rangeработает просто отлично. Есть также пара пробелов, которые вы можете удалить.
Rɪᴋᴇʀ

int("ff", 16)можно заменить просто 255.
Дверная ручка

Вам нужны скобки внутри скобок после каждого х?
Blue

0

CJam, 16 байтов

qA,'G,65>+s_W%er

Это довольно долго, потому что CJam обрабатывает базовые изменения по-разному, поэтому было проще сделать транслитерацию. Смотрите мой ответ Retina для получения дополнительной информации о транслитерации.

Попробуйте онлайн.

объяснение

q      e# Get the input
A,     e# Push [0 1 ... 8 9]
'G,65> e# Push "ABCDEF"
+s     e# Combine and convert to string
_W%    e# Make a copy and reverse it
er     e# Replace each character in the first string with
       e# the corresponding character in the second

0

Python 3, 44 байта

Первоначально я использовал 256^3тогда 16^6. Тогда я видел Pietu1998, 8^8и теперь это решение использует это вместо.

"#{:06x}".format(8**8-1-int(input()[1:],16))

0

Ява, 95 90 байт

String f(String v){return v.format("#%06x",0xFFFFFF^Integer.parseInt(v.substring(1),16));}

Побитовый XOR.


0

Баш + тр, 35 байт

tr 0-9A-Fa-f fedcba9876543210543210

Вывод всегда в нижнем регистре.

К сожалению, tr не принимает диапазоны в обратном порядке, поэтому мне пришлось их прописать.


0

C, 147 байтов

void p(char s[]){char c[3];int i=1;printf("#");while(i<6){strncpy(c,s+i++,2);i++;int x=255-strtol(c,NULL,16);x<10?printf("0%x",x):printf("%x",x);}}

Использовал strtol для преобразования из шестнадцатеричной строки в int, затем вычел число из 255, чтобы получить комплимент, как в оригинальном сообщении. Мне, однако, интересно, есть ли способ передать диапазон символов из s в strtol, чтобы мне не пришлось тратить кучу байтов, копируя в новую строку?


Я не думаю, что компиляторы обычно принудительно возвращают функции и по умолчанию имеют значение int, так что вы, вероятно, не указали voidтип возвращаемого значения?
Лиам


0

sed, 48 байтов

y/0123456789ABCDEFabcdef/fedcba9876543210543210/

Или 36 байтов, если вам нужно только поддержать один случай.


Вам не нужно поддерживать как строчные, так и прописные буквы.
Мартин Эндер

@ MartinBüttner вопрос, кажется, требует поддержки обоих случаев на входе, но не на выходе. Как и мое решение bash + tr, это решение поддерживает как ввод, так и запись только в нижнем регистре.
Гленн Рандерс-Персон

У вас есть дополнительный 0код в коде между 9и A(хотя число байтов верное, должно быть ошибка копирования).
Хоббс

Вопрос говорит, что вы можете выбрать, в каком случае ваш вход и выход.
lirtosiast

0

PowerShell, 48 байт

param($a)"#{0:x6}"-f(16MB-1-("0x"+$a.Trim('#')))

Обязательно принимает входные данные param($a)в виде строки, разделенной символом 'или ", поскольку C:\Tools\Scripts\Golfing> .\complementary-colors #a1b2c3в командной строке PowerShell будет обрабатываться #a1b2c3как комментарий и в целом игнорировать его.

Слева направо "#{0:x6}"-f(...)форматирует наши выходные вычисления обратно в шестнадцатеричное с гарантированными 6 символами (для учета ввода #ffffff). Внутри скобок мы вычитаем наш входной номер из 0xffffff. Мы делаем это, используя тот факт, что PowerShell анализирует шестнадцатеричные числа в формате 0xNNN, поэтому мы строим шестнадцатеричное число правильного формата из нашего входного числа $a. (Обратите внимание, что конкатенация плюс .Trim()короче, чем .Replace()здесь, на один байт.) Мы также используем MBунарный оператор через 16MB-1конструкцию 16777215вместо 0xffffff.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.