바코드 골프 : 숫자의 UPC 생성


12

오늘날 거의 모든 매장에서 UPC ( Universal Product Code ) 바코드를 사용하여 결제 프로세스를 단순화합니다. 이름이 당신에게 아무 의미가 없다면, 당신은 그들이 어떻게 생겼는지 알 것입니다 :

샘플 UPC-A 바코드

체재

가장 일반적인 시스템은 UPC-A이며 12 자리를 사용하여 각 특정 제품을 나타냅니다. 각 숫자는 일련의 흑백 줄무늬로 인코딩되어 기계가 7 비트 길이의 코드를 읽을 수 있습니다. 바코드의 시작, 중간 및 끝을 나타내는 총 11 비트의 패턴이 있습니다. 이것은 총 바코드 길이가 12 × 7 + 11 = 95 비트입니다. 이제부터는 이진을 사용하여 각 비트의 색상을 나타내는 경우 0흰색이고 1검은 색입니다.

시작과 끝의 패턴은 모두입니다 101. 그런 다음 숫자는 6 개의 2 개 그룹으로 나뉘어 01010왼쪽과 오른쪽 그룹 사이의 패턴으로 아래와 같이 인코딩됩니다 . 이 표에는 각 숫자의 패턴이 나와 있습니다. 숫자가 오른쪽에 있는지 왼쪽에 있는지에 따라 패턴이 다릅니다 (이렇게하면 바코드를 거꾸로 스캔 할 수 있습니다). 그러나 오른쪽의 패턴은 왼쪽의 패턴과 반대입니다 (흰색은 검은 색으로 바꾸고 그 반대).

UPC 변환 표

위의 이미지가 보이지 않으면 각 숫자의 이진 값입니다.

#   Left    Right
0   0001101 1110010
1   0011001 1100110
2   0010011 1101100
3   0111101 1000010
4   0100011 1011100
5   0110001 1001110
6   0101111 1010000
7   0111011 1000100
8   0110111 1001000
9   0001011 1110100

UPC가 있다고 가정 해보십시오 022000 125033. (이 숫자는 임의의 숫자가 아닙니다. 의미를 알아 내면 의견을 남겨주십시오.) 모든 바코드에서 동일한이 상용구로 시작합니다.

101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx01010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx101

숫자의 경우 각 숫자가 켜져있는 쪽 (왼쪽 또는 오른쪽)의 해당 인코딩으로 바꿉니다. 여전히 혼란 스러우면 아래 이미지를 참조하십시오.

UPC 인코딩 분석

다음은 |파트를 분리하는 파이프가 있는 이진 출력입니다 .

101|0001101|0010011|0010011|0001101|0001101|0001101|01010|1100110|1101100|1001110|1110010|1000010|1000010|101

도전

사용자 입력을 위해 UPC-A 바코드를 출력하는 프로그램을 작성하십시오. 이미지의 크기는 95 × 30 픽셀이어야하며 각 "비트"는 1 픽셀 너비와 30 픽셀 높이입니다. 검은 색 줄무늬가 rgb(0, 0, 0)있고 흰색 줄무늬는 지속적으로 투명 rgb(255, 255, 255)합니다.

노트

  • stdin 또는 명령 행에서 입력을 가져 오거나 문자열 또는 정수를 사용하는 함수를 작성하십시오 (입력에 선행 0이있을 수 있으며 대부분의 언어는이를 제거하거나 숫자를 8 진수로 변환 함).
  • 다음 방법 중 하나로 이미지를 출력하십시오.
    • 선택한 이름과 형식 (PNG, PBM 등)으로 파일에 저장하십시오.
    • 화면에 표시하십시오.
    • 파일 데이터를 stdout으로 출력하십시오.
  • 이미지 또는 그래픽 라이브러리를 사용할 수 있지만 바코드를 생성하는 라이브러리 또는 내장을 사용할 수 없습니다 ( Mathematica ).
  • UPC의 마지막 숫자는 일반적으로 검사 숫자 이지만 이러한 목적으로 걱정할 필요는 없습니다.

