uppgb.c (5687B)
1 #include "common.h" 2 3 #define SEC 30ULL 4 #define NOTCOMPUTED UINT64_MAX 5 #define NONBR SIZE_MAX 6 7 #define ASIZE ((uint64_t)('Z' - 'A' + 1)) 8 #define MAP_SIZE (ASIZE * ASIZE) 9 10 typedef struct { 11 size_t n; 12 size_t m; 13 14 size_t nv; 15 uint64_t *v; // store computed values 16 17 uint64_t *flows; 18 size_t *nzflows; // maps position to index of nonzero flow (in e.g. state) 19 size_t **nbrs; 20 } valves; 21 22 static inline size_t statelen(valves v) { return v.m + 2; } 23 24 static inline size_t statemax(valves v) { return ((v.n) * (v.n) << v.m) - 1; } 25 26 static inline char *goto_nbrs(char *s) { 27 size_t i = 0, c = 0; 28 while (c != 9) { 29 if (s[i] == ' ') 30 c++; 31 i++; 32 } 33 return &(s[i]); 34 } 35 36 static inline size_t map_index(char *x) { 37 return ASIZE * ((uint64_t)(x[0] - 'A')) + ((uint64_t)(x[1] - 'A')); 38 } 39 40 void init_valves(valves *v, char **lines, const size_t n) { 41 v->n = n; 42 v->m = 0; 43 44 v->flows = malloc((v->n) * sizeof(*(v->flows))); 45 v->nzflows = malloc((v->n) * sizeof(*(v->nzflows))); 46 v->nbrs = malloc((v->n) * sizeof(*(v->nbrs))); 47 48 size_t i, j; 49 size_t map[MAP_SIZE]; 50 for (i = 0; i < MAP_SIZE; i++) 51 map[i] = SIZE_MAX; 52 for (i = 0; i < n; i++) { 53 char *line = lines[i]; 54 map[map_index(&line[6])] = i; 55 } 56 57 for (i = 0; i < n; i++) { 58 char *line = lines[i]; 59 60 char *flowstr = &line[23]; 61 uint64_t flow; 62 sread_next_u64(&flow, flowstr); 63 v->flows[i] = flow; 64 if (flow != 0) { 65 v->nzflows[i] = v->m; 66 v->m++; 67 } else { 68 v->nzflows[i] = SIZE_MAX; 69 } 70 71 v->nbrs[i] = malloc((v->n) * sizeof(*(v->nbrs[i]))); 72 char *nbrs = goto_nbrs(line); 73 char *cn = nbrs; 74 j = 0; 75 while (cn[0] != '\n' && cn[0] != '\0') { 76 assert(cn[0] <= 'Z' && cn[0] >= 'A'); 77 assert(cn[1] <= 'Z' && cn[1] >= 'A'); 78 v->nbrs[i][j] = map[map_index(cn)]; 79 if (strlen(cn) < 4) { 80 j++; 81 break; 82 } 83 j++; 84 cn = &cn[4]; 85 } 86 while (j < v->n) { 87 v->nbrs[i][j] = NONBR; 88 j++; 89 } 90 } 91 92 v->nv = statemax(*v) + 1; 93 v->v = malloc((v->nv) * sizeof(*(v->v))); 94 } 95 96 size_t f(const uint8_t *state, const valves *v) { 97 size_t r = ((unsigned long)state[0]) * (v->n) + (unsigned long)state[1]; 98 size_t i; 99 for (i = 0; i < v->m; i++) { 100 r <<= 1; 101 if (state[i + 2]) 102 r++; 103 } 104 return r; 105 } 106 107 void f_inv(uint8_t *state, const size_t y, const valves *v) { 108 size_t i; 109 size_t slen = statelen(*v); 110 111 size_t x = y; 112 113 for (i = 1; i <= v->m; i++) { 114 if ((x & 0x01) != 0) { 115 state[slen - i] = 1; 116 } else { 117 state[slen - i] = 0; 118 } 119 x >>= 1; 120 } 121 122 assert(x < (v->n) * (v->n)); 123 124 state[1] = (uint8_t)(x % (v->n)); 125 state[0] = (uint8_t)(x / (v->n)); 126 } 127 128 uint8_t *init_starting_state(valves v) { 129 uint8_t *r = malloc(statelen(v)); 130 131 r[0] = 0; // posituon AA == 0 132 r[1] = 0; // elephant position same 133 134 size_t i; 135 for (i = 2; i < v.m + 2; i++) 136 r[i] = 0; // no valves on 137 138 return r; 139 } 140 141 static inline uint64_t stateflow(uint64_t b, const valves *v) { 142 uint64_t r = 0; 143 size_t i; 144 for (i = 0; i < v->n; i++) { 145 if (v->flows[i] != 0 && (b & (0x1 << v->nzflows[i])) != 0) { 146 r += v->flows[i]; 147 } 148 } 149 return r; 150 } 151 152 void print_state(const uint8_t *state, const valves *v) { 153 printf("%u : %u : ", state[0], state[1]); 154 size_t i; 155 for (i = 0; i < v->m; i++) { 156 printf("%u ", state[i + 2]); 157 } 158 printf("\n"); 159 } 160 161 static inline uint64_t vss(size_t s, valves *v) { 162 return 0x01 << (v->m - s - 1); 163 } 164 165 static inline uint64_t fss(uint64_t py, uint64_t pe, uint64_t b, valves *v) { 166 uint64_t r = py * (v->n) + pe; 167 size_t i; 168 for (i = 0; i < v->m; i++) { 169 r <<= 1; 170 if ((b & vss(i, v)) != 0) 171 r++; 172 } 173 return r; 174 } 175 176 uint64_t *compute_level(valves *v, int level) { 177 size_t i, j; 178 uint64_t b; 179 uint64_t *new = malloc((v->nv) * sizeof(*new)); 180 181 if (level <= 0) { 182 for (i = 0; i < v->nv; i++) 183 new[i] = 0; 184 } else { 185 size_t blim = (1 << v->m); 186 for (i = 0; i < v->n; i++) { // you pos 187 for (j = 0; j < v->n; j++) { // E pos 188 for (b = 0; b < blim; b++) { 189 uint64_t best = 0; 190 if (v->flows[i] != 0 && v->flows[j] != 0) { 191 best = v->v[fss( 192 i, j, (b | (0x01 << v->nzflows[i]) | (0x01 << v->nzflows[j])), 193 v)]; 194 } 195 196 uint64_t bprim; 197 size_t k = 0, l; 198 uint64_t t; 199 if (v->flows[i] != 0) { 200 k = 0; 201 bprim = b | (0x01 << v->nzflows[i]); 202 while (v->nbrs[j][k] != NONBR) { 203 t = v->v[fss(i, v->nbrs[j][k], bprim, v)]; 204 if (t > best) 205 best = t; 206 k++; 207 } 208 } 209 210 if (v->flows[j] != 0) { 211 bprim = b | (0x01 << v->nzflows[j]); 212 k = 0; 213 while (v->nbrs[i][k] != NONBR) { 214 t = v->v[fss(v->nbrs[i][k], j, bprim, v)]; 215 if (t > best) 216 best = t; 217 k++; 218 } 219 } 220 221 k = 0; 222 while (v->nbrs[i][k] != NONBR) { 223 l = 0; 224 while (v->nbrs[j][l] != NONBR) { 225 t = v->v[fss(v->nbrs[i][k], v->nbrs[j][l], b, v)]; 226 if (t > best) 227 best = t; 228 l++; 229 } 230 k++; 231 } 232 233 new[fss(i, j, b, v)] = stateflow(b, v) + best; 234 } 235 } 236 } 237 } 238 239 return new; 240 } 241 242 int main(int argc, char **argv) { 243 char **lines; 244 valves v; 245 size_t nlines = readlines(&lines, "sinput"); 246 247 init_valves(&v, lines, nlines); 248 uint64_t *r; 249 size_t i; 250 for (i = 0; i < 27; i++) { 251 printf("--- LEVEL %zu ---\n", i); 252 r = compute_level(&v, i); 253 free(v.v); 254 v.v = r; 255 } 256 257 printf("%llu\n", v.v[fss(0, 0, 0, &v)]); 258 }