高尔夫代码:Code 39 条形码
-
25-09-2019 - |
题
挑战
按字符数计算的最短代码,用于绘制 Code 39 条形码的 ASCII 表示形式。
维基百科关于 Code 39 的文章: http://en.wikipedia.org/wiki/Code_39
输入
输入将是 Code 39 条形码的合法字符字符串。这意味着 43 个字符有效: 0
-9
A
-Z
(空间)和
-.$/+%
. 。这 *
字符不会出现在输入中,因为它用作开始和结束字符。
输出
Code 39 条形码中编码的每个字符都有九个元素、五个条和四个空格。条形将表示为 #
字符,空格将用空格字符表示。九个元素中的三个将是宽的。窄元素的宽度为 1 个字符,宽元素的宽度为 3 个字符。每个字符模式之间应添加单个空格的字符间空格。应重复该图案,以使条形码的高度为八个字符高。
开始/结束字符 *
(bWbwBwBwb) 将表示如下:
# # ### ### #
# # ### ### #
# # ### ### #
# # ### ### #
# # ### ### #
# # ### ### #
# # ### ### #
# # ### ### #
^ ^ ^^ ^ ^ ^ ^^^
| | || | | | |||
narrow bar -+ | || | | | |||
wide space ---+ || | | | |||
narrow bar -----+| | | | |||
narrow space ------+ | | | |||
wide bar --------+ | | |||
narrow space ----------+ | |||
wide bar ------------+ |||
narrow space --------------+||
narrow bar ---------------+|
inter-character space ----------------+
- 开始和结束字符
*
需要在条形码的开头和结尾输出。 - 条形码之前或之后不需要包含任何安静空间。
- 不需要计算校验位。
- 不需要完整的 ASCII Code39 编码,只需标准的 43 个字符即可。
- 无需在 ASCII 条形码表示法下方打印任何文本来识别输出内容。
- 人物
#
如果需要,可以用另一个更高密度的字符替换。使用完整块字符 U+2588,将允许条形码在打印时实际扫描。
测试用例
Input:
ABC
Output:
# # ### ### # ### # # # ### # ### # # ### ### ### # # # # # ### ### #
# # ### ### # ### # # # ### # ### # # ### ### ### # # # # # ### ### #
# # ### ### # ### # # # ### # ### # # ### ### ### # # # # # ### ### #
# # ### ### # ### # # # ### # ### # # ### ### ### # # # # # ### ### #
# # ### ### # ### # # # ### # ### # # ### ### ### # # # # # ### ### #
# # ### ### # ### # # # ### # ### # # ### ### ### # # # # # ### ### #
# # ### ### # ### # # # ### # ### # # ### ### ### # # # # # ### ### #
# # ### ### # ### # # # ### # ### # # ### ### ### # # # # # ### ### #
Input:
1/3
Output:
# # ### ### # ### # # # ### # # # # # ### ### # # # # # ### ### #
# # ### ### # ### # # # ### # # # # # ### ### # # # # # ### ### #
# # ### ### # ### # # # ### # # # # # ### ### # # # # # ### ### #
# # ### ### # ### # # # ### # # # # # ### ### # # # # # ### ### #
# # ### ### # ### # # # ### # # # # # ### ### # # # # # ### ### #
# # ### ### # ### # # # ### # # # # # ### ### # # # # # ### ### #
# # ### ### # ### # # # ### # # # # # ### ### # # # # # ### ### #
# # ### ### # ### # # # ### # # # # # ### ### # # # # # ### ### #
Input:
- $ (minus space dollar)
Output:
# # ### ### # # # # ### ### # ### # ### # # # # # # # # ### ### #
# # ### ### # # # # ### ### # ### # ### # # # # # # # # ### ### #
# # ### ### # # # # ### ### # ### # ### # # # # # # # # ### ### #
# # ### ### # # # # ### ### # ### # ### # # # # # # # # ### ### #
# # ### ### # # # # ### ### # ### # ### # # # # # # # # ### ### #
# # ### ### # # # # ### ### # ### # ### # # # # # # # # ### ### #
# # ### ### # # # # ### ### # ### # ### # # # # # # # # ### ### #
# # ### ### # # # # ### ### # ### # ### # # # # # # # # ### ### #
代码计数包括输入/输出(完整程序)。
解决方案
J,102个字符
8#,:' #'{~,0,.~#:(3 u:'䝝啕啕啕䑅儑啕啕啕啕䗝䔑啕䕷煝䑑凝瑗屗眕凗瑵屵具瑝屝啕啕啕啕啕啕啕甗崗睅圗病巅呷甝崝圝畇嵇睑均痑巑嗇畱嵱坱煗䝗燕䗗煵䝵'){~32-~a.i.'*'(,,[)
解释。从下往上读:
8#,: NB. Copy 8 times
' #'{~ NB. Turn binary 0 and 1 into space and #
, NB. Link the array into a list
0,.~ NB. Append a 0 to the end of each row of the array.
#: NB. Turn the list of numbers into a binary array where each row is the base-2 representation of the corresponding number
(3 u:'䝝啕啕啕䑅儑啕啕啕啕䗝䔑啕䕷煝䑑凝瑗屗眕凗瑵屵具瑝屝啕啕啕啕啕啕啕甗崗睅圗病巅呷甝崝圝畇嵇睑均痑巑嗇畱嵱坱煗䝗燕䗗煵䝵') NB. Turn this wchar string into a list of ints in range 0-65535.
{~ NB. Select numbers from the string-list whose indices are...
32-~ NB. ... 32 less than ...
a.i. NB. ... the ascii values of ...
'*'(,,[) NB. ... the input string with a '*' on either side!
其他提示
红宝石 (1.9) - 121 132 141 166 170 289 295
向大卫致敬
puts"*#{$_}*
".tr(" --9*$+%A-Z","䝝䕷煝䑑凝瑗屗眕凗瑵屵具瑝屝䗝䑅䔑儑甗崗睅圗病巅呷甝崝圝畇嵇睑均痑巑嗇畱嵱坱煗䝗燕䗗煵䝵").gsub(/./){|c|c.ord.to_s(2).tr"01"," #"}*8
echo "ABC" | ruby -ne 'puts"*#{$_}*
".tr(" --9*$+%A-Z","䝝䕷煝䑑凝瑗屗眕凗瑵屵具瑝屝䗝䑅䔑儑甗崗睅圗病巅呷甝崝圝畇嵇睑均痑巑嗇畱嵱坱煗䝗燕䗗煵䝵").gsub(/./){|c|c.ord.to_s(2).tr"01"," #"}*8'
只存储所需的 44 个字符,并使用 Ruby 的音译函数来映射这些字符
<space>
<-> to <9>
<*>
<$>
<+>
<%>
<A> to <Z>
到编码值。
Python,304 个字符
没有花哨的 Unicode 压缩。唯一的技巧是重新排列字符以最大化重叠。我的第一个 Python 程序。
b="BWbwbwBwbWBwbwbwBWbwBwbwbWBwbwBwbWbwBwbwBWbwbwBWBwbwbwbWBwBwbwbWbwBwBwbWbwbwBwBWbwbwbwBWBwbWbWbWbwbWbWbWb"
s=t=""
for x in"*"+raw_input()+"*":
i=".NI5VRD9YLH4 OB8XSE2?J6WKG0ZMA7*PC1-TF3UQ????$/+%".find(x)*2
s+=b[i:i+9]+"w"
for x in s:t+=["#"," ","###"," "]["bwBW".find(x)]
for k in b[-8:]:print(t)
汇编器
汇编为 220 字节。
mov di,ds
mov al,42
call a3
mov dh,[80h]
mov si,82h
a1:lodsb
call a3
dec dh
jnz a1
mov al,42
call a3
mov ax,2573
stosw
mov al,36
stosb
mov cl,8
a2:mov dx,ds
mov ah,9
int 21h
loop a2
a3:sub al,97
cmp al,26
ja a4
sub al,32
a4:mov bx,a6-3
a8:add bx,3
cmp bx,a7
jae ret
cmp al,[bx]
jne a8
mov bp,[bx+1]
a5:rcr bp,1
mov al,36
sbb al,0
and al,35
stosb
or bp,bp
jnz a5
mov al,32
stosb
ret
a6:dd 0D05DC5CFh,01DD17517h,05477D275h,0D475C5D3h,01DD55717h,07745D657h,0D85D17D7h,057E05D1Dh
dd 0745DE174h,0E35177E2h,0D7E47475h,051DDE551h,0E77715E6h,05DE85C57h,05C75E95Ch,0EB7157EAh
dd 077EC715Dh,07175ED45h,0EF45D7EEh,0D5F045DDh,04757F171h,0F3475DF2h,047F44775h,07571F575h
dd 0F755C7F6h,047F875D1h,05771F957h,0CD7751CCh,071BF5D47h,05111C35Dh,0CA4511CEh,045C44451h
dd 05DD1C944h
a7:
这里没有太多发挥巧妙技巧的余地。
Python 3.1,无 Unicode (213 215 223 240 248 249 字符)
o=""
for c in"%r"%input():
u="W3YZ56C$EF. 89'0HIJM/OP+%RSTUV12X4ABD-7GKLNQ".find(c);n=sum(b"))&&&,(*&2&&&)),&/8(*&1)<&/V&&&)),&/5);D&/S"[u:])-930+35*u
while n:o+="###"[n%2*2:]+" "[n&2:];n>>=2
print((o+"\n")*8)
解释:
代码 39 序列被编码为基数 4 的数字(最左边 = 最低有效值):
bw
→ 3Bw
→ 2bW
→ 1BW
→ 0
然后对序列进行排序,例如
20333 Q
21233 N
21323 L
...
获取相邻条目的差异,给出如下列表 [48, 12, 3, …]
. 。然后 35
添加到此列表中以确保数字落在 ASCII 范围内。这给出了 "))&&&,…"
细绳。
该代码还利用了 *
不会出现在输入中,因此我们可以将其替换为任何无效字符,包括 '
. 。在 CPython 中 repr("ABC") == "'ABC'"
, ,这样我们就可以去掉 2 个字符。
Python 3.1,带有 Unicode (154 158 字符)
基于 J解, 利用 “人物 #
如果需要的话可以用另一个更高密度的角色替换” 规则,将密度定义为 深色部分的面积除以字形的最小边界矩形. :)
print((''.join(" #"[int(c)]for d in"%r"%input()for c in bin(2*ord("䝝啕啕啕䑅儑啕䗝啕啕啕䔑啕䕷煝䑑凝瑗屗眕凗瑵屵具瑝屝啕啕啕啕啕啕啕甗崗睅圗病巅呷甝崝圝畇嵇睑均痑巑嗇畱嵱坱煗䝗燕䗗煵䝵"[ord(d)-32]))[2:])+"\n")*8)
Python (2.6) -- 430 312 302 个字符
第三看问题,还有改进的空间。字符计数 wc -m
.
#coding:UTF8
k=""
for c in"*%s*"%raw_input():
i=" $*.02468BDFHJLNPRTVXZ%+-/13579ACEGIKMOQSUWY".find(c)*2
for j in"%05d%s"%tuple(map(ord,u"ಊҺூҺ姢ҺЈҺӎϴЈϴӐϲ刦ҺҺϴҼூ划ಊϴಊҺЈϴЈҼІ划ӎϴӎಊϴϴಌϲІூூҼІ刦ϴ勮ϲ刨ϲІҼӎҺ划勚ூ刔ூϲಌҺಊ划Ј勚І刔ІϲӐҺӎ姢ϴ媪ϲ姤ϲ"[i:i+2])):k+=["#"," ","###"," "][int(j)]
k+=" "
exec"print k;"*8
Lua,318 个字符
z={"1358ACEHKMORUWY.","UVWXYZ-. $/+*","2369BCFILMPSVWZ ","0123456789$/%","0456DEFJNOPTXYZ*","ABCDEFGHIJ$+%","0789GHIJQRST-. *","KLMNOPQRST/+%","1247ABDGKLNQUVX-",""}i="*"..(...).."*"o=""for c in i:gfind(".")do for j=1,10 do o=o..((j%2==0 and" "or"#"):rep(z[j]:find(c,1,true)and 3 or 1))end end for j=1,8 do print(o)end
我不希望用 Lua 赢得任何代码高尔夫问题,所以在这里回答我自己的挑战我并不感到难过。它还使用了一种不同的编码,我认为其他人可能会感兴趣。
其他观察结果
仔细观察编码后,似乎有一种方法可以省去查表,直接计算条形码的编码。然而,我发现我尝试构建计算所花费的代码比表更多。(其他语言可能并非如此。)
将字符分组以指示宽条和空格的位置后,我看到了一些有趣的模式。看起来只有一个宽阔的空间可以容纳40个角色, $/+%
例外(每个字符都有 3 个空格。)40 个字符在每个槽中被分成 10 个。并且,同样的 40 个字符有两个宽条。宽条似乎具有二进制编码,最后一个条是奇偶校验位。该条的位模式为 1、2、3、4、5、6、8、9、10、12,其中避免设置多于 2 位的数字。
1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ-._* 1 3 5 8 A C E H K M O R U W Y . 1010100100 23 6 9 BC F I LM P S VW Z _ 0110010010 456 0 DEF J NOP T XYZ * 0001110001 7890 GHIJ QRST -._* 0000001111 12 4 7 AB D G KL N Q UV X - 1101001000 --> Parity
我想,看看是否可以在没有查找表的情况下对条形码进行编码,这将是另一天的挑战。
我已经编写了在嵌入式系统上使用代码 39 条形码的代码。代码有两种风格,我认为是 39 个“常规”代码和 4 个“奇怪”代码。常规代码具有十种条宽模式之一(二宽三窄)和四种空白宽度模式之一(一宽三窄)。奇怪的东西有五个窄条和四种条宽模式之一(三宽一窄)。要使用紧凑代码呈现条形码,请将字符转换为数字 0-39(对于普通代码),或者对于“oddballs”,将字符转换为 40、50、60 或 70。然后divmod 10。高位数字将选择八种间隔宽度模式之一;如果上位数字为 3 或更少,则下位数字将选择十种条形宽度模式之一。如果上面的数字是 4-7,那么所有五个条形都应该是窄的。
该代码使用一些小的查找表非常紧凑地工作。因为查找表可以在源代码中紧凑地表示为字符串,所以具有较大查找表的方法可能具有较短的源代码(尽管我认为对于 Code Golf 源代码大小应该使用最有利的编码以字节为单位计算;一种使用 UTF-8 存储三个字节、UTF-16 存储两个字节的奇怪字符字符串的方法,应该为每个奇怪字符“充电”3 个字节,或者为所有字符每个“充电”两个字节,以产生较小的总数)。使用完全适合某些特定单字节代码页的一系列奇怪字符的方法应按每个字符一个字节收费。
垃圾邮件 垃圾邮件 垃圾邮件 垃圾邮件 可爱的垃圾邮件