Temukan warna hex tiga digit terdekat

23

Dalam CSS, warna dapat ditentukan oleh "hex triplet" - angka heksadesimal tiga byte (enam digit) di mana setiap byte mewakili komponen warna merah, hijau, atau biru. Misalnya, #FF0000sepenuhnya merah, dan setara dengan rgb(255, 0, 0).

Warna juga dapat diwakili oleh notasi steno yang menggunakan tiga digit heksadesimal. Singkatan berkembang ke bentuk enam digit dengan menduplikasi setiap digit. Misalnya, #ABCmenjadi #AABBCC.

Karena ada lebih sedikit digit dalam hex steno, lebih sedikit warna yang dapat diwakili.

Tantangan

Tulis program atau fungsi yang menggunakan kode warna heksadesimal enam digit dan berikan kode warna tiga digit terdekat.

Ini sebuah contoh:

  • Masukkan kode hex: # 28a086
  • Komponen merah
    • 0x28 = 40 (desimal)
    • 0x22 = 34
    • 0x33 = 51
    • 0x22 lebih dekat, jadi digit pertama dari kode warna yang dipersingkat adalah 2
  • Komponen hijau
    • 0xa0 = 160
    • 0x99 = 153
    • 0xaa = 170
    • 0x99 lebih dekat, jadi digit kedua adalah 9
  • Komponen biru
    • 0x86 = 134
    • 0x77 = 119
    • 0x88 = 136
    • 0x88 lebih dekat, jadi digit ketiga adalah 8
  • Kode warna yang diperpendek adalah # 298 (yang diperluas ke # 229988)

Program atau fungsi Anda harus menerima sebagai input kode warna heksadesimal enam digit yang diawali dengan #dan menghasilkan kode warna tiga digit yang diawali dengan #.

Contohnya

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

Mencetak gol

Ini adalah tantangan kode-golf, jadi jawaban tersingkat dalam bahasa Anda menang! Aturan standar berlaku.

tukang sihir
sumber
1
"menambahkan bersama perbedaan antara setiap komponen kode warna penuh dan komponen yang sesuai dari kode warna steno" - bagian ini membingungkan. Tidak ada penambahan di mana pun, bukan?
Grzegorz Oledzki
3
Perhatikan bahwa jika Anda cukup menjatuhkan digit alternatif maka setiap warna pendek mewakili jumlah warna penuh yang sama, sehingga dapat dianggap membuat representasi yang lebih baik daripada warna terdekat.
Neil
6
Melihat ini di Sandbox tetapi lupa menyebutkan bahwa saya tidak berpikir perlu #menambahkan apa pun untuk tantangan.
Shaggy
2
Bisakah kita mengeluarkan huruf kecil?
Arnauld
2
0x22 adalah 34, bukan 30
Kruga

Jawaban:

4

JavaScript (ES6), 55 byte

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

Cobalah online!

Arnauld
sumber
Penggunaan toString yang bagus! Saya tidak menyadari itu bisa mengambil param radix.
wrymug
8

05AB1E , 13 byte

ćs2ôH8+17÷hJ«

Cobalah online!

Bagaimana?

ć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
sumber
1
Saya berpikir untuk melakukan jawaban N 05AB1E juga - kecuali saya melewatkan sesuatu, konversi heksadesimal di Jelly membutuhkan banyak byte!
Nick Kennedy
1
Ya, tidak ada bawaan untuk konversi basis teks di Jelly.
Jonathan Allan
1
" ćmemenggal kepala " Itu cara lain untuk menggambarkannya, lol. : D Jawaban yang bagus, +1 dari saya.
Kevin Cruijssen
6

Japt , 16 byte

r"%w"²_n16_r17Ãg

Cobalah atau jalankan semua test case

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
Shaggy
sumber
5

8088 Majelis, IBM PC DOS, 59 58 byte

Daftar belum dirakit:

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 

Standalone PC DOS dapat dieksekusi. Input melalui baris perintah, output ke konsol.

