UPC: Difference between revisions

60,715 bytes added ,  3 months ago
m
m (→‎{{header|Wren}}: Minor tidy)
 
(18 intermediate revisions by 16 users not shown)
Line 1:
{{draft task}}
 
;Goal:
Line 73:
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>
 
=={{header|11l}}==
{{trans|Kotlin}}
 
<syntaxhighlight lang="11l">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)</syntaxhighlight>
 
{{out}}
<pre>
[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] Upside down
[9, 3, 9, 8, 2, 5, 1, 5, 8, 8, 1, 1] Upside down
Invalid digit(s)
[3, 1, 6, 3, 1, 3, 7, 1, 8, 7, 1, 7] Upside down
[2, 1, 4, 5, 7, 5, 8, 7, 5, 6, 0, 8]
[8, 1, 8, 7, 7, 8, 8, 4, 1, 8, 1, 3] Upside down
[7, 0, 6, 4, 6, 6, 7, 4, 3, 0, 3, 0]
[6, 5, 3, 4, 8, 3, 5, 4, 0, 4, 3, 5]
</pre>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">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</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/UPC.png Screenshot from Atari 8-bit computer]
<pre>
1: 924773271019 valid
2: 403944441050 valid
3: 834999676706 valid (upside down)
4: 939825158811 valid (upside down)
5: invalid
6: 316313718717 valid (upside down)
7: 214575875608 valid
8: 818778841813 valid (upside down)
9: 706466743030 valid
10: 653483540435 valid
</pre>
 
=={{header|ALGOL 68}}==
<langsyntaxhighlight lang="algol68">BEGIN
# number of digits encoded by UPC #
INT upc digits = 12;
Line 301 ⟶ 600:
FI
OD
END</langsyntaxhighlight>
{{out}}
<pre>
Line 314 ⟶ 613:
9: 7 0 6 4 6 6 7 4 3 0 3 valid
10: 6 5 3 4 8 3 5 4 0 4 3 valid
</pre>
 
=={{header|AutoHotkey}}==
<syntaxhighlight lang="autohotkey">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
}
</syntaxhighlight>
Examples:<syntaxhighlight lang="autohotkey">data =
(
# # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # #
# # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # #
# # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # #
# # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # #
# # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # #
# # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # #
# # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # #
# # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # #
# # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # #
# # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # #
)
for i, code in StrSplit(data, "`n", "`r")
output .= i ":`t" UPC2Dec(code) "`n"
MsgBox, 262144, ,% output
return</syntaxhighlight>
{{out}}
<pre>
1: 924773271019
2: 403944441050
3: 834999676706
4: 939825158811
5: Invalid!
6: 316313718717
7: 214575875608
8: 818778841813
9: 706466743030
10: 653483540435
</pre>
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f UPC.AWK
BEGIN {
Line 387 ⟶ 740:
return(sum)
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 405 ⟶ 758:
 
=={{header|C}}==
<langsyntaxhighlight lang="c">#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
Line 707 ⟶ 1,060:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre> 1: 9 2 4 7 7 3 2 7 1 0 1 Valid
Line 722 ⟶ 1,075:
=={{header|C++}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <locale>
#include <map>
Line 884 ⟶ 1,237:
}
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>[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] Upside down
[9, 3, 9, 8, 2, 5, 1, 5, 8, 8, 1, 1] Upside down
Invalid digit(s)
[3, 1, 6, 3, 1, 3, 7, 1, 8, 7, 1, 7] Upside down
[2, 1, 4, 5, 7, 5, 8, 7, 5, 6, 0, 8]
[8, 1, 8, 7, 7, 8, 8, 4, 1, 8, 1, 3] Upside down
[7, 0, 6, 4, 6, 6, 7, 4, 3, 0, 3, 0]
[6, 5, 3, 4, 8, 3, 5, 4, 0, 4, 3, 5]</pre>
 
=={{header|D}}==
{{trans|C++}}
<syntaxhighlight lang="d">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;
}</syntaxhighlight>
{{out}}
<pre>[9, 2, 4, 7, 7, 3, 2, 7, 1, 0, 1, 9]
Line 899 ⟶ 1,386:
=={{header|Factor}}==
{{works with|Factor|0.99 2019-10-06}}
<langsyntaxhighlight lang="factor">USING: combinators combinators.short-circuit formatting grouping
kernel locals math math.functions math.vectors sequences sequences.repeating
sequences.repeating unicode ;
 
