Pengkodean kode barcode

16

Tulis fungsi atau program yang menyandikan string ke kode format barcode, di mana setiap karakter dikodekan sebagai lima batang yang dipisahkan oleh empat celah. Dua bar dan satu celah lebar dan yang lainnya sempit (kode 10 * 4), atau tiga celah lebar dan tidak ada balok yang lebar (4 kode). Ini memberikan 44 kode berbeda, dari yang mana kode cadangan yang digunakan untuk menunjukkan awal dan akhir dari string yang disandikan.

Tantangan

Input adalah string yang hanya berisi karakter dari set

1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ-. +/$%

Outputnya adalah string yang disandikan sebagai string barcode. Kesenjangan sempit dan kesenjangan antar karakter adalah ruang tunggal dan kesenjangan lebar adalah tiga ruang. Bilah sempit adalah urutan byte UTF-8 untuk karakter Unicode "Blok penuh", █, yaitu 0xE2 0x96 0x88dan bilah lebar adalah tiga urutan / karakter byte tersebut ( ███). Daftar kode lengkap adalah:

      Spaces
      0100 0010 0001 1000 1011 1101 1110 0111
Bars
00000                       +    /    $   %
10001   1    A    K    U
01001   2    B    L    V
11000   3    C    M    W
00101   4    D    N    X
10100   5    E    O    Y
01100   6    F    P    Z
00011   7    G    Q    -
10010   8    H    R    .
01010   9    I    S  space          1=wide
00110   0    J    T  start/end      0=narrow

Bilah dan spasi disisipkan, dimulai dari bilah, jadi misalnya Q adalah

bar   0 0 0  1     1 
code  █ █ █ ███   ███
space  0 0 0    1

Setelah meng-encode semua karakter, string dibatasi pada kedua ujungnya dengan █ █ ███ ███ █. Kesenjangan intercharacter, ruang tunggal, dimasukkan di antara setiap huruf. Solusi Anda dapat menampilkan spasi tambahan dan baris baru tambahan (dalam urutan itu).

Contohnya

""     → "█   █ ███ ███ █ █   █ ███ ███ █"

"A"    → "█   █ ███ ███ █ ███ █ █   █ ███ █   █ ███ ███ █"

"C++"  → "█   █ ███ ███ █ ███ ███ █   █ █ █   █ █   █   █ █   █ █   █   █ █   █ ███ ███ █"

"GOLF" → "█   █ ███ ███ █ █ █ █   ███ ███ ███ █ ███ █   █ █ ███ █ █   ███ █ ███ ███   █ █ █   █ ███ ███ █"

Format input / output standar diizinkan dan celah standar tidak diizinkan. Ini adalah , jadi kode terpendek yang diukur dalam byte menang!

Angs
sumber
1
Bolehkah kita menggunakan karakter ASCII yang dapat dicetak (Anda dapat memilih mana yang diizinkan) alih-alih █?
Erik the Outgolfer
Untuk bahasa seperti BrainFuck, apa yang dianggap sebagai "satu penggunaan"?
14m2
1
@Angs saya maksudkan pada output pada dasarnya, bukan dalam kode. Tidaklah adil untuk memberikan hukuman pada penggunaan #karakter, karena, misalnya, "#"bukan satu-satunya alasan penggunaan karakter.
Erik yang Outgolfer
@EriktheOutgolfer Apa yang saya maksud adalah dalam string literal dan sejenisnya, tetapi mengingat poin l4m2 mungkin lebih baik untuk tidak mengizinkannya. Lagi pula, apakah ada bahasa yang tidak dapat menghasilkan tiga byte?
Angs

Jawaban:

7

JavaScript (ES6), 225 212 byte

Disimpan 4 byte berkat @ l4m2

s=>`#${s}#`.replace(/./g,c=>'0202020202'.replace(/./g,(j,k)=>[C='█',C+C+C,' ','   '][(i="%+/$U1AKV2BLW3CMX4DNY5EOZ6FP-7GQ.8HR 9IS#0JT".indexOf(c),[170,257,260,5,272,17,20,320,65,68,80][i>>2]^2<<i%4*2)>>k&1|j]))

Cobalah online!

Bagaimana?

Tabel dapat disusun ulang sehingga topeng biner 9-bit karakter dengan cepat disimpulkan dari baris dan kolom menggunakan rumus berikut:

n = m XOR (2 << k)

dengan:

  m  | k: 0   2   4   6