다음은 코드를 테스트하는 몇 가지 예입니다. 이진 출력도 편의상 제공됩니다.

입력: 012345678910

산출:

10100011010011001001001101111010100011011000101010101000010001001001000111010011001101110010101

입력: 777777222222

산출:

10101110110111011011101101110110111011011101101010110110011011001101100110110011011001101100101

채점

이것은 코드 golf 이므로 가장 짧은 제출 (바이트 단위)입니다. Tiebreaker는 가장 빠른 게시물로갑니다.


음 ... 수분이 많은 과일.
Dennis

입력을 배열로 가져올 수 있습니까? 예["777777","222222"]
Downgoat

@ vihan 흠, 그것은 약간의 스트레칭이라고 생각합니다. 나는 아니오라고 말할 것입니다.
NinjaBearMonkey

2
최초의 UPC 바코드 스캔!
Dennis

1
훌륭합니다. 바코드는 항상 저를 매료 시켰습니다
Beta Decay

답변:


3

CJam, 58 57 바이트

'P1N95S30N[A1r:~"rflB\NPDHt":i2fbf=:R6<::!0AAR6>A1]s30*S*

휴대용 비트 맵 (ASCII)을 STDOUT에 인쇄합니다. 온라인으로 사용해보십시오.

작동 원리

'P1N95S30N     e# Push 'P', 1, '\n', 95, ' ', 30 and '\n'.

[              e#
  A1           e#   Push 10 and 1.
  r            e#   Read a token from STDIN.
  :~           e#   Caluate each character ('0' -> 0).
  "rflB\NPDHt" e#   Push that string.
  :i           e#   Cast each character to integer.
               e#   This pushes [114 102 108 66 92 78 80 68 72 116].
  2fb          e#   Convert each integer to base 2.
               e#   This pushes the representations for the right side.
  f=           e#   Select the proper representation of each digit in the input.
  :R           e#   Save the result in R.
  6<           e#   Keep the representations of the first six digits.
  ::!          e#   Negate each binary digit to obtain the "left" representation.
  0AA          e#   Push 0, 10, 10.
  R6>          e#   Push the representations of the last six digits.
  A1           e#   Push 10, 1.
]s             e# Collect in an array and cast to string.

30*            e# Repeat the resulting string 30 times.
S*             e# Join it, using spaces as separators.

4

Rev 1 BBC BASIC, 155 ascii chars, 토큰 화 된 파일 크기는 132 바이트

INPUTn$
FORi=91TO185p=i MOD2j=i MOD47IFj<42j+=i DIV141*42p=(j>41EORASC(MID$("XLd^bFznvh",VAL(MID$(n$,j/7+1,1))+1)))>>(j MOD7)AND1
IFp LINEi*2,60,i*2,0
NEXT

43의 오프셋을 i루프 에 통합하여 몇 바이트를 절약했습니다 . 파손을 피하기 위해 MOD2총 47 개의 추가 47을 추가해야했습니다.

이렇게하면 그림과 같이 바코드가 원점에서 더 멀리 이동합니다.

여기에 이미지 설명을 입력하십시오

Rev 0 BBC BASIC, 157 ascii chars, 토큰 화 된 파일 크기는 137 바이트

INPUTn$
FORi=1TO95p=i MOD2j=(i+43)MOD47IFj<42j+=i DIV51*42p=(i>50EORASC(MID$("XLd^bFznvh",VAL(MID$(n$,j/7+1,1))+1)))>>(j MOD7)AND1
IFp LINEi*2,0,i*2,60
NEXT

http://www.bbcbasic.co.uk/bbcwin/bbcwin.html 에서 통역사 다운로드

기본 화면 모드는 흰색 배경에 검은 색 텍스트입니다. 이것은 원래 BBC BASC와 다릅니다.

테스트 인쇄가 포함 된 언 골프 버전

데이터 막대의 계산은 한 줄에 따라 다르며 IF j<42모두 한 번에 수행되어야합니다. ungolfed 버전에서는 세 단계로 수행됩니다. 골프 버전에서 마지막 두 단계는 하나의 거대한 표현으로 결합됩니다.p=...

