เครื่องเข้ารหัสบาร์โค้ดรหัส 39


16

เขียนฟังก์ชั่นหรือโปรแกรมที่เข้ารหัสสตริงลงในรหัส 39บาร์โค้ดรูปแบบที่อักขระแต่ละตัวถูกเข้ารหัสเป็นห้าแท่งคั่นด้วยช่องว่างสี่ช่อง ทั้งสองแท่งและหนึ่งในช่องว่างมีความกว้างและอื่น ๆ ที่แคบ (10 * 4 รหัส) หรือสามของช่องว่างที่มีความกว้างและไม่มีแถบใด (4 รหัส) สิ่งนี้จะให้รหัสที่แตกต่างกัน 44 รหัสซึ่งเป็นรหัสที่สงวนไว้ซึ่งใช้เพื่อแสดงถึงจุดเริ่มต้นและจุดสิ้นสุดของสตริงที่เข้ารหัส

ความท้าทาย

อินพุตเป็นสตริงที่มีอักขระจากชุดเท่านั้น

1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ-. +/$%

เอาต์พุตคือสตริงที่เข้ารหัสเป็นสตริงบาร์โค้ด ช่องว่างแคบและช่องว่างระหว่างอักขระเป็นช่องว่างเดียวและช่องว่างกว้างคือช่องว่างสามช่อง แถบแคบคือลำดับ UTF-8 สำหรับอักขระ Unicode "Full block", █, 0xE2 0x96 0x88และแถบกว้างคือลำดับ / ตัวอักษรไบต์สามตัว ( ███) รายการรหัสทั้งหมดคือ:

      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

แถบและช่องว่างนั้นเป็นแบบอินเตอร์เลดเริ่มต้นที่บาร์ดังนั้นตัวอย่างเช่น Q คือ

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

█ █ ███ ███ █หลังจากการเข้ารหัสตัวอักษรทั้งหมดสตริงคั่นที่ปลายทั้งสองด้วย intercharacter gap ซึ่งเป็นช่องว่างเดียวแทรกระหว่างตัวอักษรทุกตัว โซลูชันของคุณอาจส่งออกช่องว่างต่อท้ายและขึ้นบรรทัดใหม่ (ตามลำดับ)

ตัวอย่าง

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

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

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

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

อนุญาตรูปแบบอินพุต / เอาต์พุตมาตรฐานและไม่อนุญาตช่องโหว่มาตรฐาน นี่คือดังนั้นโค้ดที่สั้นที่สุดที่วัดเป็นไบต์จะชนะ!


1
เราสามารถใช้อักขระ ASCII ที่พิมพ์ได้ (คุณสามารถเลือกได้ว่าจะอนุญาตหรือไม่) แทน█?
Erik the Outgolfer

สำหรับภาษาอย่าง BrainFuck สิ่งใดที่นับว่าเป็น "การใช้งานครั้งเดียว"
l4m2

1
@Angs ฉันหมายถึงการส่งออกโดยทั่วไปไม่ได้อยู่ในรหัส มันไม่ยุติธรรมเลยที่จะให้บทลงโทษสำหรับการใช้#ตัวละครเนื่องจากตัวอย่าง"#"ไม่ใช่เหตุผลเดียวที่สามารถใช้ในภาษาได้
Erik the Outgolfer

@EriktheOutgolfer สิ่งที่ฉันหมายถึงคือตัวอักษรสตริงและสิ่งที่คล้ายกัน แต่เมื่อพิจารณาถึงจุดของ l4m2 มันอาจเป็นการดีที่สุดที่จะไม่อนุญาต ท้ายที่สุดมีภาษาใดบ้างที่ไม่สามารถส่งออกสามไบต์?
Angs

2
ถ้ามันจะช่วยให้ทุกคนที่นี่เป็น Pastebin มีทั้งหมด 9 บิตไบนารี Strings และทศนิยมการแปลงสำหรับตัวละครแต่ละตัว
Kevin Cruijssen

คำตอบ:


7

JavaScript (ES6), 225 212 ไบต์

บันทึกแล้ว 4 ไบต์ด้วย @ 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]))

ลองออนไลน์!

อย่างไร?

ตารางสามารถจัดเรียงใหม่เพื่อให้หน้ากากไบนารีแบบ 9 บิตของอักขระถูกอนุมานอย่างรวดเร็วจากแถวและคอลัมน์โดยใช้สูตรต่อไปนี้:

n = m XOR (2 << k)

ด้วย:

  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

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 ดูเหมือนจะไม่ถูกต้อง อย่างไรก็ตามผมได้มีการจัดการที่จะหาวิธีแก้ 221 ไบต์
Erik the Outgolfer

@EriktheOutgolfer ฉันคิดว่านั่นเป็นสิ่งที่ l4m2 ส่งมาพร้อมบล็อกเต็มแทน '#' หรือฉันกำลังพลาดอะไรอยู่?
Arnauld

@Arnauld ต้นฉบับของพวกเขาไม่ได้พื้นที่อย่างถูกต้อง
Erik the Outgolfer

3

สีแดง , 452 445 ไบต์

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

ลองออนไลน์!

ฉันจะพยายามตีกอล์ฟให้ไกลกว่านี้ แต่ฉันไม่ได้คาดหวังอะไรมากมายจากคำตอบที่ไร้เดียงสานี้


2

Java 10, 455 ไบต์

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

ลองออนไลน์

คำอธิบาย:

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

2

C (gcc) , 311 , 303 bytes

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

