条码高尔夫:生成号码的UPC


12

如今,几乎每家商店都使用通用产品代码(UPC)条形码来简化结帐流程。如果这个名称对您没有任何意义,那么您肯定会知道它们的外观:

样品UPC-A条码

格式

最常见的系统是UPC-A,它使用12位数字表示每个特定产品。每个数字被编码为一系列黑白条纹,以使机器可以读取代码,长度为7位。总共有11位的模式值指示条形码的开始,中间和结尾。条形码的总长度为12×7 + 11 = 95位。(从现在开始,当使用二进制表示每个位的颜色时,它0是白色和1黑色。)

开头和结尾都有的模式101。然后将这些数字分为2组,每组6个,并按如下所示进行编码,并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或命令行获取输入,或编写一个接受字符串或整数的函数(请注意,输入可以包含前导零,并且大多数语言都将其删除或将数字转换为八进制)。
  • 通过以下方式之一输出图像:
    • 将其保存到具有您选择的名称和格式(PNG,PBM等)的文件中。
    • 在屏幕上显示。
    • 将其文件数据输出到stdout。
  • 尽管您可能使用图像或图形库,但是您可能不使用会生成条形码的库或内置程序(我正在看着您,Mathematica)。
  • UPC的最后一位通常是一个校验位,但是出于这些目的,您不必担心。

例子

这里有一些更多的示例可用来测试您的代码。为了方便起见,还提供了二进制输出。

输入: 012345678910

输出:

10100011010011001001001101111010100011011000101010101000010001001001000111010011001101110010101

输入: 777777222222

输出:

10101110110111011011101101110110111011011101101010110110011011001101100110110011011001101100101

计分

这是代码高尔夫,因此提交时间最短(以字节为单位)。Tiebreaker去最早的职位。


嗯...多汁的水果。
丹尼斯

输入可以作为数组输入吗?例如["777777","222222"]
Downgoat

@vihan Hmm,我认为这有点麻烦。我要说不。
NinjaBearMonkey

2
首次扫描UPC条码!
丹尼斯

1
太好了 条形码一直让我着迷
β衰变

Answers:


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个,总共90个。

如果可以接受,这将使条形码远离原点,如下所示:

在此处输入图片说明

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并且必须全部在一行上完成。在非高尔夫版本中,它分三个步骤完成。在高尔夫版本中,最后两个步骤组合成一个巨大的表情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

JavaScript 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

Perl,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”),然后替换为01010,而不是在处理sprinting 时将其不同长度作为特殊情况处理。


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等效于右侧数字代码(它们比左侧更容易输入,因为它们都是可显示的字符)。在那之后,带有一些烦人的类型的直接十进制到二进制的转换从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

Javascript 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)

“最短的提交(以字节为单位)”。您需要以字节为单位计算代码,因此,我认为如果使用Unicode,则每个字符2个字节。
mbomb007

Bah,是的,我想我的未编码答案要短一些
Dendrobium

0

Python 2,174字节

我知道它可以打高尔夫球。

该字符串s是问题中的二进制表,该表的左半部分作为字符串的左半部分。如果在右半部分,则将这些值与63进行“与”运算(先删除1),然后将其移位63以显示可打印的ASCII。

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.