-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcoordset.c
159 lines (135 loc) · 3.29 KB
/
coordset.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include "coordset.h"
#include <search.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
COORD *make_coord(int x, int y) {
COORD *result = (COORD *)malloc(sizeof(COORD));
result->x = x;
result->y = y;
result->is_covered = false;
return result;
}
void print_coord(const COORD *c) {
printf("(%d, %d, %s)\n", c->x, c->y, c->is_covered ? "true" : "false");
}
static int compare_coords(const void *pc1_, const void *pc2_) {
const COORD *pc1 = pc1_, *pc2 = pc2_;
if (pc1->x < pc2->x)
return -1;
if (pc1->x > pc2->x)
return 1;
if (pc1->y < pc2->y)
return -1;
if (pc1->y > pc2->y)
return 1;
return 0;
}
// Does nothing if coord is not in cset.
void cover_coord(COORD_SET cset, int x, int y) {
COORD c = { x, y, false };
void *v = tfind(&c, &cset, compare_coords);
if (v) {
COORD *pc = *(COORD **)v;
pc->is_covered = true;
}
}
void add_coord(COORD_SET *csetp, int x, int y) {
COORD *pc = make_coord(x, y);
void *v = tsearch(pc, csetp, compare_coords);
if (v == NULL) {
perror("add_coord");
exit(-1);
} else if (*(COORD **)v != pc) {
// cset already has these coordinates
free(pc);
}
}
static void clear_coverage_action(const void *nodep, VISIT which, int depth) {
COORD *c = *(COORD **)nodep;
switch (which) {
case preorder:
case endorder:
break;
case postorder:
case leaf:
c->is_covered = false;
break;
}
}
void clear_coverage(COORD_SET cset) {
twalk(cset, clear_coverage_action);
}
// NOT GOOD to have these global, but twalk doesn't take an extra argument
// to point to a structure containing these.
int num_coords = 0;
int num_covered = 0;
static void calculate_coverage_action(
const void *nodep, VISIT which, int depth) {
COORD *c = *(COORD **)nodep;
switch (which) {
case preorder:
case endorder:
break;
case postorder:
case leaf:
num_coords++;
if (c->is_covered)
num_covered++;
break;
}
}
double calculate_coverage(COORD_SET cset) {
num_coords = num_covered = 0;
twalk(cset, calculate_coverage_action);
return (double)num_covered / num_coords;
}
bool has_coord(COORD_SET cset, int x, int y) {
COORD c = { x, y, false };
return tfind(&c, &cset, compare_coords);
}
bool is_covered(COORD_SET cset, int x, int y) {
COORD c = { x, y, false };
void *v = tfind(&c, &cset, compare_coords);
if (v) {
COORD *pc = *(COORD **)v;
return pc->is_covered;
} else {
return false;
}
}
int oldmain(int argc, char **argv) {
COORD *pc;
void *v;
void *root = NULL;
pc = make_coord(2, 3);
v = tsearch(pc, &root, compare_coords);
if (v == NULL) {
perror("tsearch");
exit(-1);
} else if (*(COORD **)v != pc) {
puts("already have it");
free(pc);
}
pc = make_coord(2, 4);
if (tfind(pc, &root, compare_coords))
puts("found");
else
puts("not found");
free(pc);
//tdestroy(root, free);
return 0;
}
const char *boolstr(bool b) {
return b ? "true" : "false";
}
int testmain(int argc, char **argv) {
COORD_SET cset = NULL;
add_coord(&cset, 2, 3);
printf("ic(2, 3)=%s\n", boolstr(is_covered(cset, 2, 3)));
cover_coord(cset, 2, 3);
printf("ic(2, 3)=%s\n", boolstr(is_covered(cset, 2, 3)));
clear_coverage(cset);
printf("ic(2, 3)=%s\n", boolstr(is_covered(cset, 2, 3)));
return 0;
}