h48

A prototype for an optimal Rubik's cube solver, work in progress.
git clone https://git.tronto.net/h48
Download | Log | Files | Refs | README | LICENSE

tool.h (5320B)


      1 #include <time.h>
      2 #include <stdarg.h>
      3 #include <stdbool.h>
      4 #include <inttypes.h>
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 
      9 #include "../src/nissy.h"
     10 #include "nissy_extra.h"
     11 
     12 static void log_stderr(const char *, ...);
     13 static void log_stdout(const char *, ...);
     14 static double timerun(void (*)(void));
     15 static void writetable(const char *, int64_t, const char *);
     16 static long long int generatetable(const char *, char **,
     17     char [static NISSY_DATAID_SIZE]);
     18 static long long int derivetable(
     19     const char *, const char *, const char *, char **);
     20 static int getdata(const char *, char **, const char *);
     21 static void gendata_run(const char *, uint64_t[static 21]);
     22 static void derivedata_run(
     23     const char *, const char *, const char *, const char *);
     24 
     25 static void
     26 log_stderr(const char *str, ...)
     27 {
     28 	va_list args;
     29 
     30 	va_start(args, str);
     31 	vfprintf(stderr, str, args);
     32 	va_end(args);
     33 }
     34 
     35 static void
     36 write_stdout(const char *str, ...)
     37 {
     38 	va_list args;
     39 
     40 	va_start(args, str);
     41 	vfprintf(stdout, str, args);
     42 	va_end(args);
     43 }
     44 
     45 static double
     46 timerun(void (*run)(void))
     47 {
     48 	struct timespec start, end;
     49 	double tdiff, tdsec, tdnano;
     50 
     51 	fflush(stdout);
     52 
     53 	if (run == NULL) {
     54 		printf("nothing to run!\n");
     55 		fflush(stdout);
     56 		return -1.0;
     57 	}
     58 
     59 	clock_gettime(CLOCK_MONOTONIC, &start);
     60 	run();
     61 	clock_gettime(CLOCK_MONOTONIC, &end);
     62 
     63 	tdsec = end.tv_sec - start.tv_sec;
     64 	tdnano = end.tv_nsec - start.tv_nsec;
     65 	tdiff = tdsec + 1e-9 * tdnano;
     66 
     67 	printf("---------\n");
     68 	printf("\nTotal time: %.4fs\n", tdiff);
     69 	fflush(stdout);
     70 
     71 	return tdiff;
     72 }
     73 
     74 static void
     75 writetable(const char *buf, int64_t size, const char *filename)
     76 {
     77 	FILE *f;
     78 
     79 	if ((f = fopen(filename, "wb")) == NULL) {
     80 		printf("Could not write tables to file %s"
     81 		    ", will be regenerated next time.\n", filename);
     82 	} else {
     83 		fwrite(buf, size, 1, f);
     84 		fclose(f);
     85 		printf("Table written to %s.\n", filename);
     86 	}
     87 }
     88 
     89 static long long int
     90 generatetable(
     91 	const char *solver,
     92 	char **buf,
     93 	char dataid[static NISSY_DATAID_SIZE]
     94 )
     95 {
     96 	long long int size, gensize;
     97 
     98 	size = nissy_solverinfo(solver, dataid);
     99 	if (size < 0) {
    100 		printf("Error getting table size.\n");
    101 		return -1;
    102 	}
    103 
    104 	*buf = malloc(size);
    105 	gensize = nissy_gendata(solver, size, *buf);
    106 
    107 	if (gensize != size) {
    108 		printf("Error generating table");
    109 		if (gensize == NISSY_OK)
    110 			printf(" (got %lld bytes)", gensize);
    111 		printf("\n");
    112 		return -2;
    113 	}
    114 
    115 	return gensize;
    116 }
    117 
    118 static long long int
    119 derivetable(
    120 	const char *solver_large,
    121 	const char *solver_small,
    122 	const char *filename_large,
    123 	char **buf
    124 )
    125 {
    126 	uint8_t h, k;
    127 	long long int size, gensize;
    128 	char *fulltable, dataid[NISSY_DATAID_SIZE];
    129 
    130 	if (getdata(solver_large, &fulltable, filename_large) != 0) {
    131 		printf("Error reading full table.\n");
    132 		gensize = -1;
    133 		goto derivetable_error_nofree;
    134 	}
    135 
    136 	size = nissy_solverinfo(solver_small, dataid);
    137 	if (size == -1) {
    138 		printf("Error getting table size.\n");
    139 		gensize = -2;
    140 		goto derivetable_error;
    141 	}
    142 
    143 	if (parse_h48_solver(solver_small, &h, &k) != 0) {
    144 		gensize = -3;
    145 		goto derivetable_error;
    146 	}
    147 
    148 	*buf = malloc(size);
    149 	gensize = gendata_h48_derive(h, fulltable, *buf);
    150 
    151 	if (gensize != size) {
    152 		printf("Error deriving table\n");
    153 		gensize = -4;
    154 		goto derivetable_error;
    155 	}
    156 
    157 derivetable_error:
    158 	free(fulltable);
    159 
    160 derivetable_error_nofree:
    161 	return gensize;
    162 }
    163 
    164 static int
    165 getdata(
    166 	const char *solver,
    167 	char **buf,
    168 	const char *filename
    169 ) {
    170 	long long int size, sizeread;
    171 	FILE *f;
    172 	char dataid[NISSY_DATAID_SIZE];
    173 
    174 	if ((f = fopen(filename, "rb")) == NULL) {
    175 		printf("Table file not found, generating it.\n");
    176 		size = generatetable(solver, buf, dataid);
    177 		switch (size) {
    178 		case -1:
    179 			goto getdata_error_nofree;
    180 		case -2:
    181 			goto getdata_error;
    182 		default:
    183 			writetable(*buf, size, filename);
    184 			break;
    185 		}
    186 	} else {
    187 		printf("Reading tables from file %s\n", filename);
    188 		size = nissy_solverinfo(solver, dataid);
    189 		*buf = malloc(size);
    190 		sizeread = fread(*buf, size, 1, f);
    191 		fclose(f);
    192 		if (sizeread != 1) {
    193 			printf("Error reading table, stopping\n");
    194 			goto getdata_error;
    195 		}
    196 	}
    197 
    198 	return 0;
    199 
    200 getdata_error:
    201 	free(*buf);
    202 getdata_error_nofree:
    203 	return 1;
    204 }
    205 
    206 static void
    207 gendata_run(
    208 	const char *solver,
    209 	uint64_t expected[static 21]
    210 ) {
    211 	long long int size;
    212 	char *buf, filename[1024], dataid[NISSY_DATAID_SIZE];
    213 
    214 	size = generatetable(solver, &buf, dataid);
    215 	sprintf(filename, "tables/%s", dataid);
    216 	switch (size) {
    217 	case -1:
    218 		return;
    219 	case -2:
    220 		goto gendata_run_finish;
    221 	default:
    222 		nissy_datainfo(size, buf, write_stdout);
    223 		printf("\n");
    224 		printf("Succesfully generated %lld bytes. "
    225 		       "See above for details on the tables.\n", size);
    226 
    227 		/* TODO: check that the table is correct */
    228 		writetable(buf, size, filename);
    229 		break;
    230 	}
    231 
    232 gendata_run_finish:
    233 	free(buf);
    234 }
    235 
    236 static void
    237 derivedata_run(
    238 	const char *solver_large,
    239 	const char *solver_small,
    240 	const char *filename_large,
    241 	const char *filename_small
    242 )
    243 {
    244 	long long int size;
    245 	char *buf;
    246 
    247 	buf = NULL;
    248 	size = derivetable(solver_large, solver_small, filename_large, &buf);
    249 	switch (size) {
    250 	case -1:
    251 		return;
    252 	case -2:
    253 		goto derivedata_run_finish;
    254 	default:
    255 		nissy_datainfo(size, buf, write_stdout);
    256 		printf("\n");
    257 		printf("Succesfully generated %lld bytes. "
    258 		       "See above for details on the tables.\n", size);
    259 
    260 		writetable(buf, size, filename_small);
    261 		break;
    262 	}
    263 
    264 derivedata_run_finish:
    265 	free(buf);
    266 }