local fmt = require "fmt" local digitL = { [" ## #"] = 0, [" ## #"] = 1, [" # ##"] = 2, [" #### #"] = 3, [" # ##"] = 4, [" ## #"] = 5, [" # ####"] = 6, [" ### ##"] = 7, [" ## ###"] = 8, [" # ##"] = 9 } local digitR = { ["### # "] = 0, ["## ## "] = 1, ["## ## "] = 2, ["# # "] = 3, ["# ### "] = 4, ["# ### "] = 5, ["# # "] = 6, ["# # "] = 7, ["# # "] = 8, ["### # "] = 9 } local end_sentinel = "# #" -- also at start local mid_sentinel = " # # " local function decode_upc(s) local function decode_upc_impl(input) local upc = input:strip() if #upc != 95 then return false end local pos = 1 local digits = {} local sum = 0 local one_three = {1, 3} -- end sentinel if upc:sub(pos, pos + 2) == end_sentinel then pos += 3 else return false end -- 6 left hand digits for _ = 1, 6 do local digit = digitL[upc:sub(pos, pos + 6)] if !digit then return false end digits:insert(digit) sum += digit * one_three[#digits % 2 + 1] pos += 7 end -- mid sentinel if upc:sub(pos, pos + 4) == mid_sentinel then pos += 5 else return false end -- 6 right hand digits for _ = 1, 6 do local digit = digitR[upc:sub(pos, pos + 6)] if !digit then return false end digits:insert(digit) sum += digit * one_three[#digits % 2 + 1] pos += 7 end -- end sentinel if upc:sub(pos, pos + 2) != end_sentinel then return false end if sum % 10 == 0 then fmt.write("%s ", fmt.swrite(digits)) return true end io.write("Failed Checksum ") return false end if decode_upc_impl(s) then print("Rightside Up") elseif decode_upc_impl(s:reverse()) then print("Upside Down") else print("Invalid digit(s)") end end local barcodes = { " # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # ", " # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # ", " # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # ", " # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # ", " # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # ", " # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # ", " # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # ", " # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # ", " # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # ", " # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # " } local n = 0 for barcodes as barcode do ++n fmt.write("%2d: ", n) decode_upc(barcode) end