Warna komplementer

26

Diberikan input warna dalam #rrggbbformat hex, output komplemen RGB-nya dalam format yang sama.

Pelengkap RGB R 2 G 2 B 2 warna apa pun R 1 G 1 B 1 didefinisikan sebagai warna dengan nilai R 2 255 - R 1 , nilai B 2 255 - B 1 , dan nilai G 2 255 - G 1 .

Digit heks dapat berupa huruf besar (# FFAA20) atau huruf kecil (# ffaa20). Kasus input dan output tidak harus konsisten (jadi Anda dapat mengambil input dalam huruf kecil tetapi output dalam huruf besar, dan sebaliknya).

Karena ini adalah , kode terpendek dalam byte akan menang.

Kasing uji (perhatikan bahwa karena memberi program / fungsi keluarannya sendiri harus menghasilkan input asli (tidak disengaja ), kasing uji harus bekerja di kedua arah):

In/Out   Out/In
----------------
#ffffff  #000000
#abcdef  #543210
#badcab  #452354
#133742  #ecc8bd
#a1b2c3  #5e4d3c
#7f7f80  #80807f
Gagang pintu
sumber
2
Maaf, tetapi sRGB tidak berfungsi seperti itu. Anda harus mengonversi ke ruang linear terlebih dahulu, di mana kode hex tidak dimasukkan
John Dvorak
2
@ JanDvorak Oh well. Keadaan tantangan akan mencerminkan ketidaktahuan saya, karena itu, karena saya tidak dapat benar-benar mengubahnya sekarang. : P
Doorknob
Rata-rata dua nilai dalam sRGB bisa menjadi tantangan terpisah yang layak. sRGB = RGB ^ 0,45 pada sebagian besar rentang, tetapi linier di dekat bagian bawah rentang.
John Dvorak

Jawaban:

17

Pyth, 9 8 byte

Terima kasih kepada @isaacg untuk -1 byte!

sXz.HM16

Mengurangkan nilai warna tertentu dari 255 sama dengan mengurangkan setiap digit heksadesimalnya dari 15. Katakan angka 16a + b . Maka nilai angka yang dibuat dengan mengurangi angka-angka dari 15 adalah 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 +

Coba di sini . Suite uji.

lirtosiast
sumber
Jawaban bagus! Saya meminjam ide Anda '0123456789abcdef'untuk mengonversi ke hex (alih-alih dec2hexfungsi)
Luis Mendo
Saya pikir tautan Anda salah. ( Copy-paste FTW. )
PurkkaKoodari
@ Pietu1998 Whoops; Saya akan memperbaikinya.
lirtosiast
Itu Utidak perlu - itu secara implisit diisi oleh M.
isaacg
6

Retina, 13 10 byte

T`w`G-A9-0

Ada tiga bagian kode, dipisahkan oleh backticks ( `): Tmenentukan mode transliterasi, yang menggantikan setiap karakter di bagian kedua dengan karakter yang sesuai di bagian ketiga.

wsama dengan regex tradisional \w, atau _0-9A-Za-z, yang diperluas ke _0123456789ABCDEFGH....

Bagian kedua diperluas GFEDCBA9876543210, berkat kemampuan Retina yang bagus untuk berkembang dalam urutan terbalik. Letakkan ini di atas satu sama lain, dan kita mendapatkan:

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

Perhatikan bahwa karakter terakhir,, 0diulang agar sesuai dengan panjang string yang lebih panjang, tetapi kami hanya peduli dengan karakter heksadesimal, yang ditunjukkan oleh caret.

Terima kasih kepada Martin Büttner karena menyarankan pendekatan ini.

Coba test suite online.

NinjaBearMonkey
sumber
4

Marbelous, 41 byte

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

Penerjemah Online di sini. Masukan harus dalam huruf besar.

Penjelasan

The 00dan ]]di bagian bawah akan mengambil karakter pertama (the #) dan itu akan jatuh ke bawah dan dikeluarkan sebelum yang lain.

3 baris pertama adalah loop untuk mengambil semua karakter yang tersisa.

Pertama-tama kita perlu mengkonversi karakter hex digit ke 0-15, dengan melakukan x -= 48, x -= x > 9 ? 7 : 0(karena 'A' - '9'8).

Untuk menemukan pelengkap, kita cukup mengonversi setiap digit xmenjadi 15-x. Ini setara dengan (untuk nilai 8-bit) (~x)+16 = ~(x-16).

Akhirnya, kita harus mengubah angka-angka ini kembali menjadi digit hex, dengan melakukan x += x > 9 ? 7 : 0, x += 48.

Jadi sekarang sudah x -= 48, x -= x > 9 ? 7 : 0, x = ~(x - 16), x += x > 9 ? 7 : 0, x += 48.

Perhatikan bahwa jika kita menghapus ekspresi dengan operator ternary pertama, maka digit input A- Fakan menghasilkan x negatif setelah negasi.

Jadi kita dapat mengubah ekspresi sebelumnya menjadi:, x -= 48, x -= 16, x = ~x, x += (x > 9 || x < 0) ? 7 : 0, x += 48yang sama dengan x -= 64, x = ~x, x += (x > 9 || x < 0) ? 7 : 0, x += 48.

Kode di atas hanyalah implementasi dari ekspresi terakhir. -Wadalah x -= 32dan +Osekarang x += 24. Karena Marbelous menggunakan aritmatika 8-bit yang tidak ditandatangani, kondisinya <Amencakup kasus x > 9dan x < 0.

es1024
sumber
Apakah Anda membuat Marbelous?
Rɪᴋᴇʀ
@RikerW Marbelous dibuat / disempurnakan oleh beberapa pengguna PPCG termasuk saya: Lihat di sini .
es1024
Baik. Terima kasih telah memberi tahu saya.
Rɪᴋᴇʀ
4

JavaScript ES6, 61 byte 66 68 48 53 64

Menghemat beberapa byte berkat @ Cᴏɴᴏʀ O'Bʀɪᴇɴ, @NinjaBearMonkey, dan @nderscore

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

Mengambil keuntungan dari casting tipe otomatis. Memperbaiki nol membunuh jumlah byte

Downgoat
sumber
Gunakan eval(`0x${s.slice(1)}`)sebagai gantiparseInt
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Panjangnya sama?
PurkkaKoodari
@ CᴏɴᴏʀO'Bʀɪᴇɴ terima kasih, saya menggunakan - alih-alih eval yang menyimpan lebih banyak byte
Downgoat
Oh, lupa tentang casting tipe otomatis: D
Conor O'Brien
Coba dengan inputnya #FFFFFF. Pengembalian #0.
Conor O'Brien
4

JavaScript ES6, 63 58 52 49 byte

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

Terima kasih kepada nderscore untuk menghemat 11 byte!

nicael
sumber
-5 byte:c=>"#"+[...c].map(x=>"fedcba9876543210"[+('0x'+x)]).join``
nderscore
@ lebih tepatnya, sudah dipikirkan :) Terima kasih. Akan menggunakannya, tetapi dengan "eval".
nicael
1
ah, saya punya satu lagi -6:c=>c.replace(/\w/g,x=>"fedcba9876543210"[+('0x'+x)])
nderscore
3

Jolf, 17 byte

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

Coba di sini! , Test suite (Gunakan full run, yang sekarang berfungsi.)

Conor O'Brien
sumber
3

Julia, 74 49 byte

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

Cukup lama saat ini tetapi ini adalah awal. Ini adalah fungsi lambda yang menerima string dan mengembalikan string. Outputnya akan dalam huruf kecil tetapi inputnya bisa dalam baik.

Seperti dicatat Thomas , mengurangi setiap komponen warna 2-digit dari 255 sama dengan mengurangkan masing-masing digit individu dalam input heksadesimal dari 15. Melilit string input, tidak termasuk yang terdepan #, kami mengonversi 15 - digit yang diurai menjadi heksadesimal. Kami bergabung dengan semua ini kemudian #memperbaiki dan menyebutnya bagus.

Alex A.
sumber
3

Japt , 35 32 22 20 16 15 byte

¡Y?(F-XnG)sG :X

Penjelasan:

¡                 //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)
nicael
sumber
Yang bagus! Saya melihat ini tadi malam dan berkata pada diri sendiri, "Besok saya akan membantu untuk menurunkannya." Tetapi sekarang Anda telah bermain golf lebih jauh dari yang saya pikir mungkin. :)
ETHproduk
2

Perl, 30 byte

termasuk +1 untuk -p

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

penggunaan: echo #000000 | perl -p file.pl
atau echo #000000 | perl -pe 's/\w/sprintf"%x",15&~hex$&/eg'.

Kenney
sumber
2

MATL , 21 byte

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

Ini menggunakan rilis 6.0.0 dari bahasa / kompiler, yang lebih awal dari tantangan.

Digit input harus huruf besar.

Contoh

Ini telah dieksekusi pada Oktaf:

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

Edit (12 Juni 2016)

Kode sekarang dapat dicoba secara online . Koma perlu diganti dengan spasi, dan 6Loleh 4L, agar sesuai dengan perubahan dalam bahasa.

Penjelasan

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 '#'
Luis Mendo
sumber
1

Pyth, 20 19 byte

1 byte terima kasih kepada xnor .

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

Cobalah online. Suite uji.

Penjelasan

  • z adalah input
  • tz menghapus #
  • itz16 mem-parsing sebagai angka heksadesimal
  • t^8 8menghitung 8 8 - 1
  • -t^8 8itz16menghitung 8 8 - 1 - input
  • %"#%06x"-t^2 24itz16 memformatnya menjadi string hex 6-karakter nol-empuk dan menambahkan #
PurkkaKoodari
sumber
Bagaimana dengan 8 ^ 8 untuk 2 ^ 24?
xnor
1

Haskell, 85 byte

Kiriman pertama saya, mungkin akan menjadi yang terpanjang (85 byte) tapi hei, Anda harus mulai dari suatu tempat. Dalam Haskell:

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

Ini menggunakan pengurangan yang sama dari 15 trik yang saya lihat orang lain gunakan.

Saya juga mencoba menggunakan printf bersama dengan trik lainnya (kurangi 8 ^ 8 - 1) dan itu berfungsi dalam ghci tetapi karena beberapa alasan ia tidak dapat dikompilasi:

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

Jika seseorang dapat membuat pekerjaan ini, itu akan menjadi hebat!

lpapez
sumber
Selamat datang di Programming Puzzles and Code Golf. Ini adalah jawaban yang sangat bagus (lebih baik daripada yang bisa saya lakukan di Haskell!). Namun, ada format jawaban umum untuk tantangan kode-golf yang memungkinkan snipet Leaderboard memasukkan jawaban Anda di leaderboard. Saya akan mengeditnya untuk Anda; Anda dapat menerima atau menolak suntingan.
wizzwizz4
Untuk membalas komentar pengguna lain, ketik @username.
wizzwizz4
@ wizzwizz4 Terima kasih banyak atas bantuan Anda.
lpapez
Kapan saja! Apakah Anda ingin mencoba beberapa tantangan saya? Analisis kursi Anda dan string Peta ke Hilbert Curve adalah favorit saya, meskipun kurva Hilbert sangat sulit.
wizzwizz4
@ wizzwizz4 Tentu saja, saya akan melihat apa yang bisa saya lakukan.
lpapez
1

Mathematica, 69 60 byte

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

Sekali lagi, ini adalah pemrosesan string yang membunuh saya di sini.

LegionMammal978
sumber
1

C, 94 byte

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;}

Fungsi mengambil dalam array char, mengembalikan nilai terbalik. Menghasilkan huruf besar untuk respons. Kode membalik setiap karakter hex ASCII ke kebalikannya jika valid, abaikan sebaliknya.

Dave P.
sumber
Anda dapat menghemat ruang dengan mendeklarasikan secara global isebelum fungsi:i;
Liam
1

𝔼𝕊𝕄𝕚𝕟 2, 18 karakter / 34 byte

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

Try it here (Firefox only).

Menggunakan versi yang dibuat setelah tantangan.

Penjelasan

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

Solusi non-kompetitif, 15 karakter / 29 byte

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

Menggunakan transliterasi.

Mama Fun Roll
sumber
Bisakah Anda menambahkan versi kompetitif juga, sehingga kita bisa melihat bagaimana bahasa itu disusun?
lirtosiast
Yakin. Lihat hasil edit baru.
Mama Fun Roll
Penggunaan simbol APL dengan baik .
lirtosiast
Hehe, simbol itu yang paling masuk akal /g.
Mama Fun Roll
1

Python, 96

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

Golf kode pertama, tolong beri pendapat :)

Meow Mix
sumber
Anda diizinkan meminta input dalam bentuk "quotes"btw, jadi input()berfungsi. Anda tidak perlu baris baru dan lekukan pada for loop, dan rangeberfungsi dengan baik. Ada juga beberapa ruang yang dapat Anda hapus.
R
int("ff", 16)bisa diganti dengan adil 255.
Gagang Pintu
Apakah Anda memerlukan tanda kurung di dalam tanda kurung setelah setiap x?
Biru
0

CJam, 16 byte

qA,'G,65>+s_W%er

Ini cukup lama karena CJam menangani perubahan basis secara berbeda, jadi lebih pendek untuk hanya melakukan transliterasi. Lihat jawaban Retina saya untuk lebih lanjut tentang transliterasi.

Cobalah online.

Penjelasan

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
NinjaBearMonkey
sumber
0

Python 3, 44 byte

Awalnya saya gunakan 256^3, lalu 16^6. Lalu saya melihat Pietu1998 8^8dan sekarang solusi ini menggunakan itu.

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

Java, 95 90 byte

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

Bitor XOR.

SuperJedi224
sumber
0

Bash + tr, 35 byte

tr 0-9A-Fa-f fedcba9876543210543210

Output selalu huruf kecil.

Sayangnya "tr" tidak mengambil rentang dalam urutan terbalik jadi saya harus mengejanya.

Glenn Randers-Pehrson
sumber
0

C, 147 byte

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);}}

Digunakan strtol untuk mengkonversi dari string hex ke int kemudian kurangi jumlahnya dari 255 untuk mendapatkan pujian seperti kata posting asli. Namun, saya bertanya-tanya apakah ada cara untuk melewatkan serangkaian karakter dari s ke strtol jadi saya tidak perlu membuang banyak byte yang disalin ke string baru?

Danwakeem
sumber
Saya tidak berpikir kompiler biasanya menjalankan pengembalian fungsi dan default ke int, jadi Anda mungkin menghilangkan voidjenis kembali?
Liam
0

R, 62 byte

f=function(a)sprintf('#%06x',(8^8-1)-strtoi(substr(a,2,7),16))
mnel
sumber
0

sed, 48 byte

y/0123456789ABCDEFabcdef/fedcba9876543210543210/

Atau 36 byte jika Anda hanya perlu mendukung satu kasing.

Neil
sumber
Anda tidak perlu mendukung huruf kecil dan besar.
Martin Ender
@ MartinBüttner pertanyaannya tampaknya membutuhkan dukungan untuk kedua kasus dalam input, tetapi tidak dalam output. Seperti solusi bash + tr saya, solusi ini mendukung input tetapi hanya menulis keluaran huruf kecil.
Glenn Randers-Pehrson
Anda memiliki tambahan 0dalam kode Anda, antara 9dan A(jumlah byte benar, harus merupakan kesalahan penyalinan).
hobbs
Pertanyaannya mengatakan Anda dapat memilih kasus input dan output Anda.
lirtosiast
0

PowerShell, 48 byte

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

Diperlukan mengambil input melalui param($a)sebagai string, dibatasi dengan 'atau ", karena C:\Tools\Scripts\Golfing> .\complementary-colors #a1b2c3pada baris perintah PowerShell akan memperlakukan#a1b2c3 sebagai komentar dan mengabaikannya.

Kiri-ke-kanan, "#{0:x6}"-f(...)memformat kalkulasi hasil kami kembali menjadi heksadesimal dengan 6 karakter yang dijamin (untuk memperhitungkan input #ffffff). Di dalam parens, kami mengurangi nomor input kami dari0xffffff . Kami melakukan ini dengan memanfaatkan fakta bahwa PowerShell mem-parsing angka heksadesimal dalam format 0xNNN, jadi kami membangun nomor hex format yang tepat dari nomor input kami $a. (Perhatikan bahwa gabungan plus .Trim()lebih pendek dari .Replace()sini dengan satu byte.) Kami juga memanfaatkan MBoperator unary melalui 16MB-1untuk membangun 16777215bukan 0xffffff.

AdmBorkBork
sumber
0

TeaScript, 24 byte

"#"+S(8**8-1-xS1)t16))x6

Bug di interpreter tidak membuat saya mendapatkan ini lebih pendek :(

Cobalah online

Downgoat
sumber
Downvote penjelasan? Ini bekerja untuk semua test case
Downgoat