121 lines
3.8 KiB
Plaintext
121 lines
3.8 KiB
Plaintext
## 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 )
|