Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
2
Task/UPC/00-META.yaml
Normal file
2
Task/UPC/00-META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/UPC
|
||||
73
Task/UPC/00-TASK.txt
Normal file
73
Task/UPC/00-TASK.txt
Normal 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, 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 (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): 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:
|
||||
::* It begins with at least 9 spaces (which our imaginary bar code reader unfortunately doesn't always reproduce properly),
|
||||
::* then has a ''' # # ''' sequence marking the start of the sequence,
|
||||
::* then has the six "left hand" digits,
|
||||
::* then has a ''' # # ''' sequence in the middle,
|
||||
::* then has the six "right hand digits",
|
||||
::* then has another ''' # # ''' (end sequence), and finally,
|
||||
::* then ends with nine trailing spaces (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 (3,1,3,1,3,1,3,1,3,1,3,1) and add the products.
|
||||
|
||||
The sum (mod 10) must be '''0''' (must have a zero as its last digit) if the UPC number has been read correctly.
|
||||
<br><br>
|
||||
|
||||
95
Task/UPC/11l/upc.11l
Normal file
95
Task/UPC/11l/upc.11l
Normal 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
227
Task/UPC/ALGOL-68/upc.alg
Normal 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
69
Task/UPC/AWK/upc.awk
Normal 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
170
Task/UPC/Action-/upc.action
Normal 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
|
||||
21
Task/UPC/AutoHotkey/upc-1.ahk
Normal file
21
Task/UPC/AutoHotkey/upc-1.ahk
Normal 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
|
||||
}
|
||||
17
Task/UPC/AutoHotkey/upc-2.ahk
Normal file
17
Task/UPC/AutoHotkey/upc-2.ahk
Normal 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
163
Task/UPC/C++/upc.cpp
Normal 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
303
Task/UPC/C/upc.c
Normal 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
120
Task/UPC/D/upc.d
Normal 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;
|
||||
}
|
||||
51
Task/UPC/Factor/upc.factor
Normal file
51
Task/UPC/Factor/upc.factor
Normal 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
126
Task/UPC/Go/upc.go
Normal 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
20
Task/UPC/J/upc-1.j
Normal 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
24
Task/UPC/J/upc-2.j
Normal 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
142
Task/UPC/Java/upc.java
Normal 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
120
Task/UPC/Jq/upc.jq
Normal 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
39
Task/UPC/Julia/upc.julia
Normal 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
109
Task/UPC/Kotlin/upc.kotlin
Normal 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
167
Task/UPC/Ksh/upc.ksh
Normal 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}
|
||||
13
Task/UPC/Mathematica/upc.math
Normal file
13
Task/UPC/Mathematica/upc.math
Normal 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
110
Task/UPC/Nim/upc.nim
Normal 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
48
Task/UPC/Perl/upc.pl
Normal 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
57
Task/UPC/Phix/upc.phix
Normal 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
54
Task/UPC/PicoLisp/upc.l
Normal 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
164
Task/UPC/Python/upc.py
Normal 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
48
Task/UPC/REXX/upc.rexx
Normal 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
81
Task/UPC/Racket/upc.rkt
Normal 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
40
Task/UPC/Raku/upc.raku
Normal 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
138
Task/UPC/Ruby/upc.rb
Normal 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
102
Task/UPC/VBScript/upc.vb
Normal 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
110
Task/UPC/Wren/upc.wren
Normal 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
39
Task/UPC/Zkl/upc-1.zkl
Normal 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
10
Task/UPC/Zkl/upc-2.zkl
Normal 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
19
Task/UPC/Zkl/upc-3.zkl
Normal 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"));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue