Introduce pet-projects dir
[lcapit-junk-code.git] / mega-sena / old / megasena-stats-lp.c
blobd975af400cafb79cc038b72eb74d6009c58d24df
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <errno.h>
7 #include <limits.h>
8 #include <signal.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
12 struct ohtbl {
13 int positions;
14 int size;
15 void **table;
17 /* debug stuff */
18 int gr_collision;
19 int nr_collisions;
20 int no_collisions;
23 #define HASH_TABLE_SIZE 10240 /* 10k */
24 #define LOTTERY_MAX 6 /* bytes */
25 #define NAME_LENGTH 17 /* bytes */
27 static sig_atomic_t show_status, reload_table;
28 static unsigned long nr_runs, nr_found, ulong_max;
30 static void sig_handler(int signum)
32 switch (signum) {
33 case SIGUSR1:
34 show_status = 1;
35 break;
36 case SIGHUP:
37 reload_table = 1;
38 break;
42 static inline unsigned int tdb_hash(char *name)
44 unsigned value; /* Used to compute the hash value. */
45 unsigned i; /* Used to cycle through random values. */
47 /* Set the initial value from the key size. */
48 for (value = 0x238F13AF * strlen(name), i=0; name[i]; i++)
49 value = (value + (((unsigned char *)name)[i] << (i*5 % 24)));
51 return (1103515243 * value + 12345);
54 static int ohtbl_init(struct ohtbl *p, int positions)
56 int i;
58 p->table = malloc(sizeof(void *) * positions);
59 if (!p->table)
60 return -1;
62 for (i = 0; i < positions; i++)
63 p->table[i] = NULL;
65 p->positions = positions;
66 p->gr_collision = -1;
67 p->size = p->nr_collisions = p->no_collisions = 0;
69 return 0;
72 static void ohtbl_destroy(struct ohtbl *p)
74 int i;
76 for (i = 0; i < p->positions; i++)
77 if (p->table[i])
78 free(p->table[i]);
80 free(p->table);
83 static int ohtbl_lookup(struct ohtbl *p, char *name, unsigned int *h)
85 int i;
86 unsigned int hash;
88 hash = tdb_hash(name) % p->positions;
90 for (i = 0; i < p->positions; i++) {
91 if (p->table[hash])
92 if (!memcmp(p->table[hash], name, NAME_LENGTH)) {
93 /* found */
94 if (h)
95 *h = hash;
96 return 1;
99 hash = (hash + 1) % p->positions;
102 /* Not found */
103 return 0;
106 static int ohtbl_insert(struct ohtbl *p, char *name)
108 int ret, i;
109 unsigned int hash;
111 ret = ohtbl_lookup(p, name, NULL);
112 if (ret) {
113 /* key already exists */
114 return 1;
117 hash = tdb_hash(name) % p->positions;
119 for (i = 0; i < p->positions; i++) {
120 if (!p->table[hash]) {
121 p->table[hash] = (void *) name;
122 p->size++;
124 if (!i)
125 p->no_collisions++;
126 else if (i > p->gr_collision)
127 p->gr_collision = i;
129 return 0;
132 p->nr_collisions++;
133 hash = (hash + 1) % p->positions;
136 /* Table is full */
137 return -1;
140 static void ohtbl_show_stats(struct ohtbl *p)
142 float lfactor, probes;
144 lfactor = (float) p->size / p->positions;
145 probes = 1 / (1 - lfactor);
147 printf("\n-> Hash table statistics\n");
148 printf("Table size: %4d\n", p->positions);
149 printf(" o free: %4d\n", p->positions - p->size);
150 printf(" o in use: %4d\n", p->size);
151 printf("Perfect hashing: %4d\n", p->no_collisions);
152 printf("Collisions: %4d\n", p->nr_collisions);
153 printf(" o nr keys: %4d\n", p->size - p->no_collisions);
154 printf(" o greater: %4d\n", p->gr_collision + 1);
155 printf("Load factor: %4.2f\n", lfactor);
156 printf("P. to probe: %4.2f\n\n", probes);
159 static int ohtbl_load_data_file(struct ohtbl *table, const char *fname)
161 FILE *file;
162 char line[24];
164 file = fopen(fname, "r");
165 if (!file)
166 return -1;
168 memset(line, 0, sizeof(line));
170 while (fgets(line, sizeof(line), file) != NULL) {
171 int err;
172 char *p;
174 if (line[0] == '#') {
175 if (!strchr(line, '\n')) {
176 int c;
178 while ((c = getc(file)) != '\n')
179 /* NOTHING */;
181 memset(line, 0, sizeof(line));
182 continue;
185 p = strchr(line, '\n');
186 if (p)
187 *p = '\0';
189 p = strdup(line);
190 if (!p) {
191 fclose(file);
192 return -1;
195 err = ohtbl_insert(table, p);
196 if (err) {
197 free(p);
198 if (err == -1) {
199 fclose(file);
200 return -1;
202 /* else key already exists */
204 memset(line, 0, sizeof(line));
207 fclose(file);
208 return 0;
211 static int set_seed(void)
213 int fd, ret;
214 size_t bytes;
215 unsigned int seed;
217 fd = open("/dev/random", O_RDONLY);
218 if (fd < 0)
219 return -1;
221 bytes = read(fd, &seed, sizeof(seed));
222 if (bytes != sizeof(seed)) {
223 ret = -1;
224 goto out;
227 ret = 0;
228 srand(seed);
229 printf("\n-> Seed: %#X\n", seed);
231 out:
232 close(fd);
233 return ret;
236 static void lottery(char *result, size_t size)
238 int num, i, j;
239 int numbers[LOTTERY_MAX];
241 memset(result, 0, size);
242 memset(numbers, -1, sizeof(numbers));
244 for (i = 0; i < LOTTERY_MAX; i++) {
245 for (;;) {
246 int found = 0;
248 num = 1 + (int) (60.0 * (rand() / (RAND_MAX + 6.0)));
250 for (j = 0; j < i; j++)
251 if (numbers[j] == num) {
252 found = 1;
253 break;
256 if (!found) {
257 numbers[i] = num;
258 break;
263 snprintf(result, size, "%02d %02d %02d %02d %02d %02d",
264 numbers[0], numbers[1], numbers[2],
265 numbers[3], numbers[4], numbers[5]);
268 static void show_pid(void)
270 printf("-> PID: %d\n\n", getpid());
273 int main(int argc, char *argv[])
275 int ret;
276 char result[24];
277 unsigned int hash;
278 struct ohtbl table;
280 if (argc != 2) {
281 printf("usage: %s < data-file >\n", argv[0]);
282 exit(1);
285 setlinebuf(stdout);
287 ret = ohtbl_init(&table, HASH_TABLE_SIZE);
288 if (ret) {
289 perror("ohtabl_init()");
290 ret = 1;
291 goto out;
294 ret = ohtbl_load_data_file(&table, argv[1]);
295 if (ret) {
296 perror("ohtbl_load_data_file()");
297 ret = 1;
298 goto out;
301 ohtbl_show_stats(&table);
303 ret = set_seed();
304 if (ret) {
305 perror("set_seed()");
306 ret = 1;
307 goto out;
310 show_pid();
312 signal(SIGUSR1, sig_handler);
313 signal(SIGHUP, sig_handler);
315 for (;;) {
318 * The following checks will probably make the program
319 * run slower, but I've implemented them because they're
320 * cool features (specially the reload table one).
322 * If you want full speed you should consider measuring
323 * this thing and removing these features if needed.
326 if (show_status) {
327 printf("-> Ran %lu (* %lu) times with %lu matches\n",
328 nr_runs, ulong_max, nr_found);
329 show_status = 0;
332 if (reload_table) {
334 * XXX: Reading all the file again isn't a smart
335 * way to do this, we could start reading from
336 * the last line read.
338 ret = ohtbl_load_data_file(&table, argv[1]);
339 if (ret) {
340 perror("ohtbl_load_data_file()");
341 fprintf(stderr, "Aborting reload\n");
343 ohtbl_show_stats(&table);
344 reload_table = 0;
347 lottery(result, sizeof(result));
349 ret = ohtbl_lookup(&table, result, &hash);
350 if (ret) {
351 printf("-> HIT in run %lu: [%d] %s\n",
352 nr_runs, hash, result);
353 nr_found++;
356 if (++nr_runs == ULONG_MAX) {
357 if (++ulong_max == ULONG_MAX) {
358 printf("-> ulong_max blew up [%lu]\n",
359 ulong_max);
360 ulong_max = 0;
362 nr_runs = 0;
366 out:
367 ohtbl_destroy(&table);
368 return ret;