CONSTANT: numbers {
Line 923 ⟶ 1,410:
 
: valid-checksum? ( seq -- ? )
{ 3 1 } 12 cycle v* sum 10 mod zerodivisor? ;
 
: valid-upc? ( seq -- ? )
Line 949 ⟶ 1,436:
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # "
}
[ process-upc "(upside down)" "" ? "%u %s\n" printf ] each</langsyntaxhighlight>
{{out}}
<pre>
Line 965 ⟶ 1,452:
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,090 ⟶ 1,577:
}
}
}</langsyntaxhighlight>
 
{{out}}
Line 1,111 ⟶ 1,598:
Implementation:
 
<langsyntaxhighlight Jlang="j">upcdigit=:".;._2]0 :0
0 0 0 1 1 0 1 NB. 0
0 0 1 1 0 0 1 NB. 1
Line 1,130 ⟶ 1,617:
if. 10 e.digits do._ return.end.
if.0 ~:10|digits+/ .* 12$3 1 do._ return.end.
)</langsyntaxhighlight>
 
Here, we perform some basic integrity checks and use a table lookup to identify the decimal digits.
Line 1,136 ⟶ 1,623:
Task example:
 
<langsyntaxhighlight Jlang="j">barcodes=:0 :0
# # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # #
# # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # #
Line 1,160 ⟶ 1,647:
7 0 6 4 6 6 7 4 3 0 3 0
6 5 3 4 8 3 5 4 0 4 3 5
</syntaxhighlight>
</lang>
 
The row which begins with _ is the damaged row. (If rescanning did not fix that problem, the operator would have to enter the code manually.)
Line 1,168 ⟶ 1,655:
=={{header|Java}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="java">import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Line 1,309 ⟶ 1,796:
barcodes.forEach(UPC::decodeUPC);
}
}</langsyntaxhighlight>
{{out}}
<pre>[9, 2, 4, 7, 7, 3, 2, 7, 1, 0, 1, 9]
Line 1,321 ⟶ 1,808:
[7, 0, 6, 4, 6, 6, 7, 4, 3, 0, 3, 0]
[6, 5, 3, 4, 8, 3, 5, 4, 0, 4, 3, 5]</pre>
 
=={{header|jq}}==
'''Adapted from [[#Wren|Wren]]'''
{{works with|jq}}
'''Also works with gojq, the Go implementation of jq'''
<syntaxhighlight lang="jq">
## 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 )
</syntaxhighlight>
{{output}}
Essentially as for [[#Wren|Wren]].
 
 
=={{header|Julia}}==
{{trans|Raku}}
<langsyntaxhighlight lang="julia">const pat1 = (" ## #", " ## #", " # ##", " #### #", " # ##",
" ## #", " # ####", " ### ##", " ## ###", " # ##")
const pat2 = [replace(x, r"[# ]" => (x) -> x == " " ? "#" : " ") for x in pat1]
Line 1,363 ⟶ 1,980:
(s = decodeUPC(reverse(line))) != "" ? s : "Invalid")
end
</langsyntaxhighlight>{{out}}
<pre>
924773271019
Line 1,379 ⟶ 1,996:
=={{header|Kotlin}}==
{{trans|C}}
<langsyntaxhighlight lang="scala">val LEFT_DIGITS = mapOf(
" ## #" to 0,
" ## #" to 1,
Line 1,487 ⟶ 2,104:
decodeUPC(barcode)
}
}</langsyntaxhighlight>
{{out}}
<pre>[9, 2, 4, 7, 7, 3, 2, 7, 1, 0, 1, 9]
Line 1,499 ⟶ 2,116:
[7, 0, 6, 4, 6, 6, 7, 4, 3, 0, 3, 0]
[6, 5, 3, 4, 8, 3, 5, 4, 0, 4, 3, 5]</pre>
 