ลองออนไลน์!

-8 ขอบคุณแมวเพดาน

ใช้กลยุทธ์การเข้ารหัสจากคำตอบของ Arnauld ลิงค์ของ TIO นั้นมี-wสวิตช์และหม้อไอน้ำเพื่อลบคำเตือนซึ่งไม่จำเป็นและไม่รวมอยู่ในคะแนน

นอกเหนือจากรูปแบบการเข้ารหัสตามที่อธิบายโดย Arnauld เคล็ดลับอื่น ๆ ที่นี่คือการรักษาwตัวแปรเป็นการสลับระหว่าง 2 และ 0 ( w=2*!w) bนี้ช่วยให้ผมเลือกระหว่างสายแรกและครั้งที่สองใน ที่แรกก็คือช่องว่างที่สองคือสี่เหลี่ยมที่เต็มไป


ฉลาดคุณควรโพสต์ :)
LambdaBeta

2

C (gcc) , 241 239 227 213 207 ไบต์

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

ลองออนไลน์!

ขึ้นอยู่กับการ@ การดำเนินงานของ

golfed น้อยกว่าเล็กน้อย:

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

1

ถ่าน , 90 ไบต์

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

ลองออนไลน์! หมายเหตุ: พื้นที่ต่อท้าย การเชื่อมโยงคือการใช้รหัสเวอร์ชันอย่างละเอียด คำอธิบาย:

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

ล้อมสตริงอินพุตใน*s จากนั้นแม็พสองครั้งสุดท้ายเชื่อมผลลัพธ์กับช่องว่าง สำหรับแผนที่ที่สองนั้นจะมีแผนที่เพิ่มเติมในช่วงของปริยายโดย0..4ที่สอง substrings จะต่อกันและผลลัพธ์เหล่านั้นจะถูกรวมเข้ากับค่าคงที่สตริงว่างที่กำหนดไว้ล่วงหน้า

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

สำหรับแผนที่ด้านในแรกให้สร้างสตริงที่เกิดขึ้นโดยการใช้ตัวเลขที่เพิ่มขึ้นตัวอักษรตัวพิมพ์ใหญ่และสัญลักษณ์-. *+/$%และค้นหาตำแหน่งของอักขระอินพุตที่แม็พ ยกตัวอย่างเช่นจะแมปไปC++[12, 40, 40]

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

สตริงย่อยแรกแสดงถึงช่องว่างก่อนแถบ ไม่มีสิ่งใดก่อนแถบแรก แต่แถบอื่น ๆ ขึ้นอยู่กับตำแหน่งของอักขระอินพุตที่ถูกแมป: ถ้าเกิน 39 แล้วมีเพียงที่เดียวที่มีพื้นที่เดียวในขณะที่ถ้าอยู่ต่ำกว่า 40 แล้วมีเพียงแห่งเดียวที่มีสามแห่ง ช่องว่างและตำแหน่งจะถูกแปลงเป็นคอลัมน์ด้วยการหารด้วย 10 ถ้าคอลัมน์และดัชนีลูปแตกต่างกัน 2 (โมดูโล 4) นั่นคือสถานที่แปลก ๆ

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

สตริงย่อยที่สองแสดงถึงแถบ หากตำแหน่งมากกว่า 39 จะมีแถบหนึ่งเสมอมิฉะนั้นตำแหน่งจะถูกค้นหาในอาร์เรย์ของบิตที่แมปกับอักขระ ตัวอย่างเช่นหากตำแหน่งคือ 12 นั่นคือการจัดทำดัชนีแบบวงกลมให้กับตัวละคร'ซึ่งอยู่100111ในรูปแบบไบนารีระบุแถบกว้างในคอลัมน์ 1 และ 2 (ผู้นำ1จะถูกละเว้นมันก็จะทำให้มั่นใจนับบิตที่สอดคล้องกัน)


1

Perl 5 , 244 ไบต์

$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{''}

ลองออนไลน์!

มีอักขระที่ไม่สามารถพิมพ์ได้จำนวนมากและอักขระไบต์สูงลิงค์ TIO เป็นxxdตัวแทน ฉันหวังว่าสิ่งนี้จะเล็กลงและฉันก็ยังสามารถแพ็คข้อมูลได้อย่างมีประสิทธิภาพมากขึ้นดังนั้นฉันจะดูว่าฉันไปอย่างไร สิ่งนี้จะสร้างการเรียงสับเปลี่ยนทั้งหมดของ" "," ","█","███"และจากนั้นแมปบ่งชี้ของรายการกับอักขระที่สอดคล้องกัน


1

Haskell , 275 270 ไบต์

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

ลองออนไลน์!

โอเปอเรเตอร์x!nที่คำนวณตัวเลขฐาน x ของ n ถูกใช้สองครั้งเพื่อคลายรหัส รหัสจะถูกบีบอัดเป็นครั้งแรกที่สายไบนารีกว้าง = 1 และแคบ = 0 R↔10000110↔262โดยคำนึงไม่มีสีเช่น ตัวเลขเหล่านี้จะถูกจัดเรียงแล้วและ differenced จะได้รับหมายเลขในช่วง [3,66] 0x117CDBC49F9EEEF11C3A659CACB31236ซึ่งจะถูกบีบอัดด้วยย้อนกลับของอัลกอริทึมเลขฐานสองเป็น มีรหัสเพียงครึ่งเดียวส่วนที่เหลือจะกลับรายการ

Ungolfed:

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.