Sebagian besar panjang kode menangani konversi hex string I / O yang diperlukan menjadi byte, karena kode mesin DOS / x86 tidak memiliki bawaan untuk itu.

I / O:

masukkan deskripsi gambar di sini

Unduh dan uji HEXCLR.COM , atau 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..
640KB
sumber
3

Retina 0.8.2 , 88 byte

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

Cobalah online! Tautan termasuk kasus uji. Penjelasan:

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

Pasangkan digit hex.

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

Ubah setiap digit secara terpisah menjadi desimal.

\d+
$*

Konversi setiap angka desimal ke unary.

+`1,
,16$*

Selesaikan konversi heksadesimal dari pasangan digit.

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

Tambahkan 8 dan bagi dengan 17.

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

Konversi kembali ke heksadesimal.

Neil
sumber
3

Python 3 , 72 70 68 byte

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

Cobalah online!

Ini adalah port jawaban asli Grzegorz Oledzkis , yang saya bantu dia main golf.

Dua fitur Python 3 membantu kami menghemat byte:

  • Pembagian titik mengambang secara default
  • Memformat string literal

-2 byte thanx ke Jonathan Allan

movatica
sumber
2
(int(x[i:i+2],16)+8)//17hemat 2
Jonathan Allan
3

Jelly , 20 19 byte

ḊØHiⱮs2ḅ⁴+8:17ịØHṭḢ

Cobalah online!

Nick Kennedy
sumber
2

Bahasa Wolfram (Mathematica) , 63 48 byte

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

Cobalah online!

-15 byte terima kasih untuk attinat ! Mengganti StringJoindengan <>dan mengompresi sintaks.

  1. RGBColor@#mengonversi string input ke warna formulir RGBColor[r, g, b]dengan tiga argumen titik apung di kisaran 0..1.

  2. Round[15 List @@ %]mengalikan daftar tiga argumen dengan 15 dan membulatkannya ke bilangan bulat terdekat. Kami sekarang memiliki daftar tiga nilai integer yang sesuai dengan tiga digit heksadesimal yang diinginkan.

  3. %~IntegerString~16 mengubah daftar tiga bilangan bulat ini menjadi daftar tiga string heksadesimal masing-masing satu karakter.

  4. "#"<>%menambahkan #karakter dan menggabungkan semua karakter ini menjadi satu.

Roma
sumber
1
48 bytes
attinat
2

MathGolf , 19 12 byte

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

Keluaran sebagai daftar karakter. Jika ini tidak diizinkan, tambahan tambahany harus ditambahkan untuk bergabung dengan daftar karakter ke string.

-7 byte terima kasih kepada @maxb , karena saya melihat melewati builtin ( 2ô_2<\1>]ke 2/).

Cobalah online.

Penjelasan:

              # 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
sumber
2

Ruby (2.5.3), 45 , 44 , 42 byte

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

EDIT: disimpan satu byte karena kita tidak memerlukan grup karakter untuk karakter kedua di regex (terinspirasi oleh jawaban Neil)

EDIT 2: menyimpan 2 byte karena sintaks dash roket lambda tidak perlu tanda kurung di sekitar argumen

DaveMongoose
sumber
2
Anda dapat menyimpan 7 byte dengan mengambil input pada stdin dan menggunakan -pflag dan 2 lainnya dengan menggunakan $&alih-alih argumen di dalam blok: tio.run/##KypNqvz/…
Jordan
1
@ Jordan, terima kasih! Saya tidak tahu tentang keduanya, jadi itu adalah bantuan nyata untuk upaya golf di masa depan
DaveMongoose
1

Python 2 ( 109 101 97 85 83 74 byte)

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

"Jarak terdekat" ditangani oleh divisi dengan 17 dan pembulatan.

Perbaikan:

-8 byte dengan menggunakan int(...+.5)trik, bukanint(round(...))

-4 byte dengan menggunakan pemahaman daftar alih-alih map()

-1 byte oleh hardcoding #di output (terima kasih @movatica)

-10 byte dengan tidak menggunakan re.findall("..",...)splicing String eksplisit

-2 byte dengan tidak menggunakan pemahaman daftar, tetapi ekspresi generator inline di join(terima kasih @movatica)

-1 byte dengan tidak menyambung bagian :7akhir untuk bagian biru

-9 byte dengan iterasi yang lebih baik atas warna - yaitu iterasi atas indeks, bukan karakter yang sebenarnya (terima kasih @movatica)

Grzegorz Oledzki
sumber
1
@movatica - Anda benar, menambahkannya
Grzegorz Oledzki
1
Hemat 1 byte dengan hardcoding '#'daripada x[0].
movatica
1
Anda dapat melewati pemahaman daftar di dalam ''.join(...), karena juga menangani ekspresi generator. Hapus []dan simpan 2 byte lagi :)
movatica
1
Terima kasih! range(1,6,2)bahkan lebih baik dengan[1,3,5]
Grzegorz Oledzki
1
Jonathan Allen mengusulkan trik berbeda untuk pembulatan dalam versi mz Pzthon3. Ini berlaku di sini juga: lambda x:'#'+''.join(hex((int(x[i:i+2],16)+8)/17)[2:]for i in[1,3,5])-> 69 byte
movatica
1

Perl 5 -p , 35 34 byte

@nwellnhof menyimpan satu byte

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

Cobalah online!

Membaca dari STDIN, mengganti setiap pasangan item yang tidak #dengan karakter tunggal yang sesuai menggunakan metode pembagian dengan 17 untuk menemukan yang terdekat, kemudian secara implisit mengeluarkan ( -p) hasilnya.

Xcali
sumber
1

Python 3, 67 byte

f=lambda x:(f(x[:-2])if x[3:]else"#")+f'{(int(x[-2:],16)+8)//17:X}'
GSy
sumber
Selamat datang. Pertimbangkan untuk menambahkan deskripsi, penjelasan, atau tautan ke juru bahasa online, seperti TIO tempat kami dapat menjalankan kode Anda. Jawaban khusus kode cenderung ditandai secara otomatis sebagai berkualitas rendah. Lihat jawaban lain yang ada untuk contoh.
mbomb007
0

Merah , 103 byte

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

Cobalah online!

Ternyata versi Linux Red saat ini tidak memiliki implementasihex-to-rgb fungsi, itu sebabnya saya membuat konversi basis "secara manual" :)

Ini berfungsi dengan baik di Merah konsol GUI di Windows:

Merah , 94 byte

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

Arang , 22 byte

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

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Penjelasan:

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

Pyth , 20 byte

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

Coba di sini.

CATATAN: Jika tautan di atas memunculkan ImportError, buka di sini sebagai gantinya; saat ini ada bug di halaman "resmi", dan ini adalah solusi sementara oleh Maltysen . Tautan ini dapat berhenti berfungsi setelah yang resmi diperbaiki.

Erik the Outgolfer
sumber
0

Keempat (gforth) , 87 byte

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

Cobalah online!

Penjelasan

  1. Abaikan / potong karakter input pertama ( #)
  2. Atur penerjemah ke mode heksadesimal
  3. Keluaran #
  4. Loop 3 kali, di setiap loop:
    1. Tambahkan 2 ke alamat awal string
    2. Ubah 2 karakter berikutnya dalam string menjadi angka heksadesimal
    3. Gunakan pembagian dan modul oleh 17 (0x11 ) untuk mendapatkan nilai terdekat untuk komponen yang diperpendek
    4. Output tanpa ruang sebelumnya
  5. Atur penerjemah kembali ke mode Desimal

Penjelasan Kode

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

K4 , 39 byte

Larutan:

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

Penjelasan:

Gunakan strategi yang sama dengan banyak jawaban ini (yaitu tambahkan 8, bagi 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 "#"

Tambahan:

  • "#",{x@*16\:a?&/a:abs(17*!16)-16/:x?y}[.Q.nA]@/:3 2#1_- ide asli saya selama 54 byte
streetster
sumber