=={{header|Ksh}}==
<syntaxhighlight lang="ksh">#!/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}</syntaxhighlight>
{{out}}
<pre> 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 Upside down
9 3 9 8 2 5 1 5 8 8 1 1 Upside down
INVALID DIGIT(S)
3 1 6 3 1 3 7 1 8 7 1 7 Upside down
2 1 4 5 7 5 8 7 5 6 0 8
8 1 8 7 7 8 8 4 1 8 1 3 Upside down
7 0 6 4 6 6 7 4 3 0 3 0
6 5 3 4 8 3 5 4 0 4 3 5</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">s=" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # #
# # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # #
# # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # #
# # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # #
# # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # #
# # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # #
# # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # #
# # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # #
# # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # #
# # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # ";
s//=Characters[StringSplit[#,"\n"]]&;
s=%/.{"#"->0," "->1};
Map[BarcodeRecognize@*Image@*List][s]</syntaxhighlight>
{{out}}
<pre>{"924773271019", "403944441050", "834999676706", "939825158811", {}, "316313718717", "214575875608", "818778841813", "706466743030", "653483540435"}</pre>
 
=={{header|Nim}}==
{{trans|D}}
<syntaxhighlight lang="nim">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()</syntaxhighlight>
 
{{out}}
<pre>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 Upside down
9, 3, 9, 8, 2, 5, 1, 5, 8, 8, 1, 1 Upside down
Invalid digit(s)
3, 1, 6, 3, 1, 3, 7, 1, 8, 7, 1, 7 Upside down
2, 1, 4, 5, 7, 5, 8, 7, 5, 6, 0, 8
8, 1, 8, 7, 7, 8, 8, 4, 1, 8, 1, 3 Upside down
7, 0, 6, 4, 6, 6, 7, 4, 3, 0, 3, 0
6, 5, 3, 4, 8, 3, 5, 4, 0, 4, 3, 5</pre>
 
