Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

2
Task/UPC/00-META.yaml Normal file
View file

@ -0,0 +1,2 @@
---
from: http://rosettacode.org/wiki/UPC

73
Task/UPC/00-TASK.txt Normal file
View file

@ -0,0 +1,73 @@
;Goal:
Convert UPC bar codes to decimal.
Specifically:
The [[wp:Universal_Product_Code|UPC]] standard is actually a collection of standards -- physical standards, data format standards, product reference standards...
Here,   in this task,   we will focus on some of the data format standards,   with an imaginary physical+electrical implementation which converts physical UPC bar codes to ASCII   (with spaces and   '''#'''   characters representing the presence or absence of ink).
;Sample input:
Below, we have a representation of ten different UPC-A bar codes read by our imaginary bar code reader:
<pre>
# # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # #
# # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # #
# # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # #
# # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # #
# # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # #
# # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # #
# # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # #
# # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # #
# # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # #
# # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # #
</pre>
Some of these were entered upside down, &nbsp; and one entry has a timing error.
;Task:
Implement code to find the corresponding decimal representation of each, rejecting the error.
Extra credit for handling the rows entered upside down &nbsp; (the other option is to reject them).
;Notes:
Each digit is represented by 7 bits:
<pre>
0: 0 0 0 1 1 0 1
1: 0 0 1 1 0 0 1
2: 0 0 1 0 0 1 1
3: 0 1 1 1 1 0 1
4: 0 1 0 0 0 1 1
5: 0 1 1 0 0 0 1
6: 0 1 0 1 1 1 1
7: 0 1 1 1 0 1 1
8: 0 1 1 0 1 1 1
9: 0 0 0 1 0 1 1
</pre>
On the left hand side of the bar code a space represents a '''0''' and a '''#''' represents a '''1'''.
<br>On the right hand side of the bar code, a '''#''' represents a '''0''' and a space represents a '''1'''
<br>Alternatively (for the above): &nbsp; spaces always represent zeros and '''#''' characters always represent ones, but the representation is logically negated -- '''1'''s and '''0'''s are flipped -- on the right hand side of the bar code.
;The UPC-A bar code structure:
::* &nbsp; It begins with at least 9 spaces &nbsp; (which our imaginary bar code reader unfortunately doesn't always reproduce properly),
::* &nbsp; then has a &nbsp; &nbsp; ''' # # ''' &nbsp; &nbsp; sequence marking the start of the sequence,
::* &nbsp; then has the six "left hand" digits,
::* &nbsp; then has a &nbsp; ''' # # ''' &nbsp; sequence in the middle,
::* &nbsp; then has the six "right hand digits",
::* &nbsp; then has another &nbsp; ''' # # ''' &nbsp; (end sequence), &nbsp; and finally,
::* &nbsp; then ends with nine trailing spaces &nbsp; (which might be eaten by wiki edits, and in any event, were not quite captured correctly by our imaginary bar code reader).
Finally, the last digit is a checksum digit which may be used to help detect errors.
;Verification:
Multiply each digit in the represented 12 digit sequence by the corresponding number in &nbsp; (3,1,3,1,3,1,3,1,3,1,3,1) &nbsp; and add the products.
The sum (mod 10) must be '''0''' &nbsp; (must have a zero as its last digit) &nbsp; if the UPC number has been read correctly.
<br><br>

95
Task/UPC/11l/upc.11l Normal file
View file

@ -0,0 +1,95 @@
V LEFT_DIGITS = [
## # = 0,
## # = 1,
# ## = 2,
#### # = 3,
# ## = 4,
## # = 5,
# #### = 6,
### ## = 7,
## ### = 8,
# ## = 9
]
V RIGHT_DIGITS = Dict(LEFT_DIGITS.items(), (k, v) -> (k.replace( , s).replace(#, ).replace(s, #), v))
V END_SENTINEL = # #
V MID_SENTINEL = # #
F decodeUPC(input)
F decode(candidate)
V pos = 0
V part = candidate[pos .+ :END_SENTINEL.len]
I part == :END_SENTINEL
pos += :END_SENTINEL.len
E
R (0B, [Int]())
[Int] output
L 6
part = candidate[pos .+ 7]
pos += 7
I part C :LEFT_DIGITS
output [+]= :LEFT_DIGITS[part]
E
R (0B, output)
part = candidate[pos .+ :MID_SENTINEL.len]
I part == :MID_SENTINEL
pos += :MID_SENTINEL.len
E
R (0B, output)
L 6
part = candidate[pos .+ 7]
pos += 7
I part C :RIGHT_DIGITS
output [+]= :RIGHT_DIGITS[part]
E
R (0B, output)
part = candidate[pos .+ :END_SENTINEL.len]
I part == :END_SENTINEL
pos += :END_SENTINEL.len
E
R (0B, output)
V sum = 0
L(v) output
I L.index % 2 == 0
sum += 3 * v
E
sum += v
R (sum % 10 == 0, output)
V candidate = input.trim( )
V out = decode(candidate)
I out[0]
print(out[1])
E
out = decode(reversed(candidate))
I out[0]
print(out[1] Upside down)
E
I out[1].len == 12
print(Invalid checksum)
E
print(Invalid digit(s))
V barcodes = [
# # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ,
# # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ,
# # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ,
# # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ,
# # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ,
# # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ,
# # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ,
# # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ,
# # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ,
# # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # #
]
L(barcode) barcodes
decodeUPC(barcode)

227
Task/UPC/ALGOL-68/upc.alg Normal file
View file

@ -0,0 +1,227 @@
BEGIN
# number of digits encoded by UPC #
INT upc digits = 12;
# MODE to hold UPC bar code parse results #
MODE UPC = STRUCT( BOOL valid # TRUE if the UPC was valid, #
# FASLE otherwise #
, [ 1 : upc digits ]INT digits
# the digits encoded by the #
# UPC if it was valid #
, BOOL inverted # TRUE if the code was scanned #
# upside down, FALSE if it was #
# right-side up #
, STRING error message # erro rmessage if the string #
# was invalid #
);
# parses the UPC string s and returns a UPC containing the results #
PROC parse upc = ( STRING s )UPC:
BEGIN
# returns TRUE if we are at the end of s, FALSE otherwise #
PROC at end = BOOL: s pos > UPB s;
# counts and skips spaces in s #
PROC skip spaces = INT:
BEGIN
INT spaces := 0;
WHILE IF at end THEN FALSE ELSE s[ s pos ] = " " FI DO
spaces +:= 1;
s pos +:= 1
OD;
spaces
END; # skip spaces #
# skips over the next number of bits characters of s and returns #
# a bit representation ( space = 0, anything else = 1 ) #
PROC get value = ( INT number of bits )BITS:
BEGIN
BITS value := 2r0;
FOR b TO number of bits WHILE NOT at end DO
value := ( value SHL 1 ) OR IF s[ s pos ] = " " THEN 2r0 ELSE 2r1 FI;
s pos +:= 1
OD;
value
END; # get value #
# the representations of the digits #
[]BITS representations = ( 2r 0 0 0 1 1 0 1 # 0 #
, 2r 0 0 1 1 0 0 1 # 1 #
, 2r 0 0 1 0 0 1 1 # 2 #
, 2r 0 1 1 1 1 0 1 # 3 #
, 2r 0 1 0 0 0 1 1 # 4 #
, 2r 0 1 1 0 0 0 1 # 5 #
, 2r 0 1 0 1 1 1 1 # 6 #
, 2r 0 1 1 1 0 1 1 # 7 #
, 2r 0 1 1 0 1 1 1 # 8 #
, 2r 0 0 0 1 0 1 1 # 9 #
);
[]BITS reversed digits = ( 2r 0 1 0 0 1 1 1 # 0 #
, 2r 0 1 1 0 0 1 1 # 1 #
, 2r 0 0 1 1 0 1 1 # 2 #
, 2r 0 1 0 0 0 0 1 # 3 #
, 2r 0 0 1 1 1 0 1 # 4 #
, 2r 0 1 1 1 0 0 1 # 5 #
, 2r 0 0 0 0 1 0 1 # 6 #
, 2r 0 0 1 0 0 0 1 # 7 #
, 2r 0 0 0 1 0 0 1 # 8 #
, 2r 0 0 1 0 1 1 1 # 9 #
);
# number of digits in the left and right sides of the UPC #
INT digits per side = upc digits OVER 2;
UPC result;
FOR d TO upc digits DO ( digits OF result )[ d ] := 0 OD;
inverted OF result := FALSE;
error message OF result := "unknown error";
valid OF result := FALSE;
INT s pos := LWB s;
IF skip spaces < 6 # should be 9 but we are being tolerant #
THEN
# insufficient leading spaces #
error message OF result := "missing leading spaces"
ELIF get value( 3 ) /= 2r101 THEN
# no start #
error message OF result := "missing start sequence"
ELSE
# ok so far - should now have six digits, each encoded in #
# seven bits #
# note we store the digits as 1..10 if the are right-sid up #
# and -1..-10 if they are inverted, so we can distinguish #
# right-side up 0 and inverted 0 #
# the digits are corrected to be 0..9 later #
BOOL valid digits := TRUE;
FOR d TO digits per side WHILE valid digits DO
BITS code = get value( 7 );
BOOL found digit := FALSE;
FOR d pos TO UPB representations WHILE NOT found digit DO
IF code = representations[ d pos ] THEN
# found a "normal" digit #
found digit := TRUE;
( digits OF result )[ d ] := d pos
ELIF code = reversed digits[ d pos ] THEN
# found a reversed digit #
found digit := TRUE;
inverted OF result := TRUE;
( digits OF result )[ d ] := - d pos
FI
OD;
IF NOT found digit THEN
# have an invalid digit #
error message OF result := "invalid digit " + whole( d, 0 );
valid digits := FALSE
FI
OD;
IF NOT valid digits THEN
# had an error #
SKIP
ELIF get value( 5 ) /= 2r01010 THEN
# no middle separator #
error message OF result := "missing middle sequence"
ELSE
# should now have 6 negated digits #
FOR d FROM digits per side + 1 TO upc digits WHILE valid digits DO
BITS code = NOT get value( 7 ) AND 16r7f;
BOOL found digit := FALSE;
FOR d pos TO UPB representations WHILE NOT found digit DO
IF code = representations[ d pos ] THEN
# found a normal negated digit #
found digit := TRUE;
( digits OF result )[ d ] := d pos
ELIF code = reversed digits[ d pos ] THEN
# found reversed negated digit #
found digit := TRUE;
inverted OF result := TRUE;
( digits OF result )[ d ] := - d pos
FI
OD;
IF NOT found digit THEN
# have an invalid digit #
error message OF result := "invalid digit " + whole( d, 0 );
valid digits := FALSE
FI
OD;
IF NOT valid digits THEN
# had an error #
SKIP
ELIF get value( 3 ) /= 2r101 THEN
# no end sequence #
error message OF result := "missing end sequence"
ELIF skip spaces < 6 # should be 9 but we are being #
# tolerant #
THEN
# insufficient trailing spaces #
error message OF result := "insufficient trailing spaces"
ELIF NOT at end THEN
# extraneous stuff after the trailing spaces #
error message OF result := "unexpected trailing bits"
ELSE
# valid so far - if there were reversed digits, #
# check they were all reversed #
# and correct the digits to be in 0..9 #
BOOL all reversed := TRUE;
FOR d TO upc digits DO
IF ( digits OF result )[ d ] < 0 THEN
# reversd digit #
( digits OF result )[ d ] := ABS ( digits OF result )[ d ] - 1
ELSE
# normal digit #
( digits OF result )[ d ] -:= 1;
all reversed := FALSE
FI
OD;
IF inverted OF result AND NOT all reversed
THEN
# had a mixture of inverted and non-inverted #
# digits #
error message OF result := "some reversed digits found"
ELSE
# the code appears valid - check the check sum #
IF inverted OF result THEN
# the code was reversed - reverse the digits #
FOR d TO digits per side DO
INT right digit
= ( digits OF result )[ ( upc digits + 1 ) - d ];
( digits OF result )[ ( upc digits + 1 ) - d ]
:= ( digits OF result )[ d ];
( digits OF result )[ d ] := right digit
OD
FI;
INT check sum := 0;
FOR d FROM 1 BY 2 TO upc digits DO check sum +:= 3 * ( digits OF result )[ d ] OD;
FOR d FROM 2 BY 2 TO upc digits DO check sum +:= ( digits OF result )[ d ] OD;
IF check sum MOD 10 /= 0 THEN
# invalid check digit #
error message OF result := "incorrect check digit"
ELSE
# the UPC code appears valid #
valid OF result := TRUE
FI
FI
FI
FI
FI;
result
END; # parse upc #
# task test cases #
[]STRING tests =
( " # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # "
, " # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # "
, " # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # "
, " # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # "
, " # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # "
, " # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # "
, " # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # "
, " # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # "
, " # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # "
, " # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # "
);
FOR t pos FROM LWB tests TO UPB tests DO
UPC code = parse upc( tests[ t pos ] );
print( ( whole( t pos, -2 ), ":" ) );
IF NOT valid OF code THEN
# invalid UPC code #
print( ( " error: ", error message OF code, newline ) )
ELSE
# valid code #
FOR d TO upc digits - 1 DO print( ( whole( ( digits OF code )[ d ], -2 ) ) ) OD;
print( ( " valid" ) );
IF inverted OF code THEN print( ( " (inverted)" ) ) FI;
print( ( newline ) )
FI
OD
END

69
Task/UPC/AWK/upc.awk Normal file
View file

@ -0,0 +1,69 @@
# syntax: GAWK -f UPC.AWK
BEGIN {
ls_arr[" ## #"] = 0
ls_arr[" ## #"] = 1
ls_arr[" # ##"] = 2
ls_arr[" #### #"] = 3
ls_arr[" # ##"] = 4
ls_arr[" ## #"] = 5
ls_arr[" # ####"] = 6
ls_arr[" ### ##"] = 7
ls_arr[" ## ###"] = 8
ls_arr[" # ##"] = 9
for (i in ls_arr) {
tmp = i
gsub(/#/,"x",tmp)
gsub(/ /,"#",tmp)
gsub(/x/," ",tmp)
rs_arr[tmp] = ls_arr[i]
}
split("3,1,3,1,3,1,3,1,3,1,3,1",weight_arr,",")
bc_arr[++n] = " # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # "
bc_arr[++n] = " # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # "
bc_arr[++n] = " # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # "
bc_arr[++n] = " # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # "
bc_arr[++n] = " # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # "
bc_arr[++n] = " # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # "
bc_arr[++n] = " # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # "
bc_arr[++n] = " # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # "
bc_arr[++n] = " # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # "
bc_arr[++n] = " # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # "
bc_arr[++n] = " # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### #" # NG
tmp = "123456712345671234567123456712345671234567"
printf("%2s: %-18s---%s-----%s---\n","N","UPC-A",tmp,tmp) # heading
for (i=1; i<=n; i++) {
# accept any number of spaces at beginning or end; I.E. minimum of 9 is not enforced
sub(/^ +/,"",bc_arr[i])
sub(/ +$/,"",bc_arr[i])
bc = bc_arr[i]
if (length(bc) == 95 && substr(bc,1,3) == "# #" && substr(bc,46,5) == " # # " && substr(bc,93,3) == "# #") {
upc = ""
sum = upc_build(ls_arr,1,substr(bc,4,42))
sum += upc_build(rs_arr,7,substr(bc,51,42))
if (upc ~ /^x+$/) { msg = "reversed" }
else if (upc ~ /x/) { msg = "invalid digit(s)" }
else if (sum % 10 != 0) { msg = "bad check digit" }
else { msg = upc }
}
else {
msg = "invalid format"
}
printf("%2d: %-18s%s\n",i,msg,bc)
}
exit(0)
}
function upc_build(arr,pos,bc, i,s,sum) {
pos--
for (i=1; i<=42; i+=7) {
s = substr(bc,i,7)
pos++
if (s in arr) {
upc = upc arr[s]
sum += arr[s] * weight_arr[pos]
}
else {
upc = upc "x"
}
}
return(sum)
}

170
Task/UPC/Action-/upc.action Normal file
View file

@ -0,0 +1,170 @@
DEFINE PTR="CARD"
DEFINE RESOK="255"
DEFINE RESUPSIDEDOWN="254"
DEFINE RESINVALID="253"
DEFINE DIGITCOUNT="12"
DEFINE DIGITLEN="7"
PTR ARRAY ldigits(10),rdigits(10)
CHAR ARRAY marker="# #",midmarker=" # # "
PROC Init()
ldigits(0)=" ## #" ldigits(1)=" ## #"
ldigits(2)=" # ##" ldigits(3)=" #### #"
ldigits(4)=" # ##" ldigits(5)=" ## #"
ldigits(6)=" # ####" ldigits(7)=" ### ##"
ldigits(8)=" ## ###" ldigits(9)=" # ##"
rdigits(0)="### # " rdigits(1)="## ## "
rdigits(2)="## ## " rdigits(3)="# # "
rdigits(4)="# ### " rdigits(5)="# ### "
rdigits(6)="# # " rdigits(7)="# # "
rdigits(8)="# # " rdigits(9)="### # "
RETURN
BYTE FUNC DecodeMarker(CHAR ARRAY s BYTE POINTER pos CHAR ARRAY marker)
CHAR ARRAY tmp(6)
BYTE x
x=pos^+marker(0)
IF x>s(0) THEN
RETURN (RESINVALID)
ELSE
SCopyS(tmp,s,pos^,pos^+marker(0)-1)
pos^==+marker(0)
IF SCompare(tmp,marker)#0 THEN
RETURN (RESINVALID)
FI
FI
RETURN (RESOK)
BYTE FUNC DecodeDigit(CHAR ARRAY s BYTE POINTER pos PTR ARRAY digits)
CHAR ARRAY tmp(DIGITLEN+1)
BYTE i,x
x=pos^+DIGITLEN
IF x>s(0) THEN
RETURN (RESINVALID)
ELSE
SCopyS(tmp,s,pos^,pos^+DIGITLEN-1)
pos^==+DIGITLEN
FOR i=0 TO 9
DO
IF SCompare(tmp,digits(i))=0 THEN
RETURN (i)
FI
OD
FI
RETURN (RESINVALID)
BYTE FUNC Validation(BYTE ARRAY code)
BYTE ARRAY mult=[3 1 3 1 3 1 3 1 3 1 3 1]
BYTE i
INT sum
sum=0
FOR i=0 TO DIGITCOUNT-1
DO
sum==+code(i)*mult(i)
OD
IF sum MOD 10=0 THEN
RETURN (RESOK)
FI
RETURN (RESINVALID)
BYTE FUNC DecodeInternal(CHAR ARRAY s BYTE ARRAY code)
BYTE res,pos,i
pos=1
WHILE pos<=s(0) AND s(pos)=32
DO pos==+1 OD
res=DecodeMarker(s,@pos,marker)
IF res=RESINVALID THEN RETURN (res) FI
FOR i=0 TO 5
DO
res=DecodeDigit(s,@pos,ldigits)
IF res=RESINVALID THEN RETURN (res) FI
code(i)=res
OD
res=DecodeMarker(s,@pos,midmarker)
IF res=RESINVALID THEN RETURN (res) FI
FOR i=6 TO 11
DO
res=DecodeDigit(s,@pos,rdigits)
IF res=RESINVALID THEN RETURN (res) FI
code(i)=res
OD
res=DecodeMarker(s,@pos,marker)
IF res=RESINVALID THEN RETURN (res) FI
res=Validation(code)
RETURN (res)
PROC Reverse(CHAR ARRAY src,dst)
BYTE i,j
i=1 j=src(0) dst(0)=j
WHILE j>0
DO
dst(j)=src(i)
i==+1 j==-1
OD
RETURN
BYTE FUNC Decode(CHAR ARRAY s BYTE ARRAY code)
CHAR ARRAY tmp(256)
BYTE res
res=DecodeInternal(s,code)
IF res=RESOK THEN RETURN (res) FI
Reverse(s,tmp)
res=DecodeInternal(tmp,code)
IF res=RESINVALID THEN RETURN (res) FI
RETURN (RESUPSIDEDOWN)
PROC Test(BYTE id CHAR ARRAY s)
BYTE ARRAY code(DIGITCOUNT)
BYTE res,i
res=Decode(s,code)
IF id<10 THEN Put(32) FI
PrintF("%B: ",id)
IF res=RESINVALID THEN
PrintE("invalid")
ELSE
FOR i=0 TO DIGITCOUNT-1
DO
PrintB(code(i))
OD
IF res=RESUPSIDEDOWN THEN
PrintE(" valid (upside down)")
ELSE
PrintE(" valid")
FI
FI
RETURN
PROC Main()
PTR ARRAY codes(10)
BYTE i
Init()
codes(0)=" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # "
codes(1)=" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # "
codes(2)=" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # "
codes(3)=" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # "
codes(4)=" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # "
codes(5)=" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # "
codes(6)=" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # "
codes(7)=" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # "
codes(8)=" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # "
codes(9)=" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # "
FOR i=0 TO 9
DO
Test(i+1,codes(i))
OD
RETURN

View file

@ -0,0 +1,21 @@
UPC2Dec(code){
lBits :={" ## #":0," ## #":1," # ##":2," #### #":3," # ##":4," ## #":5," # ####":6," ### ##":7," ## ###":8," # ##":9}
xlBits:={"# ## ":0,"# ## ":1,"## # ":2,"# #### ":3,"## # ":4,"# ## ":5,"#### # ":6,"## ### ":7,"### ## ":8,"## # ":9}
rBits :={"### # ":0,"## ## ":1,"## ## ":2,"# # ":3,"# ### ":4,"# ### ":5,"# # ":6,"# # ":7,"# # ":8,"### # ":9}
xrBits:={" # ###":0," ## ##":1," ## ##":2," # #":3," ### #":4," ### #":5," # #":6," # #":7," # #":8," # ###":9}
UPC := "", CD := 0, code := Trim(code, " ")
S := SubStr(code, 1, 3), code := SubStr(code, 4) ; start or "upside down" end sequence
loop 6
C := SubStr(code, 1, 7), code := SubStr(code, 8) ; six left hand or "upside down" right hand digits
, UPC := lBits[C] <> "" ? UPC . lBits[C] : xrBits[C] . UPC
M := SubStr(code, 1, 5), code := SubStr(code, 6) ; middle sequence
loop 6
C := SubStr(code, 1, 7), code := SubStr(code, 8) ; six right hand or "upside down" left hand digits
, UPC := rBits[C] <> "" ? UPC . rBits[C] : xlBits[C] . UPC
E := SubStr(code, 1, 3), code := SubStr(code, 4) ; end or "upside down" start sequence
for k, v in StrSplit(UPC)
CD += Mod(A_Index, 2) ? v*3 : v ; Check Digit
if (S <> "# #") || (M <> " # # ") || (E <> "# #") || Mod(CD, 10)
return "Invalid!"
return UPC
}

View file

@ -0,0 +1,17 @@
data =
(
# # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # #
# # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # #
# # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # #
# # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # #
# # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # #
# # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # #
# # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # #
# # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # #
# # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # #
# # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # #
)
for i, code in StrSplit(data, "`n", "`r")
output .= i ":`t" UPC2Dec(code) "`n"
MsgBox, 262144, ,% output
return

163
Task/UPC/C++/upc.cpp Normal file
View file

@ -0,0 +1,163 @@
#include <iostream>
#include <locale>
#include <map>
#include <vector>
std::string trim(const std::string &str) {
auto s = str;
//rtrim
auto it1 = std::find_if(s.rbegin(), s.rend(), [](char ch) { return !std::isspace<char>(ch, std::locale::classic()); });
s.erase(it1.base(), s.end());
//ltrim
auto it2 = std::find_if(s.begin(), s.end(), [](char ch) { return !std::isspace<char>(ch, std::locale::classic()); });
s.erase(s.begin(), it2);
return s;
}
template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
auto it = v.cbegin();
auto end = v.cend();
os << '[';
if (it != end) {
os << *it;
it = std::next(it);
}
while (it != end) {
os << ", " << *it;
it = std::next(it);
}
return os << ']';
}
const std::map<std::string, int> LEFT_DIGITS = {
{" ## #", 0},
{" ## #", 1},
{" # ##", 2},
{" #### #", 3},
{" # ##", 4},
{" ## #", 5},
{" # ####", 6},
{" ### ##", 7},
{" ## ###", 8},
{" # ##", 9}
};
const std::map<std::string, int> RIGHT_DIGITS = {
{"### # ", 0},
{"## ## ", 1},
{"## ## ", 2},
{"# # ", 3},
{"# ### ", 4},
{"# ### ", 5},
{"# # ", 6},
{"# # ", 7},
{"# # ", 8},
{"### # ", 9}
};
const std::string END_SENTINEL = "# #";
const std::string MID_SENTINEL = " # # ";
void decodeUPC(const std::string &input) {
auto decode = [](const std::string &candidate) {
using OT = std::vector<int>;
OT output;
size_t pos = 0;
auto part = candidate.substr(pos, END_SENTINEL.length());
if (part == END_SENTINEL) {
pos += END_SENTINEL.length();
} else {
return std::make_pair(false, OT{});
}
for (size_t i = 0; i < 6; i++) {
part = candidate.substr(pos, 7);
pos += 7;
auto e = LEFT_DIGITS.find(part);
if (e != LEFT_DIGITS.end()) {
output.push_back(e->second);
} else {
return std::make_pair(false, output);
}
}
part = candidate.substr(pos, MID_SENTINEL.length());
if (part == MID_SENTINEL) {
pos += MID_SENTINEL.length();
} else {
return std::make_pair(false, OT{});
}
for (size_t i = 0; i < 6; i++) {
part = candidate.substr(pos, 7);
pos += 7;
auto e = RIGHT_DIGITS.find(part);
if (e != RIGHT_DIGITS.end()) {
output.push_back(e->second);
} else {
return std::make_pair(false, output);
}
}
part = candidate.substr(pos, END_SENTINEL.length());
if (part == END_SENTINEL) {
pos += END_SENTINEL.length();
} else {
return std::make_pair(false, OT{});
}
int sum = 0;
for (size_t i = 0; i < output.size(); i++) {
if (i % 2 == 0) {
sum += 3 * output[i];
} else {
sum += output[i];
}
}
return std::make_pair(sum % 10 == 0, output);
};
auto candidate = trim(input);
auto out = decode(candidate);
if (out.first) {
std::cout << out.second << '\n';
} else {
std::reverse(candidate.begin(), candidate.end());
out = decode(candidate);
if (out.first) {
std::cout << out.second << " Upside down\n";
} else if (out.second.size()) {
std::cout << "Invalid checksum\n";
} else {
std::cout << "Invalid digit(s)\n";
}
}
}
int main() {
std::vector<std::string> barcodes = {
" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ",
" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ",
" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ",
" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ",
" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ",
" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ",
" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ",
" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ",
" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ",
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # ",
};
for (auto &barcode : barcodes) {
decodeUPC(barcode);
}
return 0;
}

303
Task/UPC/C/upc.c Normal file
View file

@ -0,0 +1,303 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char const *const string;
bool consume_sentinal(bool middle, string s, size_t *pos) {
if (middle) {
if (s[*pos] == ' ' && s[*pos + 1] == '#' && s[*pos + 2] == ' ' && s[*pos + 3] == '#' && s[*pos + 4] == ' ') {
*pos += 5;
return true;
}
} else {
if (s[*pos] == '#' && s[*pos + 1] == ' ' && s[*pos + 2] == '#') {
*pos += 3;
return true;
}
}
return false;
}
int consume_digit(bool right, string s, size_t *pos) {
const char zero = right ? '#' : ' ';
const char one = right ? ' ' : '#';
size_t i = *pos;
int result = -1;
if (s[i] == zero) {
if (s[i + 1] == zero) {
if (s[i + 2] == zero) {
if (s[i + 3] == one) {
if (s[i + 4] == zero) {
if (s[i + 5] == one && s[i + 6] == one) {
result = 9;
}
} else if (s[i + 4] == one) {
if (s[i + 5] == zero && s[i + 6] == one) {
result = 0;
}
}
}
} else if (s[i + 2] == one) {
if (s[i + 3] == zero) {
if (s[i + 4] == zero && s[i + 5] == one && s[i + 6] == one) {
result = 2;
}
} else if (s[i + 3] == one) {
if (s[i + 4] == zero && s[i + 5] == zero && s[i + 6] == one) {
result = 1;
}
}
}
} else if (s[i + 1] == one) {
if (s[i + 2] == zero) {
if (s[i + 3] == zero) {
if (s[i + 4] == zero && s[i + 5] == one && s[i + 6] == one) {
result = 4;
}
} else if (s[i + 3] == one) {
if (s[i + 4] == one && s[i + 5] == one && s[i + 6] == one) {
result = 6;
}
}
} else if (s[i + 2] == one) {
if (s[i + 3] == zero) {
if (s[i + 4] == zero) {
if (s[i + 5] == zero && s[i + 6] == one) {
result = 5;
}
} else if (s[i + 4] == one) {
if (s[i + 5] == one && s[i + 6] == one) {
result = 8;
}
}
} else if (s[i + 3] == one) {
if (s[i + 4] == zero) {
if (s[i + 5] == one && s[i + 6] == one) {
result = 7;
}
} else if (s[i + 4] == one) {
if (s[i + 5] == zero && s[i + 6] == one) {
result = 3;
}
}
}
}
}
}
if (result >= 0) {
*pos += 7;
}
return result;
}
bool decode_upc(string src, char *buffer) {
const int one = 1;
const int three = 3;
size_t pos = 0;
int sum = 0;
int digit;
//1) 9 spaces (unreliable)
while (src[pos] != '#') {
if (src[pos] == 0) {
return false;
}
pos++;
}
//2) Start "# #"
if (!consume_sentinal(false, src, &pos)) {
return false;
}
//3) 6 left-hand digits (space is zero and hash is one)
digit = consume_digit(false, src, &pos);
if (digit < 0) {
return false;
}
sum += three * digit;
*buffer++ = digit + '0';
*buffer++ = ' ';
digit = consume_digit(false, src, &pos);
if (digit < 0) {
return false;
}
sum += one * digit;
*buffer++ = digit + '0';
*buffer++ = ' ';
digit = consume_digit(false, src, &pos);
if (digit < 0) {
return false;
}
sum += three * digit;
*buffer++ = digit + '0';
*buffer++ = ' ';
digit = consume_digit(false, src, &pos);
if (digit < 0) {
return false;
}
sum += one * digit;
*buffer++ = digit + '0';
*buffer++ = ' ';
digit = consume_digit(false, src, &pos);
if (digit < 0) {
return false;
}
sum += three * digit;
*buffer++ = digit + '0';
*buffer++ = ' ';
digit = consume_digit(false, src, &pos);
if (digit < 0) {
return false;
}
sum += one * digit;
*buffer++ = digit + '0';
*buffer++ = ' ';
//4) Middle "# #"
if (!consume_sentinal(true, src, &pos)) {
return false;
}
//5) 6 right-hand digits (hash is zero and space is one)
digit = consume_digit(true, src, &pos);
if (digit < 0) {
return false;
}
sum += three * digit;
*buffer++ = digit + '0';
*buffer++ = ' ';
digit = consume_digit(true, src, &pos);
if (digit < 0) {
return false;
}
sum += one * digit;
*buffer++ = digit + '0';
*buffer++ = ' ';
digit = consume_digit(true, src, &pos);
if (digit < 0) {
return false;
}
sum += three * digit;
*buffer++ = digit + '0';
*buffer++ = ' ';
digit = consume_digit(true, src, &pos);
if (digit < 0) {
return false;
}
sum += one * digit;
*buffer++ = digit + '0';
*buffer++ = ' ';
digit = consume_digit(true, src, &pos);
if (digit < 0) {
return false;
}
sum += three * digit;
*buffer++ = digit + '0';
*buffer++ = ' ';
digit = consume_digit(true, src, &pos);
if (digit < 0) {
return false;
}
sum += one * digit;
*buffer++ = digit + '0';
*buffer++ = ' ';
//6) Final "# #"
if (!consume_sentinal(false, src, &pos)) {
return false;
}
//7) 9 spaces (unreliable)
// skip
//8) the dot product of the number and (3, 1)+ sequence mod 10 must be zero
return sum % 10 == 0;
}
void test(string src) {
char buffer[24];
if (decode_upc(src, buffer)) {
buffer[22] = 0;
printf("%sValid\n", buffer);
} else {
size_t len = strlen(src);
char *rev = malloc(len + 1);
size_t i;
if (rev == NULL) {
exit(1);
}
for (i = 0; i < len; i++) {
rev[i] = src[len - i - 1];
}
#pragma warning(push)
#pragma warning(disable : 6386)
// if len + 1 bytes are allocated, and len bytes are writable, there is no buffer overrun
rev[len] = 0;
#pragma warning(pop)
if (decode_upc(rev, buffer)) {
buffer[22] = 0;
printf("%sValid (upside down)\n", buffer);
} else {
printf("Invalid digit(s)\n");
}
free(rev);
}
}
int main() {
int num = 0;
printf("%2d: ", ++num);
test(" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ");
printf("%2d: ", ++num);
test(" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ");
printf("%2d: ", ++num);
test(" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ");
printf("%2d: ", ++num);
test(" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ");
printf("%2d: ", ++num);
test(" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ");
printf("%2d: ", ++num);
test(" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ");
printf("%2d: ", ++num);
test(" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ");
printf("%2d: ", ++num);
test(" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ");
printf("%2d: ", ++num);
test(" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ");
printf("%2d: ", ++num);
test(" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # ");
return 0;
}

120
Task/UPC/D/upc.d Normal file
View file

@ -0,0 +1,120 @@
import std.algorithm : countUntil, each, map;
import std.array : array;
import std.conv : to;
import std.range : empty, retro;
import std.stdio : writeln;
import std.string : strip;
import std.typecons : tuple;
immutable LEFT_DIGITS = [
" ## #",
" ## #",
" # ##",
" #### #",
" # ##",
" ## #",
" # ####",
" ### ##",
" ## ###",
" # ##"
];
immutable RIGHT_DIGITS = LEFT_DIGITS.map!`a.map!"a == '#' ? ' ' : '#'".array`.array;
immutable END_SENTINEL = "# #";
immutable MID_SENTINEL = " # # ";
void decodeUPC(string input) {
auto decode(string candidate) {
int[] output;
size_t pos = 0;
auto next = pos + END_SENTINEL.length;
auto part = candidate[pos .. next];
if (part == END_SENTINEL) {
pos = next;
} else {
return tuple(false, cast(int[])[]);
}
foreach (_; 0..6) {
next = pos + 7;
part = candidate[pos .. next];
auto i = countUntil(LEFT_DIGITS, part);
if (i >= 0) {
output ~= i;
pos = next;
} else {
return tuple(false, cast(int[])[]);
}
}
next = pos + MID_SENTINEL.length;
part = candidate[pos .. next];
if (part == MID_SENTINEL) {
pos = next;
} else {
return tuple(false, cast(int[])[]);
}
foreach (_; 0..6) {
next = pos + 7;
part = candidate[pos .. next];
auto i = countUntil(RIGHT_DIGITS, part);
if (i >= 0) {
output ~= i;
pos = next;
} else {
return tuple(false, cast(int[])[]);
}
}
next = pos + END_SENTINEL.length;
part = candidate[pos .. next];
if (part == END_SENTINEL) {
pos = next;
} else {
return tuple(false, cast(int[])[]);
}
int sum = 0;
foreach (i,v; output) {
if (i % 2 == 0) {
sum += 3 * v;
} else {
sum += v;
}
}
return tuple(sum % 10 == 0, output);
}
auto candidate = input.strip;
auto output = decode(candidate);
if (output[0]) {
writeln(output[1]);
} else {
output = decode(candidate.retro.array.to!string);
if (output[0]) {
writeln(output[1], " Upside down");
} else if (output[1].empty) {
writeln("Invalid digit(s)");
} else {
writeln("Invalid checksum", output);
}
}
}
void main() {
auto barcodes = [
" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ",
" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ",
" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ",
" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ",
" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ",
" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ",
" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ",
" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ",
" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ",
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # ",
];
barcodes.each!decodeUPC;
}

View file

@ -0,0 +1,51 @@
USING: combinators combinators.short-circuit formatting grouping
kernel locals math math.functions math.vectors sequences
sequences.repeating unicode ;
CONSTANT: numbers {
" ## #"
" ## #"
" # ##"
" #### #"
" # ##"
" ## #"
" # ####"
" ### ##"
" ## ###"
" # ##"
}
: upc>dec ( str -- seq )
[ blank? ] trim 3 tail 3 head* 42 cut 5 tail
[ 35 = 32 35 ? ] map append 7 group [ numbers index ] map ;
: valid-digits? ( seq -- ? ) [ f = ] none? ;
: valid-checksum? ( seq -- ? )
{ 3 1 } 12 cycle v* sum 10 divisor? ;
: valid-upc? ( seq -- ? )
{ [ valid-digits? ] [ valid-checksum? ] } 1&& ;
:: process-upc ( upc -- obj upside-down? )
upc upc>dec :> d
{
{ [ d valid-upc? ] [ d f ] }
{ [ upc reverse upc>dec dup valid-upc? ] [ t ] }
{ [ drop d valid-digits? ] [ "Invalid checksum" f ] }
[ "Invalid digit(s)" f ]
} cond ;
{
" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # "
" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # "
" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # "
" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # "
" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # "
" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # "
" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # "
" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # "
" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # "
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # "
}
[ process-upc "(upside down)" "" ? "%u %s\n" printf ] each

126
Task/UPC/Go/upc.go Normal file
View file

@ -0,0 +1,126 @@
package main
import (
"fmt"
"regexp"
)
var bits = []string{
"0 0 0 1 1 0 1 ",
"0 0 1 1 0 0 1 ",
"0 0 1 0 0 1 1 ",
"0 1 1 1 1 0 1 ",
"0 1 0 0 0 1 1 ",
"0 1 1 0 0 0 1 ",
"0 1 0 1 1 1 1 ",
"0 1 1 1 0 1 1 ",
"0 1 1 0 1 1 1 ",
"0 0 0 1 0 1 1 ",
}
var (
lhs = make(map[string]int)
rhs = make(map[string]int)
)
var weights = []int{3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1}
const (
s = "# #"
m = " # # "
e = "# #"
d = "(?:#| ){7}"
)
func init() {
for i := 0; i <= 9; i++ {
lt := make([]byte, 7)
rt := make([]byte, 7)
for j := 0; j < 14; j += 2 {
if bits[i][j] == '1' {
lt[j/2] = '#'
rt[j/2] = ' '
} else {
lt[j/2] = ' '
rt[j/2] = '#'
}
}
lhs[string(lt)] = i
rhs[string(rt)] = i
}
}
func reverse(s string) string {
b := []byte(s)
for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
b[i], b[j] = b[j], b[i]
}
return string(b)
}
func main() {
barcodes := []string{
" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ",
" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ",
" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ",
" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ",
" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ",
" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ",
" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ",
" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ",
" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ",
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # ",
}
// Regular expression to check validity of a barcode and extract digits. However we accept any number
// of spaces at the beginning or end i.e. we don't enforce a minimum of 9.
expr := fmt.Sprintf(`^\s*%s(%s)(%s)(%s)(%s)(%s)(%s)%s(%s)(%s)(%s)(%s)(%s)(%s)%s\s*$`,
s, d, d, d, d, d, d, m, d, d, d, d, d, d, e)
rx := regexp.MustCompile(expr)
fmt.Println("UPC-A barcodes:")
for i, bc := range barcodes {
for j := 0; j <= 1; j++ {
if !rx.MatchString(bc) {
fmt.Printf("%2d: Invalid format\n", i+1)
break
}
codes := rx.FindStringSubmatch(bc)
digits := make([]int, 12)
var invalid, ok bool // False by default.
for i := 1; i <= 6; i++ {
digits[i-1], ok = lhs[codes[i]]
if !ok {
invalid = true
}
digits[i+5], ok = rhs[codes[i+6]]
if !ok {
invalid = true
}
}
if invalid { // Contains at least one invalid digit.
if j == 0 { // Try reversing.
bc = reverse(bc)
continue
} else {
fmt.Printf("%2d: Invalid digit(s)\n", i+1)
break
}
}
sum := 0
for i, d := range digits {
sum += weights[i] * d
}
if sum%10 != 0 {
fmt.Printf("%2d: Checksum error\n", i+1)
break
} else {
ud := ""
if j == 1 {
ud = "(upside down)"
}
fmt.Printf("%2d: %v %s\n", i+1, digits, ud)
break
}
}
}
}

20
Task/UPC/J/upc-1.j Normal file
View file

@ -0,0 +1,20 @@
upcdigit=:".;._2]0 :0
0 0 0 1 1 0 1 NB. 0
0 0 1 1 0 0 1 NB. 1
0 0 1 0 0 1 1 NB. 2
0 1 1 1 1 0 1 NB. 3
0 1 0 0 0 1 1 NB. 4
0 1 1 0 0 0 1 NB. 5
0 1 0 1 1 1 1 NB. 6
0 1 1 1 0 1 1 NB. 7
0 1 1 0 1 1 1 NB. 8
0 0 0 1 0 1 1 NB. 9
)
upc2dec=:3 :0
if. 95~: #code=. '#'=dtb dlb y do._ return.end.
if. (11$1 0) ~: 0 1 2 45 46 47 48 49 92 93 94{ code do._ return. end.
digits=. <./([:,upcdigit i.0 1~:(3 50+/i.6 7) { ])"1 code,:|.code
if. 10 e.digits do._ return.end.
if.0 ~:10|digits+/ .* 12$3 1 do._ return.end.
)

24
Task/UPC/J/upc-2.j Normal file
View file

@ -0,0 +1,24 @@
barcodes=:0 :0
# # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # #
# # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # #
# # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # #
# # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # #
# # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # #
# # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # #
# # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # #
# # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # #
# # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # #
# # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # #
)
upc2dec;._2 barcodes
9 2 4 7 7 3 2 7 1 0 1 9
4 0 3 9 4 4 4 4 1 0 5 0
8 3 4 9 9 9 6 7 6 7 0 6
9 3 9 8 2 5 1 5 8 8 1 1
_ 0 0 0 0 0 0 0 0 0 0 0
3 1 6 3 1 3 7 1 8 7 1 7
2 1 4 5 7 5 8 7 5 6 0 8
8 1 8 7 7 8 8 4 1 8 1 3
7 0 6 4 6 6 7 4 3 0 3 0
6 5 3 4 8 3 5 4 0 4 3 5

142
Task/UPC/Java/upc.java Normal file
View file

@ -0,0 +1,142 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
public class UPC {
private static final int SEVEN = 7;
private static final Map<String, Integer> LEFT_DIGITS = Map.of(
" ## #", 0,
" ## #", 1,
" # ##", 2,
" #### #", 3,
" # ##", 4,
" ## #", 5,
" # ####", 6,
" ### ##", 7,
" ## ###", 8,
" # ##", 9
);
private static final Map<String, Integer> RIGHT_DIGITS = LEFT_DIGITS.entrySet()
.stream()
.collect(Collectors.toMap(
entry -> entry.getKey()
.replace(' ', 's')
.replace('#', ' ')
.replace('s', '#'),
Map.Entry::getValue
));
private static final String END_SENTINEL = "# #";
private static final String MID_SENTINEL = " # # ";
private static void decodeUPC(String input) {
Function<String, Map.Entry<Boolean, List<Integer>>> decode = (String candidate) -> {
int pos = 0;
var part = candidate.substring(pos, pos + END_SENTINEL.length());
List<Integer> output = new ArrayList<>();
if (END_SENTINEL.equals(part)) {
pos += END_SENTINEL.length();
} else {
return Map.entry(false, output);
}
for (int i = 1; i < SEVEN; i++) {
part = candidate.substring(pos, pos + SEVEN);
pos += SEVEN;
if (LEFT_DIGITS.containsKey(part)) {
output.add(LEFT_DIGITS.get(part));
} else {
return Map.entry(false, output);
}
}
part = candidate.substring(pos, pos + MID_SENTINEL.length());
if (MID_SENTINEL.equals(part)) {
pos += MID_SENTINEL.length();
} else {
return Map.entry(false, output);
}
for (int i = 1; i < SEVEN; i++) {
part = candidate.substring(pos, pos + SEVEN);
pos += SEVEN;
if (RIGHT_DIGITS.containsKey(part)) {
output.add(RIGHT_DIGITS.get(part));
} else {
return Map.entry(false, output);
}
}
part = candidate.substring(pos, pos + END_SENTINEL.length());
if (!END_SENTINEL.equals(part)) {
return Map.entry(false, output);
}
int sum = 0;
for (int i = 0; i < output.size(); i++) {
if (i % 2 == 0) {
sum += 3 * output.get(i);
} else {
sum += output.get(i);
}
}
return Map.entry(sum % 10 == 0, output);
};
Consumer<List<Integer>> printList = list -> {
var it = list.iterator();
System.out.print('[');
if (it.hasNext()) {
System.out.print(it.next());
}
while (it.hasNext()) {
System.out.print(", ");
System.out.print(it.next());
}
System.out.print(']');
};
var candidate = input.trim();
var out = decode.apply(candidate);
if (out.getKey()) {
printList.accept(out.getValue());
System.out.println();
} else {
StringBuilder builder = new StringBuilder(candidate);
builder.reverse();
out = decode.apply(builder.toString());
if (out.getKey()) {
printList.accept(out.getValue());
System.out.println(" Upside down");
} else if (out.getValue().size() == 12) {
System.out.println("Invalid checksum");
} else {
System.out.println("Invalid digit(s)");
}
}
}
public static void main(String[] args) {
var barcodes = List.of(
" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ",
" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ",
" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ",
" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ",
" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ",
" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ",
" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ",
" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ",
" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ",
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # "
);
barcodes.forEach(UPC::decodeUPC);
}
}

120
Task/UPC/Jq/upc.jq Normal file
View file

@ -0,0 +1,120 @@
## Generic utilities
def enumerate(stream): foreach stream as $x (0; .+1; "\(.): \($x)");
def reverseString: explode | reverse | implode;
## UPC functions
def digitL: {
" ## #": 0,
" ## #": 1,
" # ##": 2,
" #### #": 3,
" # ##": 4,
" ## #": 5,
" # ####": 6,
" ### ##": 7,
" ## ###": 8,
" # ##": 9
};
def digitR: {
"### # ": 0,
"## ## ": 1,
"## ## ": 2,
"# # ": 3,
"# ### ": 4,
"# ### ": 5,
"# # ": 6,
"# # ": 7,
"# # ": 8,
"### # ": 9
};
def endSentinel: "# #"; # also at start
def midSentinel:" # # ";
def decodeUpc:
# Emit {rc: boolean, message: string}
def decodeUpcImpl:
# The "nil" result
def nil: { rc: false, message: ""};
(sub("^ *";"") | sub(" *$"; "")) as $upc
| if ($upc|length != 95) then nil
else [1, 3] as $oneThree
| { pos: 0,
digits: [],
sum: 0 }
| # end sentinel
if $upc[.pos: .pos+3] != endSentinel
then nil
else .pos += 3
# 6 left hand digits
| .i = 0
| until( .i == 6 or .i == null;
.i += 1
| digitL[$upc[.pos: .pos+7]] as $digit
| if ($digit|not) then .i = null
else .digits += [$digit]
| .sum += $digit * $oneThree[(.digits|length) % 2]
| .pos += 7
end )
| if .i == null then nil
else # mid sentinel
if $upc[.pos: .pos+5] != midSentinel
then nil
else .pos += 5
# 6 right hand digits
| .i = 0
| until( .i == 6 or .i == null;
.i += 1
| digitR[$upc[.pos: .pos+7]] as $digit
| if ($digit|not) then .i = null
else .digits += [$digit]
| .sum += $digit * $oneThree[(.digits|length) % 2]
| .pos += 7
end )
| if .i == null then nil
else # end sentinel
if ($upc[.pos : .pos+3] != endSentinel) then false
else if (.sum % 10 == 0)
then {rc: true, message: "\(.digits) "}
else {rc: false, message: "Failed Checksum "}
end
end
end
end
end
end
end ;
. as $in
| decodeUpcImpl
| .message
+ (if .rc then "Rightside Up"
else ($in | reverseString | decodeUpcImpl)
| .message
+ (if .rc then "Upside Down"
else "Invalid digit(s)"
end)
end);
## Examples
def barcodes: [
" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ",
" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ",
" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ",
" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ",
" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ",
" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ",
" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ",
" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ",
" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ",
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # "
];
enumerate( barcodes[] | decodeUpc )

39
Task/UPC/Julia/upc.julia Normal file
View file

@ -0,0 +1,39 @@
const pat1 = (" ## #", " ## #", " # ##", " #### #", " # ##",
" ## #", " # ####", " ### ##", " ## ###", " # ##")
const pat2 = [replace(x, r"[# ]" => (x) -> x == " " ? "#" : " ") for x in pat1]
const ptod1 = Dict((b => a - 1) for (a, b) in enumerate(pat1))
const ptod2 = Dict((b => a - 1) for (a, b) in enumerate(pat2))
const reg = Regex("^\\s*# #\\s*((?:" * join(pat1, "|") *
"){6})\\s*# #\\s*((?:" * join(pat2, "|") * "){6})\\s*# #\\s*")
const lines = [
" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ",
" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ",
" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ",
" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ",
" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ",
" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ",
" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ",
" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ",
" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ",
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # ",
]
function decodeUPC(line)
if (m = match(reg, line)) != nothing
mats, dig = filter(!isempty, m.captures), Int[]
for mat in mats
append!(dig, [ptod1[x.match] for x in eachmatch(r"(.......)", mat)
if haskey(ptod1, x.match)])
append!(dig, [ptod2[x.match] for x in eachmatch(r"(.......)", mat)
if haskey(ptod2, x.match)])
end
dsum = sum([(isodd(i) ? 3 : 1) * n for (i, n) in enumerate(dig)])
(dsum % 10 == 0) && return prod(string.(dig))
end
return ""
end
for line in lines
println((s = decodeUPC(line)) != "" ? s :
(s = decodeUPC(reverse(line))) != "" ? s : "Invalid")
end

109
Task/UPC/Kotlin/upc.kotlin Normal file
View file

@ -0,0 +1,109 @@
val LEFT_DIGITS = mapOf(
" ## #" to 0,
" ## #" to 1,
" # ##" to 2,
" #### #" to 3,
" # ##" to 4,
" ## #" to 5,
" # ####" to 6,
" ### ##" to 7,
" ## ###" to 8,
" # ##" to 9
)
val RIGHT_DIGITS = LEFT_DIGITS.mapKeys {
it.key.replace(' ', 's').replace('#', ' ').replace('s', '#')
}
const val END_SENTINEL = "# #"
const val MID_SENTINEL = " # # "
fun decodeUPC(input: String) {
fun decode(candidate: String): Pair<Boolean, List<Int>> {
var pos = 0
var part = candidate.slice(pos until pos + END_SENTINEL.length)
if (part == END_SENTINEL) {
pos += END_SENTINEL.length
} else {
return Pair(false, emptyList())
}
val output = mutableListOf<Int>()
for (i in 0 until 6) {
part = candidate.slice(pos until pos + 7)
pos += 7
if (LEFT_DIGITS.containsKey(part)) {
output.add(LEFT_DIGITS.getOrDefault(part, -1))
} else {
return Pair(false, output.toList())
}
}
part = candidate.slice(pos until pos + MID_SENTINEL.length)
if (part == MID_SENTINEL) {
pos += MID_SENTINEL.length
} else {
return Pair(false, output.toList())
}
for (i in 0 until 6) {
part = candidate.slice(pos until pos + 7)
pos += 7
if (RIGHT_DIGITS.containsKey(part)) {
output.add(RIGHT_DIGITS.getOrDefault(part, -1))
} else {
return Pair(false, output.toList())
}
}
part = candidate.slice(pos until pos + END_SENTINEL.length)
if (part == END_SENTINEL) {
pos += END_SENTINEL.length
} else {
return Pair(false, output.toList())
}
val sum = output.mapIndexed { i, v -> if (i % 2 == 0) v * 3 else v }.sum()
return Pair(sum % 10 == 0, output.toList())
}
val candidate = input.trim()
var out = decode(candidate)
if (out.first) {
println(out.second)
} else {
out = decode(candidate.reversed())
if (out.first) {
print(out.second)
println(" Upside down")
} else {
if (out.second.size == 12) {
println("Invalid checksum")
} else {
println("Invalid digit(s)")
}
}
}
}
fun main() {
val barcodes = listOf(
" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ",
" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ",
" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ",
" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ",
" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ",
" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ",
" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ",
" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ",
" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ",
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # ",
)
for (barcode in barcodes) {
decodeUPC(barcode)
}
}

167
Task/UPC/Ksh/upc.ksh Normal file
View file

@ -0,0 +1,167 @@
#!/bin/ksh
# Find the corresponding UPC decimal representation of each, rejecting the error
# # Variables:
#
UPC_data_file="../upc.data"
END_SEQ='# #' # Start and End sequence
MID_SEQ=' # # ' # Middle sequence
typeset -a CHK_ARR=( 3 1 3 1 3 1 3 1 3 1 3 1 )
integer bpd=7 # Number of bits per digit
integer numdig=6 # Number of digits per "side"
typeset -a umess=( '' 'Upside down')
typeset -a udig=( 0001101 0011001 0010011 0111101 0100011 0110001 0101111 0111011 0110111 0001011 )
# # Functions:
#
# # Function _validate(array) - verify result with CHK_ARR
#
function _validate {
typeset _arr ; nameref _arr="$1"
typeset _ifs ; _ifs="$2"
typeset _dp _singlearr _oldIFS
_oldIFS=$IFS ; IFS=${_ifs}
typeset -ia _singlearr=( ${_arr[@]} )
integer _dp=$(_dotproduct _singlearr CHK_ARR)
IFS=${_oldIFS}
return $(( _dp % 10 ))
}
# # Function _dotproduct(arr1, arr2) - return dot product
#
function _dotproduct {
typeset _arr1 ; nameref _arr1="$1"
typeset _arr2 ; nameref _arr2="$2"
typeset _i _dp ; integer _i _dp
for (( _i=0; _i<${#_arr1[*]}; _i++ )); do
(( _dp += ( _arr1[_i] * _arr2[_i] ) ))
done
echo ${_dp}
}
# # Function _flipit(string) - return flipped string
#
function _flipit {
typeset _buf ; _buf="$1"
typeset _tmp ; unset _tmp
for (( _i=$(( ${#_buf}-1 )); _i>=0; _i-- )); do
_tmp="${_tmp}${_buf:${_i}:1}"
done
echo "${_tmp}"
}
# # Function _bitget(string, side) - return bitless string & bit
#
function _bitget {
typeset _buff ; _buff="$1"
typeset _side ; integer _side=$2
typeset _ubit _bit
_ubit=${_buff:0:1}
[[ ${_ubit} == \# ]] && _bit=1 || _bit=0
(( _side )) && (( _bit = ! _bit ))
echo ${_buff#*${_ubit}}
return ${_bit}
}
# # Function _decode(upc_arr, digit_arr)
#
function _decode {
typeset _uarr ; nameref _uarr="$1" # UPC code array
typeset _darr ; nameref _darr="$2" # Decimal array
typeset _s _d _b _bit _digit _uarrcopy ; integer _s _d _b _bit
typeset -a _uarrcopy=( ${_uarr[@]} )
for (( _s=0; _s<${#_uarr[*]}; _s++ )); do # each "side"
for (( _d=0; _d<numdig; _d++ )) ; do # each "digit"
for (( _b=0; _b<bpd; _b++ )) ; do # each "bit"
_uarr[_s]=$(_bitget ${_uarr[_s]} ${_s}) ; _bit=$?
_digit="${_digit}${_bit}"
done
_darr[_s]="${_darr[_s]} $(_todec ${_digit})"
if (( $? )); then # May be upside-down
typeset -a _uarr=( ${_uarrcopy[@]} ) # Replace
return 1
fi
unset _digit
done
done
}
# # Function _todec(digit) - Return numeric digit from upc code
#
function _todec {
typeset _bdig ; _bdig="$1"
typeset _i ; integer _i
for (( _i=0; _i<${#udig[*]}; _i++ )); do
[[ ${_bdig} == ${udig[_i]} ]] && echo ${_i} && return 0
done
return 1
}
# # Function _parseUPC(str, arr) - parse UPS string into 2 ele array
#
function _parseUPC {
typeset _buf ; typeset _buf="$1"
typeset _arr ; nameref _arr="$2"
typeset _pre _mid
_pre="${_buf%%${END_SEQ}*}"
_buf="${_buf#*${_pre}}" # Strip preamble
_buf="${_buf#*${END_SEQ}}" # Strip $SEQ
_arr[0]="${_buf:0:$((bpd * numdig))}" # Get the left hand digits
_buf="${_buf#*${_arr[0]}}" # Strip left side digits
_mid="${_buf:0:5}" # Check the middle SEQ
_buf="${_buf#*${MID_SEQ}}" # Strip $SEQ
_arr[1]="${_buf:0:$((bpd * numdig))}" # Get the right hand digits
_buf="${_buf#*${_arr[1]}}" # Strip right side digits
_end="${_buf:0:3}" # Check the end SEQ
_buf="${_buf#*${END_SEQ}}" # Strip $SEQ
}
######
# main #
######
oldIFS="$IFS" ; IFS=''
while read; do
[[ "$REPLY" == \;* ]] && continue
unset side_arr ; typeset -a side_arr # [0]=left [1]=right
_parseUPC "$REPLY" side_arr
unset digit_arr ; typeset -a digit_arr # [0]=left [1]=right
_decode side_arr digit_arr ; integer uflg=$?
if (( uflg )); then # Flip sides and reverse UPC_code
unset digit_arr ; typeset -a digit_arr # [0]=left [1]=right
buff="$(_flipit "${side_arr[0]}")"
side_arr[0]="$(_flipit "${side_arr[1]}")"
side_arr[1]="${buff}"
_decode side_arr digit_arr ; integer vflg=$?
fi
(( ! vflg )) && _validate digit_arr "${oldIFS}" ; integer vflg=$?
if (( vflg )); then
print "INVALID DIGIT(S)"
unset vflg
else
print "${digit_arr[*]} ${umess[uflg]}"
unset uflg
fi
done < ${UPC_data_file}

View file

@ -0,0 +1,13 @@
s=" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # #
# # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # #
# # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # #
# # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # #
# # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # #
# # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # #
# # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # #
# # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # #
# # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # #
# # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # ";
s//=Characters[StringSplit[#,"\n"]]&;
s=%/.{"#"->0," "->1};
Map[BarcodeRecognize@*Image@*List][s]

110
Task/UPC/Nim/upc.nim Normal file
View file

@ -0,0 +1,110 @@
import algorithm, sequtils, strutils
const
LeftDigits = [" ## #",
" ## #",
" # ##",
" #### #",
" # ##",
" ## #",
" # ####",
" ### ##",
" ## ###",
" # ##"]
RightDigits = LeftDigits.mapIt(it.multiReplace(("#", " "), (" ", "#")))
EndSentinel = "# #"
MidSentinel = " # # "
template isEven(n: int): bool = (n and 1) == 0
proc decodeUPC(input: string) =
#.................................................................................................
proc decode(candidate: string): tuple[valid: bool, list: seq[int]] =
const Invalid = (false, @[])
var pos = 0
var next = pos + EndSentinel.len
if candidate[pos..<next] == EndSentinel:
pos = next
else:
return Invalid
for _ in 1..6:
next = pos + 7
let i = LeftDigits.find(candidate[pos..<next])
if i >= 0:
result.list.add i
pos = next
else:
return Invalid
next = pos + MidSentinel.len
if candidate[pos..<next] == MidSentinel:
pos = next
else:
return Invalid
for _ in 1..6:
next = pos + 7
let i = RightDigits.find(candidate[pos..<next])
if i >= 0:
result.list.add i
pos = next
else:
return Invalid
next = pos + EndSentinel.len
if candidate[pos..<next] == EndSentinel:
pos = next
else:
return Invalid
var sum = 0
for i, v in result.list:
sum += (if i.isEven: 3 * v else: v)
result.valid = sum mod 10 == 0
#.................................................................................................
var candidate = input.strip()
let output = candidate.decode()
if output.valid:
echo output.list.join(", ")
else:
candidate.reverse()
let output = candidate.decode()
if output.valid:
echo output.list.join(", "), " Upside down"
elif output.list.len == 0:
echo "Invalid digit(s)"
else:
echo "Invalid checksum: ", output.list.join(", ")
#———————————————————————————————————————————————————————————————————————————————————————————————————
when isMainModule:
const BarCodes = [
" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ",
" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ",
" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ",
" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ",
" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ",
" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ",
" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ",
" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ",
" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ",
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # ",
]
for barcode in BarCodes:
barcode.decodeUPC()

48
Task/UPC/Perl/upc.pl Normal file
View file

@ -0,0 +1,48 @@
use strict;
use warnings;
use feature 'say';
sub decode_UPC {
my($line) = @_;
my(%pattern_to_digit_1,%pattern_to_digit_2,@patterns1,@patterns2,@digits,$sum);
for my $p (' ## #', ' ## #', ' # ##', ' #### #', ' # ##', ' ## #', ' # ####', ' ### ##', ' ## ###', ' # ##') {
push @patterns1, $p;
push @patterns2, $p =~ tr/# / #/r;
}
$pattern_to_digit_1{$patterns1[$_]} = $_ for 0..$#patterns1;
$pattern_to_digit_2{$patterns2[$_]} = $_ for 0..$#patterns2;
my $re = '\s*# #\s*' .
"(?<match1>(?:@{[join '|', @patterns1]}){6})" .
'\s*# #\s*' .
"(?<match2>(?:@{[join '|', @patterns2]}){6})" .
'\s*# #\s*';
$line =~ /^$re$/g || return;
my($match1,$match2) = ($+{match1}, $+{match2});
push @digits, $pattern_to_digit_1{$_} for $match1 =~ /(.{7})/g;
push @digits, $pattern_to_digit_2{$_} for $match2 =~ /(.{7})/g;
$sum += (3,1)[$_%2] * $digits[$_] for 0..11;
$sum % 10 ? '' : join '', @digits;
}
my @lines = (
' # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ',
' # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ',
' # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ',
' # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ',
' # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ',
' # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ',
' # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ',
' # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ',
' # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ',
' # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # ',
);
for my $line (@lines) {
say decode_UPC($line)
// decode_UPC(join '', reverse split '', $line)
// 'Invalid';
}

57
Task/UPC/Phix/upc.phix Normal file
View file

@ -0,0 +1,57 @@
(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">numbers</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">" ## #"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 0</span>
<span style="color: #008000;">" ## #"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 1</span>
<span style="color: #008000;">" # ##"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 2</span>
<span style="color: #008000;">" #### #"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 3</span>
<span style="color: #008000;">" # ##"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 4</span>
<span style="color: #008000;">" ## #"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 5</span>
<span style="color: #008000;">" # ####"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 6</span>
<span style="color: #008000;">" ### ##"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 7</span>
<span style="color: #008000;">" ## ###"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 8</span>
<span style="color: #008000;">" # ##"</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- 9</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">decode</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">bar_code</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">bar_code</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">trim</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bar_code</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bar_code</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">95</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">bar_code</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">"# #"</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">bar_code</span><span style="color: #0000FF;">[</span><span style="color: #000000;">46</span><span style="color: #0000FF;">..</span><span style="color: #000000;">50</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">" # # "</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">bar_code</span><span style="color: #0000FF;">[</span><span style="color: #000000;">93</span><span style="color: #0000FF;">..</span><span style="color: #000000;">95</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">"# #"</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">reversed</span><span style="color: #0000FF;">=</span><span style="color: #004600;">false</span> <span style="color: #008080;">to</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">12</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">st</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">6</span><span style="color: #0000FF;">?</span><span style="color: #000000;">i</span><span style="color: #0000FF;">*</span><span style="color: #000000;">7</span><span style="color: #0000FF;">-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">:</span><span style="color: #000000;">i</span><span style="color: #0000FF;">*</span><span style="color: #000000;">7</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">number</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">bar_code</span><span style="color: #0000FF;">[</span><span style="color: #000000;">st</span><span style="color: #0000FF;">..</span><span style="color: #000000;">st</span><span style="color: #0000FF;">+</span><span style="color: #000000;">6</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">></span><span style="color: #000000;">6</span> <span style="color: #008080;">then</span> <span style="color: #000000;">number</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute_all</span><span style="color: #0000FF;">(</span><span style="color: #000000;">number</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" #X"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"X #"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">r</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">number</span><span style="color: #0000FF;">,</span><span style="color: #000000;">numbers</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sum</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">})),</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"invalid checksum\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%v%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">reversed</span><span style="color: #0000FF;">?</span><span style="color: #008000;">" (upside down)"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">bar_code</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bar_code</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"invalid\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">bar_codes</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"""
# # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # #
# # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # #
# # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # #
# # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # #
# # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # #
# # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # #
# # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # #
# # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # #
# # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # #
# # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # #
"""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bar_codes</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">decode</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bar_codes</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--

54
Task/UPC/PicoLisp/upc.l Normal file
View file

@ -0,0 +1,54 @@
(de l2n (Lst)
(case Lst
((0 0 0 1 1 0 1) 0)
((0 0 1 1 0 0 1) 1)
((0 0 1 0 0 1 1) 2)
((0 1 1 1 1 0 1) 3)
((0 1 0 0 0 1 1) 4)
((0 1 1 0 0 0 1) 5)
((0 1 0 1 1 1 1) 6)
((0 1 1 1 0 1 1) 7)
((0 1 1 0 1 1 1) 8)
((0 0 0 1 0 1 1) 9) ) )
(de convs (Lst Flg)
(make
(for L Lst
(link
(if2 (= "#" L) Flg 0 1 1 0) ) ) ) )
(de getL (Lst)
(make
(cut 3 'Lst)
(do 6
(link (convs (cut 7 'Lst))) )
(cut 5 'Lst)
(do 6
(link (convs (cut 7 'Lst) T)) ) ) )
(de parse (Str)
(let Lst
(make
(link (clip (chop Str)))
(link (reverse (car (made)))) )
(find
'((N) (fully num? N))
(mapcar '((L) (mapcar l2n (getL L))) Lst) ) ) )
(de upc (Str)
(let Lst (parse Str)
(cons
Lst
(%
(apply + (mapcar * Lst (circ 3 1)))
10 ) ) ) )
(setq *U
(quote
" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # "
" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # "
" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # "
" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # "
" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # "
" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # "
" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # "
" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # "
" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # "
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # " ) )
(for L (mapcar upc *U)
(println (if (car L) @ 'invalid)) )

164
Task/UPC/Python/upc.py Normal file
View file

@ -0,0 +1,164 @@
"""UPC-A barcode reader. Requires Python =>3.6"""
import itertools
import re
RE_BARCODE = re.compile(
r"^(?P<s_quiet> +)" # quiet zone
r"(?P<s_guard># #)" # start guard
r"(?P<left>[ #]{42})" # left digits
r"(?P<m_guard> # # )" # middle guard
r"(?P<right>[ #]{42})" # right digits
r"(?P<e_guard># #)" # end guard
r"(?P<e_quiet> +)$" # quiet zone
)
LEFT_DIGITS = {
(0, 0, 0, 1, 1, 0, 1): 0,
(0, 0, 1, 1, 0, 0, 1): 1,
(0, 0, 1, 0, 0, 1, 1): 2,
(0, 1, 1, 1, 1, 0, 1): 3,
(0, 1, 0, 0, 0, 1, 1): 4,
(0, 1, 1, 0, 0, 0, 1): 5,
(0, 1, 0, 1, 1, 1, 1): 6,
(0, 1, 1, 1, 0, 1, 1): 7,
(0, 1, 1, 0, 1, 1, 1): 8,
(0, 0, 0, 1, 0, 1, 1): 9,
}
RIGHT_DIGITS = {
(1, 1, 1, 0, 0, 1, 0): 0,
(1, 1, 0, 0, 1, 1, 0): 1,
(1, 1, 0, 1, 1, 0, 0): 2,
(1, 0, 0, 0, 0, 1, 0): 3,
(1, 0, 1, 1, 1, 0, 0): 4,
(1, 0, 0, 1, 1, 1, 0): 5,
(1, 0, 1, 0, 0, 0, 0): 6,
(1, 0, 0, 0, 1, 0, 0): 7,
(1, 0, 0, 1, 0, 0, 0): 8,
(1, 1, 1, 0, 1, 0, 0): 9,
}
MODULES = {
" ": 0,
"#": 1,
}
DIGITS_PER_SIDE = 6
MODULES_PER_DIGIT = 7
class ParityError(Exception):
"""Exception raised when a parity error is found."""
class ChecksumError(Exception):
"""Exception raised when check digit does not match."""
def group(iterable, n):
"""Chunk the iterable into groups of size ``n``."""
args = [iter(iterable)] * n
return tuple(itertools.zip_longest(*args))
def parse(barcode):
"""Return the 12 digits represented by the given barcode. Raises a
ParityError if any digit fails the parity check."""
match = RE_BARCODE.match(barcode)
# Translate bars and spaces to 1s and 0s so we can do arithmetic
# with them. Group "modules" into chunks of 7 as we go.
left = group((MODULES[c] for c in match.group("left")), MODULES_PER_DIGIT)
right = group((MODULES[c] for c in match.group("right")), MODULES_PER_DIGIT)
# Parity check
left, right = check_parity(left, right)
# Lookup digits
return tuple(
itertools.chain(
(LEFT_DIGITS[d] for d in left),
(RIGHT_DIGITS[d] for d in right),
)
)
def check_parity(left, right):
"""Check left and right parity. Flip left and right if the barcode
was scanned upside down."""
# When reading from left to right, each digit on the left should
# have odd parity, and each digit on the right should have even
# parity.
left_parity = sum(sum(d) % 2 for d in left)
right_parity = sum(sum(d) % 2 for d in right)
# Use left and right parity to check if the barcode was scanned
# upside down. Flip it if it was.
if left_parity == 0 and right_parity == DIGITS_PER_SIDE:
_left = tuple(tuple(reversed(d)) for d in reversed(right))
right = tuple(tuple(reversed(d)) for d in reversed(left))
left = _left
elif left_parity != DIGITS_PER_SIDE or right_parity != 0:
# Error condition. Mixed parity.
error = tuple(
itertools.chain(
(LEFT_DIGITS.get(d, "_") for d in left),
(RIGHT_DIGITS.get(d, "_") for d in right),
)
)
raise ParityError(" ".join(str(d) for d in error))
return left, right
def checksum(digits):
"""Return the check digit for the given digits. Raises a
ChecksumError if the check digit does not match."""
odds = (digits[i] for i in range(0, 11, 2))
evens = (digits[i] for i in range(1, 10, 2))
check_digit = (sum(odds) * 3 + sum(evens)) % 10
if check_digit != 0:
check_digit = 10 - check_digit
if digits[-1] != check_digit:
raise ChecksumError(str(check_digit))
return check_digit
def main():
barcodes = [
" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ",
" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ",
" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ",
" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ",
" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ",
" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ",
" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ",
" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ",
" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ",
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # ",
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### ## ## # ### # # ",
]
for barcode in barcodes:
try:
digits = parse(barcode)
except ParityError as err:
print(f"{err} parity error!")
continue
try:
check_digit = checksum(digits)
except ChecksumError as err:
print(f"{' '.join(str(d) for d in digits)} checksum error! ({err})")
continue
print(f"{' '.join(str(d) for d in digits)}")
if __name__ == "__main__":
main()

48
Task/UPC/REXX/upc.rexx Normal file
View file

@ -0,0 +1,48 @@
/*REXX program to read/interpret UPC symbols and translate them to a numberic string.*/
#.0= ' ## #'
#.1= ' ## #'
#.2= ' # ##'
#.3= ' #### #'
#.4= ' # ##'
#.5= ' ## #'
#.6= ' # ####'
#.7= ' ### ##'
#.8= ' ## ###' /* [↓] right─sided UPC digits.*/
#.9= ' # ##' ; do i=0 for 10; ##.i= translate(#.i, ' #', "# ")
end /*i*/
say center('UPC', 14, "") ' ---'copies(1234567, 6)"-----"copies(1234567, 6)'---'
@.=.
@.1 = ' # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # '
@.2 = ' # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # '
@.3 = ' # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # '
@.4 = ' # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # '
@.5 = ' # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # '
@.6 = ' # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # '
@.7 = ' # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # '
@.8 = ' # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # '
@.9 = ' # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # '
@.10= ' # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # '
ends= '# #' /*define ENDS literal const*/
do j=1 while @.j\==.; $= @.j
txt= /*initialize TXT variable*/
if left($, 9)\='' | right($, 9)\='' then txt= 'bad blanks'
$= strip($); $$= $ /*elide blanks at ends of $*/
L= length($) /*obtain length of $ string*/
if left($, 3) \==ends | right($, 3) \==ends then txt= 'bad fence'
if L \== 95 & txt=='' then txt= 'bad length'
$= substr($, 4, L - length(ends)*2) /*elide "ends". */
$= delstr($, length($) % 2 - 1, 5) /* " middle. */
sum= 0 /*initialize SUM*/
if txt=='' then do k=1 for 12; parse var $ x +7 $ /*get UPC digit.*/
do d=0 for 10; if x==#.d | x==##.d then leave /*valid digit? */
end /*d*/
if d==10 & k \==12 then do; txt= 'reversed' ; leave; end
if d==10 then do; txt= 'bad digit'; leave; end
if k // 2 then sum= sum + d * 3 /*mult. by 3. */
else sum= sum + d /* " " 1. */
txt= txt || d
end /*k*/
if left(txt,1)\=="b" then if sum//10\==0 then txt= 'bad checksum' /*invalid sum? */
say center( strip(txt), 15) ' ' $$ /*show chksum (or err msg) with the UPC*/
end /*j*/ /*stick a fork in it, we're all done. */

81
Task/UPC/Racket/upc.rkt Normal file
View file

@ -0,0 +1,81 @@
#lang racket
;; inspired by Kotlin
(define (is-#? c) (char=? c #\#))
(define left-digits
(for/hash ((i (in-naturals))
(c '((#f #f #t #t #f)
(#f #t #t #f #f)
(#f #t #f #f #t)
(#t #t #t #t #f)
(#t #f #f #f #t)
(#t #t #f #f #f)
(#t #f #t #t #t)
(#t #t #t #f #t)
(#t #t #f #t #t)
(#f #f #t #f #t))))
(values `(#f ,@c #t) i)))
(define right-digits (for/hash (([k v] left-digits)) (values (map not k) v)))
(define (lookup-blocks bits hsh fail)
(let recur ((bs bits) (r null))
(if (null? bs)
(reverse r)
(let-values (((bs tl) (split-at bs 7)))
(let ((d (hash-ref hsh bs (λ () (fail (list 'not-found bs))))))
(recur tl (cons d r)))))))
(define (extract-blocks b fail)
(let*-values
(((e-l-m-r-e) (map is-#? (string->list (string-trim b))))
((_) (unless (= (length e-l-m-r-e) (+ 3 (* 7 6) 5 (* 7 6) 3))
(fail 'wrong-length)))
((e l-m-r-e) (split-at e-l-m-r-e 3))
((_) (unless (equal? e '(#t #f #t)) (fail 'left-sentinel)))
((l-m-r e) (split-at-right l-m-r-e 3))
((_) (unless (equal? e '(#t #f #t)) (fail 'right-sentinel)))
((l m-r) (split-at l-m-r 42))
((m r) (split-at m-r 5))
((_) (unless (equal? m '(#f #t #f #t #f)) (fail 'mid-sentinel))))
(values l r)))
(define (upc-checksum? ds)
(zero? (modulo (for/sum ((m (in-cycle '(3 1))) (d ds)) (* m d)) 10)))
(define (lookup-digits l r fail (transform values))
(let/ec fail-lookups
(define ds (append (lookup-blocks l left-digits (λ _ (fail-lookups #f)))
(lookup-blocks r right-digits (λ _ (fail-lookups #f)))))
(if (upc-checksum? ds)
(transform ds)
(fail (list 'checksum (transform ds))))))
(define (decode-upc barcode upside-down fail)
(define-values (l r) (extract-blocks barcode fail))
(or (lookup-digits l r fail)
(lookup-digits (reverse r) (reverse l) fail upside-down)))
(define (report-upc barcode)
(displayln (decode-upc barcode
(λ (v) (cons 'upside-down v))
(λ (e) (format "invalid: ~s" e)))))
(define (UPC)
(for-each report-upc
'(" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # "
" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # "
" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # "
" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # "
" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # "
" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # "
" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # "
" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # "
" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # "
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # "
; first element again, with corrupted second digit
" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ")))
(module+ main (UPC))

40
Task/UPC/Raku/upc.raku Normal file
View file

@ -0,0 +1,40 @@
sub decode_UPC ( Str $line ) {
constant @patterns1 = ' ## #', ' ## #', ' # ##', ' #### #', ' # ##',
' ## #', ' # ####', ' ### ##', ' ## ###', ' # ##';
constant @patterns2 = @patterns1».trans( '#' => ' ', ' ' => '#' );
constant %pattern_to_digit_1 = @patterns1.antipairs;
constant %pattern_to_digit_2 = @patterns2.antipairs;
constant $re = / ^ '# #' (@patterns1) ** 6
' # # ' (@patterns2) ** 6
'# #' $ /;
$line.trim ~~ $re
orelse return;
my @digits = flat %pattern_to_digit_1{ $0».Str },
%pattern_to_digit_2{ $1».Str };
return unless ( @digits Z* ( |(3,1) xx * ) ).sum %% 10;
return @digits.join;
}
my @lines =
' # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ',
' # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ',
' # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ',
' # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ',
' # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ',
' # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ',
' # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ',
' # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ',
' # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ',
' # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # ',
;
for @lines -> $line {
say decode_UPC($line)
// decode_UPC($line.flip)
// 'Invalid';
}

138
Task/UPC/Ruby/upc.rb Normal file
View file

@ -0,0 +1,138 @@
DIGIT_F = {
" ## #" => 0,
" ## #" => 1,
" # ##" => 2,
" #### #" => 3,
" # ##" => 4,
" ## #" => 5,
" # ####" => 6,
" ### ##" => 7,
" ## ###" => 8,
" # ##" => 9,
}
DIGIT_R = {
"### # " => 0,
"## ## " => 1,
"## ## " => 2,
"# # " => 3,
"# ### " => 4,
"# ### " => 5,
"# # " => 6,
"# # " => 7,
"# # " => 8,
"### # " => 9,
}
END_SENTINEL = "# #"
MID_SENTINEL = " # # "
def decode_upc(s)
def decode_upc_impl(input)
upc = input.strip
if upc.length != 95 then
return false
end
pos = 0
digits = []
sum = 0
# end sentinel
if upc[pos .. pos + 2] == END_SENTINEL then
pos += 3
else
return false
end
# 6 left hand digits
for i in 0 .. 5
digit = DIGIT_F[upc[pos .. pos + 6]]
if digit == nil then
return false
else
digits.push(digit)
sum += digit * [1, 3][digits.length % 2]
pos += 7
end
end
# mid sentinel
if upc[pos .. pos + 4] == MID_SENTINEL then
pos += 5
else
return false
end
# 6 right hand digits
for i in 0 .. 5
digit = DIGIT_R[upc[pos .. pos + 6]]
if digit == nil then
return false
else
digits.push(digit)
sum += digit * [1, 3][digits.length % 2]
pos += 7
end
end
# end sentinel
if upc[pos .. pos + 2] == END_SENTINEL then
pos += 3
else
return false
end
if sum % 10 == 0 then
print digits, " "
return true
else
print "Failed Checksum "
return false
end
end
if decode_upc_impl(s) then
puts "Rightside Up"
elsif decode_upc_impl(s.reverse) then
puts "Upside Down"
else
puts "Invalid digit(s)"
end
end
def main
num = 0
print "%2d: " % [num += 1]
decode_upc(" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ")
print "%2d: " % [num += 1]
decode_upc(" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ")
print "%2d: " % [num += 1]
decode_upc(" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ")
print "%2d: " % [num += 1]
decode_upc(" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ")
print "%2d: " % [num += 1]
decode_upc(" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ")
print "%2d: " % [num += 1]
decode_upc(" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ")
print "%2d: " % [num += 1]
decode_upc(" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ")
print "%2d: " % [num += 1]
decode_upc(" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ")
print "%2d: " % [num += 1]
decode_upc(" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ")
print "%2d: " % [num += 1]
decode_upc(" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # ")
end
main()

102
Task/UPC/VBScript/upc.vb Normal file
View file

@ -0,0 +1,102 @@
'read UPC barcode Antoni Gual 10/2022 https://rosettacode.org/wiki/UPC
Option Explicit
Const m_limit ="# #"
Const m_middle=" # # "
Dim a,bnum,i,check,odic
a=array(" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ",_
" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ",_
" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ",_
" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ",_
" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ",_
" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ",_
" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ",_
" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ",_
" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ",_
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # ")
' 0 1 2 3 4 5 6 7 8 9
bnum=Array("0001101","0011001","0010011","0111101","0100011"," 0110001","0101111","0111011","0110111","0001011")
Set oDic = WScript.CreateObject("scripting.dictionary")
For i=0 To 9:
odic.Add bin2dec(bnum(i),Asc("1")),i+1
odic.Add bin2dec(bnum(i),Asc("0")),-i-1
Next
For i=0 To UBound(a) : print pad(i+1,-2) & ": "& upc(a(i)) :Next
WScript.Quit(1)
Function bin2dec(ByVal B,a) 'binary,ascii of bit 1
Dim n
While len(b)
n =n *2 - (asc(b)=a) 'true is -1 in vbs
b=mid(b,2)
Wend
bin2dec= n And 127
End Function
Sub print(s):
On Error Resume Next
WScript.stdout.WriteLine (s)
If err= &h80070006& Then WScript.Echo " Please run this script with CScript": WScript.quit
End Sub
function pad(s,n) if n<0 then pad= right(space(-n) & s ,-n) else pad= left(s& space(n),n) end if :end function
Function iif(t,a,b) If t Then iif=a Else iif=b End If :End Function
Function getnum(s,r) 'get a number from code, check if its's reversed and trim the code
Dim n,s1,r1
'returns number or 0 if not found
s1=Left(s,7)
s=Mid(s,8)
r1=r
Do
If r Then s1=StrReverse(s1)
n=bin2dec(s1,asc("#"))
If odic.exists(n) Then
getnum=odic(n)
Exit Function
Else
If r1<>r Then getnum=0:Exit Function
r=Not r
End If
Loop
End Function
Function getmarker(s,m) 'get a marker and trim the code
getmarker= (InStr(s,m)= 1)
s=Mid(s,Len(m)+1)
End Function
Function checksum(ByVal s)
Dim n,i : n=0
do
n=n+(Asc(s)-48)*3
s=Mid(s,2)
n=n+(Asc(s)-48)*1
s=Mid(s,2)
Loop until Len(s)=0
checksum= ((n mod 10)=0)
End function
Function upc(ByVal s1)
Dim i,n,s,out,rev,j
'forget about the leading adn trailing spaces, the task says they may be wrong
s=Trim(s1)
If getmarker(s,m_limit)=False Then upc= "bad start marker ":Exit function
rev=False
out=""
For j= 0 To 1
For i=0 To 5
n=getnum(s,rev)
If n=0 Then upc= pad(out,16) & pad ("bad code",-10) & pad("pos "& i+j*6+1,-11): Exit Function
out=out & Abs(n)-1
Next
If j=0 Then If getmarker(s,m_middle)=False Then upc= "bad middle marker " & out :Exit Function
Next
If getmarker(s,m_limit)=False Then upc= "bad end marker " :Exit function
If rev Then out=strreverse(out)
upc= pad(out,16) & pad(iif (checksum(out),"valid","not valid"),-10)& pad(iif(rev,"reversed",""),-11)
End Function

110
Task/UPC/Wren/upc.wren Normal file
View file

@ -0,0 +1,110 @@
import "/fmt" for Fmt
var digitL = {
" ## #": 0,
" ## #": 1,
" # ##": 2,
" #### #": 3,
" # ##": 4,
" ## #": 5,
" # ####": 6,
" ### ##": 7,
" ## ###": 8,
" # ##": 9
}
var digitR = {
"### # ": 0,
"## ## ": 1,
"## ## ": 2,
"# # ": 3,
"# ### ": 4,
"# ### ": 5,
"# # ": 6,
"# # ": 7,
"# # ": 8,
"### # ": 9
}
var endSentinel = "# #" // also at start
var midSentinel = " # # "
var decodeUpc = Fn.new { |s|
var decodeUpcImpl = Fn.new { |input|
var upc = input.trim()
if (upc.count != 95) return false
var pos = 0
var digits = []
var sum = 0
var oneThree = [1, 3]
// end sentinel
if (upc[pos..pos+2] == endSentinel) {
pos = pos + 3
} else {
return false
}
// 6 left hand digits
for (i in 0..5) {
var digit = digitL[upc[pos..pos+6]]
if (!digit) return false
digits.add(digit)
sum = sum + digit * oneThree[digits.count % 2]
pos = pos + 7
}
// mid sentinel
if (upc[pos..pos+4] == midSentinel) {
pos = pos + 5
} else {
return false
}
// 6 right hand digits
for (i in 0..5) {
var digit = digitR[upc[pos..pos+6]]
if (!digit) return false
digits.add(digit)
sum = sum + digit * oneThree[digits.count % 2]
pos = pos + 7
}
// end sentinel
if (upc[pos..pos+2] != endSentinel) return false
if (sum%10 == 0) {
System.write("%(digits) ")
return true
}
System.write("Failed Checksum ")
return false
}
if (decodeUpcImpl.call(s)) {
System.print("Rightside Up")
} else if (decodeUpcImpl.call(s[-1..0])) {
System.print("Upside Down")
} else {
System.print("Invalid digit(s)")
}
}
var barcodes = [
" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ",
" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ",
" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ",
" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ",
" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ",
" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ",
" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ",
" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ",
" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ",
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # "
]
var n = 0
for (barcode in barcodes) {
n = n + 1
Fmt.write("$2d: ", n)
decodeUpc.call(barcode)
}

39
Task/UPC/Zkl/upc-1.zkl Normal file
View file

@ -0,0 +1,39 @@
var lhd=Dictionary(), rhd=Dictionary();
[0..].zip(List(
"0 0 0 1 1 0 1", //--> "___##_#":0 "###__#_":0
"0 0 1 1 0 0 1",
"0 0 1 0 0 1 1",
"0 1 1 1 1 0 1",
"0 1 0 0 0 1 1",
"0 1 1 0 0 0 1",
"0 1 0 1 1 1 1",
"0 1 1 1 0 1 1",
"0 1 1 0 1 1 1",
"0 0 0 1 0 1 1") //--> "___#_##":9 "###_#__":9
).pump(Void,fcn([(n,bs)]){
bs-=" ";
lhd[bs.translate("01","_#")]=n;
rhd[bs.translate("10","_#")]=n;
});
fcn parseBarCode(barcode, one=True){ // --> 12 digits
upsideDown:='wrap{ // was I looking at this bar code upside down?
if(one and (r:=parseBarCode(barcode.reverse(),False))) return(r);
return(False);
};
var [const] start=RegExp(String("_"*9, "+#_#")), tail="_"*7;
if(not start.search(barcode)) return(upsideDown());
r,idx,d,mark := List(), start.matched[0][1], lhd, "_#_#_";
do(2){
do(6){
if(Void==(z:=d.find(barcode[idx,7]))) return(upsideDown());
r.append(z);
idx+=7;
}
if(barcode[idx,5] != mark) return(Void);
d,idx,mark = rhd, idx+5, "#_#__";
}
if(tail!=barcode[idx,7]) return(Void); // 9 trailing blanks? two checked above
r
}

10
Task/UPC/Zkl/upc-2.zkl Normal file
View file

@ -0,0 +1,10 @@
var upcRE = RegExp(String("_"*9, "+#_#",
lhd.keys.concat("|","(",")")*6, "_#_#_",
rhd.keys.concat("|","(",")")*6, "#_#", "_"*9)),
digits=lhd.copy().extend(rhd);
fcn parseBarCode2(barcode){ // --> 12 digits
if(not (upcRE.search(barcode) or upcRE.search(barcode.reverse()))) return(False);
upcRE.matched[1,*] // ( (a,b), "_#_####","_##___#", 10 more digit patterns )
.apply(digits.get)
}

19
Task/UPC/Zkl/upc-3.zkl Normal file
View file

@ -0,0 +1,19 @@
barcodes:=
#<<<"
_________#_#___#_##__#__##_#___##_###_##_###_##_####_#_#_#_##_##__#___#__##__##_###__#_##__##_###_#__#_#_________
_________#_#_#___##___##_#_####_#___#_##_#___##_#___##_#_#_#_###__#_###__##__##_###__#_#__###_###__#_#_#_________
_________#_#____#_#_#__###__#___#____#_#__#___#____#_#_#_#_##_#___##_#___##_#___##___#_#_####_###_##_#_#_________
_________#_#_##__##_##__##___#__#___#__#_###__#_##__##_#_#_#___##_##__#__###_##_##_#___#_####_##_#___#_#_________
_________#_#_###_##_#___##_##_###__##__#_##___#___#_##_#_#_###_#__##_##__#____#_###_#__##_##__#______#_#__________
__________#_#__#___#_##__##__#___#___#__#_##__##__#___#_#_#_#_####_#__##__#_####_####_#_#__##__#_####_#_#____________
_________#_#__#__##__##__#_#___##_##___#_###_##_##___#_#_#_#__#___#___#__#__###_#_#____###__#_#__#___#_#_________
_________#_#_#____#_##__##___#__#_##__##__###_#___#__#_#_#_###_##_##_###_##_###_###_##_#__##__###_##_#_#__________
_________#_#_###_##___##_#_#_####_#___##_#_####_#_####_#_#_#___#__#_###__#____#_###__#_#____#_###__#_#_#_________
_______________#_#_#_####_##___#_####_#_#___##_##_###_####_#_#_#_#__###_#_###__###__#_#_###__#____#_#__###_#_#_________"
.split("\n");
#<<<
foreach n,barcode in ([1..].zip(barcodes)){
bc:=parseBarCode(barcode);
println("%2d: [%s]".fmt(n,bc and bc.concat(" ") or "Not valid"));
}