비트 맵에 순서를 바꿔야했는데 >>(j MOD 7), 비트에 액세스하는 데 사용 하기 때문에 가장 중요하지 않은 비트에 먼저 액세스한다는 의미입니다. 이 작업이 완료되면 모든 왼쪽 비트 맵이 ASCII 범위에 편리하게 배치됩니다.

  INPUTn$
  FOR i=1TO95                            :REM iterate through 95 bars
    p=i MOD2                             :REM calculate colour of format bar 1=black
    j=(i+43)MOD47                        :REM repetition is 42 data bars + 5 format bars. offset and modulo. if j<42 it is a data bar and we must change p.

    REM if i DIV 51=1 we are in the second half, so add 42 to j. Find the bitmap for left hand value, from character j/7 of the input.
    REM i>50 evaluates to false=0 true=-1. XOR this with p to invert bitmap for right hand side. Shift and AND with 1.  
    IF j<42 j+=i DIV51*42:p=ASC(MID$("XLd^bFznvh",  VAL(MID$(n$,j/7+1,1))+1  )) :p=(i>50EORp)>>(j MOD7) AND 1

    IF j MOD 7 = 0 PRINT                  :REM format test output
    PRINT ;p;                             :REM print test output
    IF p LINEi*2-2,0,i*2-2,60             :REM if p=1 plot bar. there are 2 logical units for each pixel.
  NEXT

테스트 출력이 포함 된 일반 출력, 언 골프 버전

여기에 이미지 설명을 입력하십시오


2

자바 스크립트 ES6, 225 바이트

s=>`P1
30 90
`+([...`101${(f=(z,j)=>[...j].map(i=>`000${z[+i].toString(2)}`.slice(-7)).join``)([13,25,19,61,35,49,47,59,55,11],s[0])}01010${f([114,102,108,66,92,78,80,68,72,116],s[1])}101`].join` `+`
`).repeat(30).slice(0,-1)

ES7 기능이 더 짧을 수는 있지만 지원이 확실하지 않으므로 ES6을 고수하고 있습니다. 또한 입력을 배열로 가정합니다. 출력은 PBN 파일 입니다. 할 많은 골프가 있습니다.

내가 잘못했다면 의견을 남기고 수정해야합니다.


나는 당신에게 평균 PBM 파일 ... 생각
sergiol

2

펄, 153 바이트

substr($_=<>,6,0)=A;y/0-9A/=ICmSa_kg;0/;$s.=sprintf("%07b",-48+ord$1^($k++>6?127:0))while/(.)/g;$s=~s/0{7}/01010/;print"P1
95 30
".('101'.$s.'101'.$/)x30

barcode.perl 파일로 복사 한 후 다음과 같이 실행하십시오.

perl barcode.perl > output.pbm

그런 다음 바코드 번호를 입력하십시오.

설명:

바코드 숫자의 비트 패턴은 문자열로 저장되고 Perl y///음역 연산자를 사용하여 입력 숫자로 대체됩니다 . 대체 문자열의 각 값에는 인쇄 할 수없는 문자를 피하기 위해 48 (ASCII '0')이 추가되었습니다. 바코드 후반의 숫자는 전반의 숫자와 반대입니다.

중앙 패턴은 0000000 (다른 방법으로는 절대로 나타나지 않을 수 있고 'A'로 인코딩 된 다음 '0'으로 인코딩 된 패턴)으로 설정 한 다음 sprinting 시 특수한 길이로 다른 길이를 처리하지 않고 01010으로 대체 합니다.


1

옥타브, 115 바이트