=={{header|Perl}}==
{{trans|Raku}}
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use feature 'say';
Line 1,550 ⟶ 2,489:
// 'Invalid';
}
</syntaxhighlight>
</lang>
{{out}}
<pre>924773271019
Line 1,564 ⟶ 2,503:
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>constant numbers = {" ## #", -- 0
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
" ## #", -- 1
<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>
" # ##", -- 2
<span style="color: #008000;">" ## #"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 31</span>
<span style="color: #008000;">" # ##"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 42</span>
<span style="color: #008000;">" #### #"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 53</span>
<span style="color: #008000;">" # ##"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 64</span>
<span style="color: #008000;">" ## #"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 75</span>
<span style="color: #008000;">" # ####"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 86</span>
<span style="color: #008000;">" ### ##"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 7</span>
" # ##"} -- 9
<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>
procedure decode(string bar_code)
bar_code = trim(bar_code)
<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>
if length(bar_code)=95
<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>
and bar_code[1..3]="# #"
<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>
and bar_code[46..50]=" # # "
<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>
and bar_code[93..95]="# #" then
<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>
for reversed=false to true do
<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>
sequence r = {}
<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>
for i=1 to 12 do
<span style="color: #004080;">sequence</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
integer st = iff(i<=6?i*7-3:i*7+2)
<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>
string number = bar_code[st..st+6]
<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>
if i>6 then number = substitute_all(number," #X","X #") end if
<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>
r &= find(number,numbers)-1
<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>
end for
<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>
if not find(-1,r) then
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
if remainder(sum(sq_mul(r,{3,1,3,1,3,1,3,1,3,1,3,1})),10) then
<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>
printf(1,"invalid checksum\n")
<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>
else
<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>
printf(1,"%v%s\n",{r,iff(reversed?" (upside down)","")})
end if<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>
return
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
bar_code <span style="color: reverse(bar_code)#008080;">return</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<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>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
printf(1,"invalid\n")
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end procedure
<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>
constant bar_codes = split("""
# # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # #
<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;">"""
# # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # #
# # # ## # ### # ## ### ## # ## # # # ### # # # ## ## # ## # ## ## # ## # ## # #### ### ## # #
# # ## ## ## ## # #### # # ## ### # ## # ## # # # ## ## # ### ## ## # ## # # ### ## # # # #
# # ### ## # # ## ## ### # # # # # # # # # # ## # ## # ## ## ## # # ### # ## ## # # # #
# # ## # # ## ## # # # # # ### # ## # # # # # ## ## # ## # #### #### # # ## # ### ## # # #
# # # ## # ## # # ## ## # ### ## ## # # # # # # ## # # ### # ### ## # # ### # ## ## # # #
# # # # ## ## # # # # ## ## ### # # # # # ### ## ## # ## # # #### ### # # # ## # ## ## # #
# # ### ## ## # # ## ## # # ## # ## ## # ### # # # # # # ### # # # ### # # # ### # # #
# # # #### ## # ## ## # # # ## ## ### #### # # # # # ### ## ### ### ## ### ### ## # # # ### ## # #
# # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # #
""","\n",true)
# # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # #
for i=1 to length(bar_codes) do
"""</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>
decode(bar_codes[i])
<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>
end for</lang>
<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>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,633 ⟶ 2,575:
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de l2n (Lst)
(case Lst
((0 0 0 1 1 0 1) 0)
Line 1,686 ⟶ 2,628:
" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # " ) )
(for L (mapcar upc *U)
(println (if (car L) @ 'invalid)) )</langsyntaxhighlight>
{{out}}
<pre>
Line 1,700 ⟶ 2,642:
(6 5 3 4 8 3 5 4 0 4 3 5)
</pre>
 
=={{header|Python}}==
<syntaxhighlight lang="python">"""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()
</syntaxhighlight>
 
{{out}}
<pre>
$ python barcode.py
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
7 4 8 1 5 9 9 2 3 9 2 _ parity error!
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
6 5 3 4 8 3 5 4 0 4 2 5 checksum error! (8)
</pre>
 
=={{header|Racket}}==
 
<syntaxhighlight lang="racket">#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))</syntaxhighlight>
 
{{out}}
 
<pre>(9 2 4 7 7 3 2 7 1 0 1 9)
(4 0 3 9 4 4 4 4 1 0 5 0)
(upside-down 8 3 4 9 9 9 6 7 6 7 0 6)
(upside-down 9 3 9 8 2 5 1 5 8 8 1 1)
#f
(upside-down 3 1 6 3 1 3 7 1 8 7 1 7)
(2 1 4 5 7 5 8 7 5 6 0 8)
(upside-down 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)
invalid: (checksum (9 9 4 7 7 3 2 7 1 0 1 9))</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" perl6line>sub decode_UPC ( Str $line ) {
constant @patterns1 = ' ## #', ' ## #', ' # ##', ' #### #', ' # ##',
' ## #', ' # ####', ' ### ##', ' ## ###', ' # ##';
Line 1,742 ⟶ 2,965:
// decode_UPC($line.flip)
// 'Invalid';
}</langsyntaxhighlight>
 
{{out}}
Line 1,757 ⟶ 2,980:
 
=={{header|REXX}}==
<langsyntaxhighlight lang="rexx">/*REXX program to read/interpret UPC symbols and translate them to a numberic string.*/
#.0= ' ## #'
#.1= ' ## #'
Line 1,767 ⟶ 2,990:
#.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 = ' # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # '
Line 1,781 ⟶ 3,004:
@.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 do j=left(txt,1 while @.j)\==.;"b" then if sum//10\==0 then $txt= @.j;'bad checksum' /*invalid sum? txt=*/
say center( if leftstrip($txt), 915)\= ' ' $$ | right($, 9)\='' /*show thenchksum txt=(or 'baderr blanks'msg) with the UPC*/
end /*j*/ /*stick a fork in it, we're all done. */</syntaxhighlight>
$= strip($); $$= $; L= length($)
if left($, 3)\=='# #' | right($, 3)\=="# #" then txt= 'bad fence'
if L\==95 & txt=='' then txt= 'bad len'
$= substr($, 4, L - 3 - 3); sum= 0 /*elide ends.*/
$= delstr($, length($) % 2 - 1, 5) /* " middle.*/
if txt=='' then do k=1 for 12; parse var $ x +7 $ /*get UPC dig.*/
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 dig'; leave; end
if k//2 then sum= sum + 3 * d /*mult. by 3.*/
else sum= sum + d /* " " 1.*/
txt= txt || d
end /*k*/
if sum//10 \== 0 then txt= 'bad chksum' /*invalid sum?*/
say center( strip(txt), 15) ' ' $$
end /*j*/ /*stick a fork in it, we're all done. */</lang>
{{out|output|text=&nbsp; when using the internal default input:}}
<pre>
─────UPC────── ---123456712345671234567123456712345671234567-----123456712345671234567123456712345671234567---
─────UPC────── ___123456712345671234567123456712345671234567-----123456712345671234567123456712345671234567___
924773271019 # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # #
403944441050 # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # #
reversed # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # #
reversed # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # #
bad dig digit # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # #
reversed # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # #
214575875608 # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # #
reversed # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # #
706466743030 # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # #
bad len length # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### #
</pre>
 
=={{header|Ruby}}==
{{trans|C}}
<langsyntaxhighlight lang="ruby">DIGIT_F = {
" ## #" => 0,
" ## #" => 1,
Line 1,955 ⟶ 3,182:
end
 
main()</langsyntaxhighlight>
{{out}}
<pre> 1: [9, 2, 4, 7, 7, 3, 2, 7, 1, 0, 1, 9] Rightside Up
Line 1,967 ⟶ 3,194:
9: [7, 0, 6, 4, 6, 6, 7, 4, 3, 0, 3, 0] Rightside Up
10: [6, 5, 3, 4, 8, 3, 5, 4, 0, 4, 3, 5] Rightside Up</pre>
 
=={{header|VBScript}}==
<syntaxhighlight lang="vb">
'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
</syntaxhighlight>
{{out}}
<small>
<pre>
 
1: 924773271019 valid
2: 403944441050 valid
3: 834999676706 valid reversed
4: 939825158811 valid reversed
5: 74815992392 bad code pos 12
6: 316313718717 valid reversed
7: 214575875608 valid
8: 818778841813 valid reversed
9: 706466743030 valid
10: 653483540435 valid
</pre>
</small>
 
 
=={{header|Wren}}==
{{trans|Ruby}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">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)
}</syntaxhighlight>
 
{{out}}
<pre>
1: [9, 2, 4, 7, 7, 3, 2, 7, 1, 0, 1, 9] Rightside Up
2: [4, 0, 3, 9, 4, 4, 4, 4, 1, 0, 5, 0] Rightside Up
3: [8, 3, 4, 9, 9, 9, 6, 7, 6, 7, 0, 6] Upside Down
4: [9, 3, 9, 8, 2, 5, 1, 5, 8, 8, 1, 1] Upside Down
5: Invalid digit(s)
6: [3, 1, 6, 3, 1, 3, 7, 1, 8, 7, 1, 7] Upside Down
7: [2, 1, 4, 5, 7, 5, 8, 7, 5, 6, 0, 8] Rightside Up
8: [8, 1, 8, 7, 7, 8, 8, 4, 1, 8, 1, 3] Upside Down
9: [7, 0, 6, 4, 6, 6, 7, 4, 3, 0, 3, 0] Rightside Up
10: [6, 5, 3, 4, 8, 3, 5, 4, 0, 4, 3, 5] Rightside Up
</pre>
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">var lhd=Dictionary(), rhd=Dictionary();
[0..].zip(List(
"0 0 0 1 1 0 1", //--> "___##_#":0 "###__#_":0
Line 2,007 ⟶ 3,485:
if(tail!=barcode[idx,7]) return(Void); // 9 trailing blanks? two checked above
r
}</langsyntaxhighlight>
Or, if you like way too long regular expressions:
<langsyntaxhighlight lang="zkl">var upcRE = RegExp(String("_"*9, "+#_#",
lhd.keys.concat("|","(",")")*6, "_#_#_",
rhd.keys.concat("|","(",")")*6, "#_#", "_"*9)),
Line 2,018 ⟶ 3,496:
upcRE.matched[1,*] // ( (a,b), "_#_####","_##___#", 10 more digit patterns )
.apply(digits.get)
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">barcodes:=
#<<<"
_________#_#___#_##__#__##_#___##_###_##_###_##_####_#_#_#_##_##__#___#__##__##_###__#_##__##_###_#__#_#_________
Line 2,037 ⟶ 3,515:
bc:=parseBarCode(barcode);
println("%2d: [%s]".fmt(n,bc and bc.concat(" ") or "Not valid"));
}</langsyntaxhighlight>
{{out}}
<pre>
9,476

edits