-----+------------------      Examples:
 170 |    %   +   /   $
 257 |    U   1   A   K         'G' = 320 XOR (2 << 4) = 320 XOR 32 = 352
 260 |    V   2   B   L
   5 |    W   3   C   M         '+' = 170 XOR (2 << 2) = 170 XOR 8  = 162
 272 |    X   4   D   N
  17 |    Y   5   E   O
  20 |    Z   6   F   P
 320 |    -   7   G   Q
  65 |    .   8   H   R
  68 |   spc  9   I   S
  80 |    #   0   J   T
Arnauld
sumber
s=>`#${s}#`.replace(/./g,c=>'0202020202'.replace(/./g,(j,k)=>[C='#',C+C+C,' ',' '][(i="%+/$U1AKV2BLW3CMX4DNY5EOZ6FP-7GQ.8HR 9IS#0JT".indexOf(c),[,257,260,5,272,17,20,320,65,68,80][i>>2]|(2<<i%4*2^(i<4)*170))>>k&1|j]))(221)
l4m2
@ l4m2 Itu sepertinya tidak valid. Namun, saya sudah berhasil menemukan perbaikan untuk 221 byte .
Erik the Outgolfer
@EriktheOutgolfer Saya pikir pada dasarnya itulah yang dikirimkan l4m2 dengan blok penuh alih-alih '#'. Atau apakah saya melewatkan sesuatu?
Arnauld
@Arnauld Dokumen asli mereka tidak terpasang dengan benar.
Erik the Outgolfer
3

Merah , 452 445 byte

func[s][q: func[x y z][append/dup x y z]append insert s"*""*"b:
func[n][v: copy[]until[append v n % 2 * 2 + 1
1 > n: n / 2]q v 1 5 - length? v
reverse v]a: q":1234567890:ABCDEFGHIJ:KLMNOPQRST:UVWXYZ-. *"" "44
a/45: #"+"a/56: #"/"a/67: #"$"a/78: #"%"foreach t s[i: index? find a t
k: b pick[0 17 9 24 5 20 12 3 18 10 6]either 0 = j: i % 11[11][j]m:
b pick[8 4 2 16 22 26 28 14]i - 1 / 11 + 1 z: copy""repeat n 5[q z"█"k/(n)
q z" "m/(n)]prin z]]

Cobalah online!

Saya akan mencoba untuk bermain golf lebih jauh, tetapi saya tidak berharap banyak dari solusi naif ini.

Galen Ivanov
sumber
2

Java 10, 455 byte

s->{String r="",R=r;for(var c:("~"+s+"~").split(""))r+=r.format("%9s",Long.toString(new int[]{148,289,97,352,49,304,112,37,292,100,52,265,73,328,25,280,88,13,268,76,28,259,67,322,19,274,82,7,262,70,22,385,193,448,145,400,208,133,388,196,138,162,168,42}["~1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ-. +/$%".indexOf(c)],2)).replace(' ','0');for(int l=r.length(),i=0,c;i<l;R+=""+(i%9%2<1?c<49?"█":"███":c<49?" ":"   ")+(i%9>7&++i<l?" ":""))c=r.charAt(i);return R;}

Cobalah online.

Penjelasan:

s->{                     // Method with String as both parameter and return-type
  String r="",           //  Temp-String, staring empty
         R=r;            //  Result-String, starting empty as well
  for(var c:("~"+s+"~")  //  Prepend and append "~" to the input
            .split(""))  //  And loop over each character
    r+=r.format("%9s",Long.toString( 
                         //   Convert the following integer to a 9-bit binary String:
       new int[]{148,289,97,352,49,304,112,37,292,100,52,
                 265,73,328,25,280,88,13,268,76,28,259,67,322,
                 19,274,82,7,262,70,22,385,193,448,145,400,208,
                 133,388,196,138,162,168,42}
                         //    Array containing all decimal values of the binary Strings
       ["~1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ-. +/$%".indexOf(c)]
                         //    with the index based on the current character
   ,2)).replace(' ','0');
                         //   (also part of the integer to 9-bit binary String conversion)
  for(int l=r.length(),i=0,c;i<l;
                         //  Loop `i` over the temp-String
      R+=                //    After every iteration: append the following to the result:
         ""+(i%9%2<1?    //     If `i` modulo-9 modulo-2 is 0:
              c<49?      //      And `c` is '0':
               "█"       //       Append a single block
              :          //      Else:
               "███"     //       Append three blocks
             :c<49?      //     Else-if `c` is '0':
              " "        //      Append a single space
             :           //     Else:
              "   ")     //      Append three spaces
         +(i%9>7         //     If `i` modulo-9 is 8,
           &++i<l?       //     and this is not the very last character
            " "          //      Append a space delimiter
           :             //     Else:
            ""))         //      Append nothing more
    c=r.charAt(i);       //   Set `c` to the current character in `r`
  return R;}             //  Return the result
