코드 39 바코드 인코더


16

문자열을 Code 39 형식 바코드 로 인코딩하는 함수 또는 프로그램을 작성하십시오 . 여기서 각 문자는 4 개의 공백으로 구분 된 5 개의 막대로 인코딩됩니다. 막대 중 두 개와 간격 중 하나가 넓고 다른 하나는 좁거나 (10 * 4 코드), 간격 중 세 개가 넓고 막대 중 하나가 없습니다 (4 코드). 이 코드는 44 개의 서로 다른 코드를 제공하며,이 중 하나는 인코딩 된 문자열의 시작과 끝을 나타내는 데 사용되는 예약 된 코드입니다.

도전

입력은 세트의 문자 만 포함하는 문자열입니다.

1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ-. +/$%

출력은 바코드 문자열로 인코딩 된 문자열입니다. 좁은 간격과 문자 간 간격은 단일 공간이고 넓은 간격은 3 칸입니다. 좁은 막대는 유니 코드 문자 "Full block"에 대한 UTF-8 바이트 시퀀스, █입니다. 즉 0xE2 0x96 0x88넓은 막대는 이러한 3 개의 바이트 시퀀스 / 문자 ( ███)입니다. 전체 코드 목록은 다음과 같습니다.

      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

모든 문자를 인코딩 한 후 문자열의 양쪽 끝이로 구분됩니다 █ █ ███ ███ █. 단일 문자 인 문자 간 간격이 모든 문자 사이에 삽입됩니다. 솔루션은 후행 공백과 후행 줄 바꿈 (순서대로)을 출력 할 수 있습니다.

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

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

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

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

표준 입력 / 출력 형식이 허용되고 표준 허점이 허용되지 않습니다. 이것은 이므로 바이트 단위로 측정 된 가장 짧은 코드가 이깁니다!


1
█ 대신 인쇄 가능한 ASCII 문자 (허용 할 문자를 선택할 수 있음)를 사용할 수 있습니까?
아웃 골퍼 에릭

BrainFuck과 같은 언어의 경우 "한 번의 사용"으로 간주되는 것은 무엇입니까?
l4m2

1
@Angs 기본적으로 출력이 아니라 코드가 아닙니다. #예를 들어, "#"언어로 사용될 수있는 유일한 이유는 아니기 때문에 캐릭터 사용에 대한 처벌을하는 것은 그리 공평 하지 않습니다.
아웃 골퍼 에릭 12

@EriktheOutgolfer 내가 의미하는 것은 문자열 리터럴 등 이었지만 l4m2의 요점을 고려하면 허용하지 않는 것이 가장 좋습니다. 결국, 3 바이트를 출력 할 수없는 언어가 있습니까?
Angs

답변:


7

자바 스크립트 (ES6) 225 212 바이트

@ l4m2 덕분에 4 바이트 절약

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 바이트에 대한 수정 사항을 찾았습니다 .
Outgolfer Erik

@EriktheOutgolfer 나는 그것이 기본적으로 l4m2가 '#'대신 전체 블록으로 제출 한 것이라고 생각합니다. 아니면 뭔가 빠졌습니까?
Arnauld

@Arnauld 원본이 제대로 배치되지 않았습니다.
아웃 골퍼 에릭

3

빨강 , 452445 바이트

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

자바 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 바이트

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

온라인으로 사용해보십시오!

ceilingcat 덕분에 -8

Arnauld의 답변에서 인코딩 전략을 사용합니다. TIO 링크에는 -w경고를 제거하기위한 스위치 및 상용구가 포함되어 있으며, 이는 불필요하므로 점수에 포함되지 않습니다.

Arnauld가 설명 한 인코딩 체계 외에도 다른 트릭은 w변수를 2와 0 ( w=2*!w) 사이에서 전환 하는 것으로 유지하는 것 입니다. 이를 통해에서 첫 번째 문자열과 두 번째 문자열 중에서 선택할 수 있습니다 b. 첫 번째는 공백이고 두 번째는 채워진 사각형입니다.


영리한, 당신은 그것을 게시해야합니다 :)
LambdaBeta

2

C (gcc) , 24139227213207 바이트

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

온라인으로 사용해보십시오!

@LambdaBeta의 구현을 기반으로 합니다 .

약간 덜 골프 :

#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, 여기서 두 개의 하위 문자열이 연결되고 이러한 결과는 사전 정의 된 빈 문자열 상수와 결합됩니다.

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

첫 번째 내부 맵의 경우 증가 된 숫자, 대문자 알파벳 및 기호를 사용하여 구성된 문자열을 작성 -. *+/$%하고 맵핑 된 입력 문자의 위치를 ​​찾으십시오. 예를 들어에 C++매핑됩니다 [12, 40, 40].

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

첫 번째 부분 문자열은 막대 앞의 공백을 나타냅니다. 첫 번째 막대 앞에는 아무것도 없지만 다른 막대는 매핑 된 입력 문자의 위치에 따라 다릅니다. 39를 초과하면 한 곳에만 단일 공백이 있고 40 이하인 경우 한 곳에만 3 개가 있습니다 공백과 위치도 열로 나누어 열로 변환합니다. 열과 루프 인덱스가 2 (모듈로 4)가 다르면 그 자리가 이상합니다.

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

두 번째 부분 문자열은 막대를 나타냅니다. 위치가 39를 초과하면 항상 하나의 막대가 있고 그렇지 않으면 문자에 매핑 된 비트 배열에서 위치가 조회됩니다. 예를 들어, 위치가 12 인 경우, 1 열 및 2 열의 넓은 막대를 나타내는 2 진 문자 '인 문자에 순환 색인됩니다 100111(리딩 1은 무시되므로 단순히 일관된 비트 수를 보장합니다).


1

펄 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

하스켈 , 275270 바이트

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!nn의 x-베이스 자릿수를 계산하는 연산자 는 코드 압축 해제에 두 번 사용됩니다. 코드는 예를 들어 색상에 관계없이 wide = 1 및 좁은 = 0 인 이진 문자열로 압축됩니다 R↔10000110↔262. 그런 다음이 숫자는 [3,66] 범위의 숫자를 얻기 위해 정렬되고 차이가납니다.이 숫자는로 이진 숫자 알고리즘의 역으로 ​​압축됩니다 0x117CDBC49F9EEEF11C3A659CACB31236. 여기에는 코드의 절반 만 포함되어 있으며 나머지는 역순입니다.

언 골프 드 :

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.