UPC: Difference between revisions
Content added Content deleted
(Added Algol 68) |
|||
Line 719: | Line 719: | ||
9: 7 0 6 4 6 6 7 4 3 0 3 Valid |
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> |
10: 6 5 3 4 8 3 5 4 0 4 3 Valid</pre> |
||
=={{header|C++}}== |
|||
{{trans|Kotlin}} |
|||
<lang c++>#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; |
|||
}</lang> |
|||
{{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|Factor}}== |
=={{header|Factor}}== |