Kevin Cruijssen
sumber
2

C (gcc) , 311 , 303 byte

(*P)()=printf;i;j;w;m[]={170,257,260,5,272,17,20,320,65,68,80};char*b=" \0\xE2\x96\x88",*t="%+/$U1AKV2BLW3CMX4DNY5EOZ6FP-7GQ.8HR 9IS#0JT",*c;p(x){j=256;w=2;while(j){P(b+w);if(x&1){P(b+w);P(b+w);}x/=2;j>>=1;w=2*!w;}P(" ");}f(char*_){p(82);for(c=_;*c;c++){i=strchr(t,*c)-t;p(m[i>>2]^(2<<(i&3)*2));}p(82);}

Cobalah online!

-8 Terima kasih untuk ceilingcat

Menggunakan strategi penyandian dari jawaban Arnauld. TIO termasuk tautan-w switch dan boilerplate untuk menghilangkan peringatan, ini tidak perlu dan dengan demikian tidak termasuk dalam skor.

Selain dari skema pengkodean seperti yang dijelaskan oleh Arnauld, trik lain di sini adalah untuk mempertahankan wvariabel sebagai toggling antara 2 dan 0 ( w=2*!w). Ini memungkinkan saya untuk memilih antara string pertama dan kedua di b. Yang pertama adalah spasi, yang kedua adalah persegi panjang yang diisi.

LambdaBeta
sumber
pintar, Anda harus mempostingnya :)
LambdaBeta
2

C (gcc) , 241 239 227 213 213 207 byte

#define P printf(i%2?" ":"█")
i;p(x){for(i=9;i--;x/=2)P,x&1&&P+P;P;}f(char*_){p(82);for(char*t="%+/$U1AKV2BLW3CMX4DNY5EOZ6FP-7GQ.8HR 9IS#0JT";*_;p(L"ªāĄ\5Đ\21\24ŀADP"[i/4]^2<<i%4*2))i=index(t,*_++)-t;p(82);}

Cobalah online!

Berdasarkan implementasi @ LambdaBeta .

Sedikit kurang golf:

#define P printf(i%2?" ":"█")
i;
p(x){
 for(i=9;i--;x/=2)
  P,
  x&1&&
   P+
   P;
 P;
}
f(char*_){
 p(82);
 for(char*t="%+/$U1AKV2BLW3CMX4DNY5EOZ6FP-7GQ.8HR 9IS#0JT";*_;p(L"ªāĄ\5Đ\21\24ŀADP"[i/4]^2<<i%4*2))
  i=index(t,*_++)-t;
 p(82);
}
plafon
sumber
1

Arang , 90 byte

⪫EE⪫**S⌕⁺⁺⭆…αχ﹪⊕μχα-. *+/$%ι⪫E⁵⁺⎇μ× ∨⁼›ι³⁹⁼²﹪⁻÷ι∨›ι³⁹χμ⁴¦³ω×█∨›ι³⁹∨§↨℅§.6':+3<-59ι²⊕μ³ω 

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

⪫EE⪫**S...⪫E⁵⁺...ω 

Bungkus string input dalam *s dan kemudian petakan di atasnya dua kali, akhirnya gabungkan hasilnya dengan spasi. Untuk peta kedua, kemudian ada peta tambahan pada rentang implisit 0..4, di mana dua substring digabungkan, dan hasil tersebut kemudian bergabung dengan konstanta string kosong yang telah ditentukan.

⌕⁺⁺⭆…αχ﹪⊕μχα-. *+/$%ι

Untuk peta bagian dalam pertama, buat string yang dibentuk dengan mengambil digit yang bertambah, alfabet huruf besar, dan simbol -. *+/$%, dan mencari posisi karakter input yang dipetakan. Misalnya, C++akan memetakan ke [12, 40, 40].

⎇μ× ∨⁼›ι³⁹⁼²﹪⁻÷ι∨›ι³⁹χμ⁴¦³ω

