UPC: Difference between revisions

8,872 bytes added ,  3 years ago
m (→‎{{header|zkl}}: restore code)
Line 135:
11: invalid format # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### #
</pre>
=={{header|C}}==
<lang c>#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;
}</lang>
{{out}}
<pre> 1: 9 2 4 7 7 3 2 7 1 0 1 Valid
2: 4 0 3 9 4 4 4 4 1 0 5 Valid
3: 8 3 4 9 9 9 6 7 6 7 0 Valid (upside down)
4: 9 3 9 8 2 5 1 5 8 8 1 Valid (upside down)
5: Invalid digit(s)
6: 3 1 6 3 1 3 7 1 8 7 1 Valid (upside down)
7: 2 1 4 5 7 5 8 7 5 6 0 Valid
8: 8 1 8 7 7 8 8 4 1 8 1 Valid (upside down)
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|Factor}}==
{{works with|Factor|0.99 2019-10-06}}
1,452

edits