function b(s)
n='rflB\MPDHt'-0;r=dec2bin(n(s-47)',7)'(:)-48;v=[a=[1 0 1] ~r(1:42)' 0 a r(43:84)' a];v(ones(30,1),:)

여러 줄 버전 :

function b(s)
   n='rflB\MPDHt'-0;
   r=dec2bin(n(s-47)',7)'(:)-48;
   v=[a=[1 0 1] ~r(1:42)' 0 a r(43:84)' a];
   v(ones(30,1),:)

n오른쪽 숫자 코드와 동등한 ASCII입니다 (모두 표시 가능한 문자이므로 왼쪽보다 입력하기가 더 쉽습니다). 그 후, 성가신 유형의 10 진수에서 이진으로의 변환은 char에서 숫자로 변경됩니다. v최종 바이너리 문자열을 빌드 한 다음 30 번 반복하고 콘솔에 출력합니다.

간결하게 표시된 30 개 행 중 2 개만있는 샘플 출력 :

s = '777777222222';
ans =

 Columns 1 through 30:

   1   0   1   0   1   1   1   0   1   1   0   1   1   1   0   1   1   0   1   1   1   0   1   1   0   1   1   1   0   1
   1   0   1   0   1   1   1   0   1   1   0   1   1   1   0   1   1   0   1   1   1   0   1   1   0   1   1   1   0   1
...

 Columns 31 through 60:

   1   0   1   1   1   0   1   1   0   1   1   1   0   1   1   0   1   0   1   1   1   0   1   1   0   0   1   1   0   1
   1   0   1   1   1   0   1   1   0   1   1   1   0   1   1   0   1   0   1   1   1   0   1   1   0   0   1   1   0   1
...

 Columns 61 through 90:

   1   0   0   1   1   0   1   1   0   0   1   1   0   1   1   0   0   1   1   0   1   1   0   0   1   1   0   1   1   0
   1   0   0   1   1   0   1   1   0   0   1   1   0   1   1   0   0   1   1   0   1   1   0   0   1   1   0   1   1   0
...

 Columns 91 through 94:

   0   1   0   1
   0   1   0   1
...

압축 출력 :

1010111011011101101110110111011011101101110110101110110011011001101100110110011011001101100101

원래 이미지를 표시하려고했지만 콘솔에 출력을 보내면 9 바이트가 절약되었습니다. 을 사용하여 결과를 표시 할 수 imshow있지만 1흰색과 0검은 색으로 표시 되므로 먼저 데이터를 반전시켜야합니다.

imshow(~v(ones(30,1),:));

1

코브라-218

do(s='')
    print'P1\n95 30'+('\n'+('101'+(for n in 12get Convert.toString(if((t=139+[2,14,8,50,24,38,36,48,44,0][s[n]to int-48])and n<6,t,~t),2)[-7:]+if(n-5,'','01010')).join('')+'101').toCharArray.join(' ')).repeat(30)

1

자바 스크립트 ES6, 199 바이트

n=>`P1 95 30 `+(101+(g=(a,...s)=>(``+1e12+n).slice(...s,-6).split``.map(m=>(1e3+a[m].toString(2)).slice(-7)).join``)(a=[13,25,19,61,35,49,47,59,55,11],-12)+`01010`+g(a.map(i=>~i&127))+101).repeat(30)

"가장 짧은 제출 (바이트 단위)". 코드를 바이트 단위로 계산해야하므로 유니 코드를 사용하는 경우 문자 당 2 바이트입니다.
mbomb007

바, 그래, 내 비 유니 코드 답변은 그보다 짧은 것 같아요
Dendrobium

0

파이썬 2, 174 바이트

골프를 칠 수 있다는 것을 알고 있습니다.

문자열 s은 문제의 이진 테이블이며 테이블의 왼쪽 절반은 문자열의 왼쪽 절반입니다. 오른쪽 절반에 있으면 값이 63으로 먼저 AND됩니다 (처음 1 제거). 인쇄 가능한 ASCII가되도록 63만큼 이동합니다.

BUG : 현재 버그를 수정하려고합니다. 첫 번째 예제의 출력은 바코드의 한 자리수만큼 꺼져 있습니다. 알아 내면 알려주세요.

I=raw_input()
s="LXR|bpnzvJcekA[MOCGs"
x="".join(format(ord(s[int(I[i])+10*(i>5)])-63|1+63*(i>5),'07b')for i in range(len(I)))
L=len(x)/2
print"101%s01010%s101"%(x[:L],x[L:])

또는 나는 도전을 완전히 잘못했다. 이 경우에도 알려주십시오.
mbomb007
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.