Substring pertama mewakili spasi sebelum bar. Tidak ada apa-apa sebelum bilah pertama, tetapi bilah lainnya tergantung pada posisi karakter input yang dipetakan: jika lebih dari 39, maka hanya satu tempat yang memiliki ruang tunggal, sedangkan jika di bawah 40, maka hanya satu tempat yang memiliki tiga spasi, dan posisinya juga dikonversi ke kolom dengan membaginya dengan 10. Jika kolom dan indeks loop berbeda dengan 2 (modulo 4) maka itu adalah tempat aneh.

×█∨›ι³⁹∨§↨℅§.6':+3<-59ι²⊕μ³

Substring kedua mewakili bar. Jika posisinya di atas 39 maka selalu ada satu bar kalau tidak posisinya terlihat dalam array bit yang dipetakan ke karakter. Misalnya, jika posisinya 12, maka itu diindeks secara melingkar ke karakter ', yang 100111dalam bentuk biner, yang menunjukkan bilah lebar di kolom 1 dan 2. (Bagian depan 1diabaikan, itu hanya memastikan jumlah bit yang konsisten.)

Neil
sumber
1

Perl 5 , 244 byte

$l="{ ,   ,...,.........}"x9;@h{$",qw($ % + - . /),0..9,'',A..Z}=(<"$l">)[q{..=9...Z.>>...J=9..j.%r1...=).[.>=-..Ux?V.^=8.>.6o+ax_.=(..B=,..Yx6..b=(..#r'p.^...G.<=,..Sx5B.\=(.V.It..z:..-z.=<6.}=~s/./ord$&/gre=~/.{6}/g];s/^|./$h{$&} /g;$\=$h{''}

Cobalah online!

Berisi banyak unsintables dan karakter byte tinggi, tautan TIO menyediakan xxdrepresentasi. Saya berharap ini akan menjadi lebih kecil, dan saya mungkin masih bisa mengemas data dengan cara yang lebih efisien sehingga saya akan melihat bagaimana saya pergi. Ini membangun semua permutasi " "," ","█","███"dan kemudian memetakan indeks daftar ke karakter yang sesuai.

Dom Hastings
sumber
1

Haskell , 275 270 byte

z=0:z
x!0=[]
x!n=mod n x:x!div n x
e c|Just a<-lookup c.zip"W3YZ56C$EF. 89*HM/ORU1QGNTDJ7%40LSBIP2-+XVKA".((++)<*>(reverse<$>))$take 9.(++z).(2!)<$>scanl(+)7(67!0x117CDBC49F9EEEF11C3A659CACB31236)=zipWith(\l c->c<$[1..2*l+1])(a++[0])(cycle"█ ")>>=id
f s='*':s++"*">>=e

Cobalah online!

Operator x!nyang menghitung digit x-base dari n, digunakan dua kali untuk mendekompres kode. Kode dikompresi terlebih dahulu sebagai string biner dengan lebar = 1 dan sempit = 0, tanpa memperhatikan warna, misalnyaR↔10000110↔262 . Angka-angka ini kemudian diurutkan dan dibedakan untuk mendapatkan angka dalam kisaran [3,66], yang dikompresi dengan kebalikan dari algoritma digit biner sebagai 0x117CDBC49F9EEEF11C3A659CACB31236. Ini hanya berisi setengah dari kode, sisanya adalah kebalikan dari ini.

Tidak Terkumpul:

z=0:z                       -- infinite zeroes for padding
x!0=[]                      -- digits of n in base x, recursion base case
x!n=mod n x:x!div n x       -- digits of n in base x
e c | Just a                -- read upwards from (*)
  <-lookup c                -- lookup code, given letter
  . zip"W3YZ56C$EF. 89*HM/ORU1QGNTDJ7%40LSBIP2-+XVKA" 
                            -- combine codes with correct letters
  . ((++)<*>(reverse<$>))   -- concatenate list and list with reverse codes
  $ take 9                  -- take nine
  . (++z)                   -- pad with infinite zeroes on right
  . (2!)                    -- convert to binary digits – [[1,1,1],[1,0,1,1]…]
  <$> scanl (+) 7           -- cumulative sum starting from 7 – [7,13,19,22,25…]
        (67!0x117CDBC49F9EEEF11C3A659CACB31236)       
                            -- (*) digits in base 67 – [6,6,3,3,3,9,5,7…]
  = zipWith
      (\l c->c<$[1..2*l+1]) -- combine width and color, length is 2*l+1
      (a++[0])              -- list of widths as 0/1, 0 added for interchar gap
      (cycle"█ ")           -- infinite list of bar colors, leftovers are unused
  >>=id                     -- concatenate
f s='*':s++"*">>=e          -- surround string with delimiters, map e and concat
Angs
sumber