#if 1
#include <stdio.h>
typedef struct {
int point;
int jmp;
}Area;
Area area[35]; //한 줄에 많이 들어가봤자 33개정도 코드밖에 못들어감
char code_h[501];
char pw[10][8] = { "0001101", "0011001", "0010011", "0111101", "0100011", "0110001", "0101111", "0111011", "0110111", "0001011" };
void reset() {
int i;
for (i = 0; i < 35; i++)
area[i].point = -1;
}
void insert_area(int point, int jmp) {
int i;
for (i = 0; i < 35; i++) {
if (area[i].point == -1) {
area[i].point = point;
area[i].jmp = jmp;
break;
}
}
}
void visit() {
int i;
for (i = 0; i < 35; i++) {
if (area[i].point != -1 && code_h[area[i].point] == '0') {
area[i].point = -1;
}
}
}
int is_visit(int x) {
int i;
for (i = 0; i < 35; i++) {
if (area[i].point == x)
return area[i].jmp;
}
return -1;
}
void hextoBi(char hex, char *bi) { //16진수 1개 -> 4자리 2진수로 변환
int num;
int i;
if (hex >= '0' && hex <= '9') {
num = hex - '0';
}
else {
num = hex - 'A' + 10;
}
for (i = 0; i < 4; i++) {
if (num & (1 << (3 - i)))
bi[i] = '1';
else
bi[i] = '0';
}
}
void decode(int *dist, char *code, int index, int scope, int len) { //암호 해석
char newcode[2000];
int start;
int i, j, k;
for (i = 0; i < len; i++) {
hextoBi(code[i + index], newcode + (i * 4));
}
for (i = len * 4 - 1; i > 0; i--) {
if (newcode[i] == '1') {
start = i - 14 * scope * 4 + 1;
break;
}
}
for (k = 0; k < 8; k++) {
for (i = 0; i < 10; i++) {
for (j = 0; j < 7; j++) {
if (newcode[(k * 7 + j)*scope + start] != pw[i][j])
break;
}
if (j == 7) {
dist[k] = i;
break;
}
}
}
}
int find_scope(char *code, int index) { //몇배율인지를 return
char tmp[4];
int check[4] = { 0, 0, 0, 0 };
int i, check_index = 3;
int end = 1, start = 1;
int min;
while (end) {
hextoBi(code[index], tmp);
for (i = 3; i >= 0; i--) { //뒤에서부터 보면서
if (check_index & 1) {
//'1'의 개수 저장 ([1], [3] 번째)
if (tmp[i] == '1') {
check[check_index]++;
start = 0;
}
else {
if (start)
continue;
check_index--;
check[check_index]++;
if (check_index == 0) {
end = 0;
break;
}
}
}
else {
//'0'의 개수 저장 ([0], [2] 번째)
if (tmp[i] == '0') {
check[check_index]++;
}
else {
check_index--;
check[check_index]++;
}
}
}
index--;
}
min = 9999;
for (i = 1; i < 4; i++) {
if (check[i] < min)
min = check[i];
}
return min;
}
int check_code(int *code) { //유효한 암호인지 확인
int i;
int sum, check, tmp;
sum = 0;
check = 0;
for (i = 0; i < 8; i++) {
tmp = code[i];
if (i % 2 == 0)
tmp *= 3;
check += tmp;
sum += code[i];
}
if (check % 10 == 0)
return sum;
else
return 0;
}
int main() {
int T, test_case;
int N, M;
int i, j;
int scope;
int code_d[8];
int ans;
int jmp;
int len;
freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
scanf("%d", &T);
for (test_case = 0; test_case < T; test_case++) {
ans = 0;
reset();
scanf("%d %d", &N, &M);
for (i = 0; i < N; i++) {
scanf("%s", code_h);
visit();
for (j = M - 1; j >= 13; j--) {
if (code_h[j] != '0') {
//암호 시작
jmp = is_visit(j);
if (jmp != -1) { //처리했으면 pass
j = jmp;
}
else {
scope = find_scope(code_h, j);
jmp = j - 14 * scope;
if (code_h[j] == '1' || code_h[j] == '3' || code_h[j] == '5' || code_h[j] == '7' || code_h[j] == '9' ||
code_h[j] == 'B' || code_h[j] == 'D' || code_h[j] == 'F')
jmp++;
if (jmp < 0)
jmp = 0;
insert_area(j, jmp);
len = j - jmp + 1;
j = jmp; //암호 시작위치로 이동
decode(code_d, code_h, j, scope, len);
ans += check_code(code_d);
}
}
}
}
printf("#%d %d\n", test_case + 1, ans);
}
return 0;
}
#endif
댓글