diff options
Diffstat (limited to '19.c')
-rw-r--r-- | 19.c | 223 |
1 files changed, 223 insertions, 0 deletions
@@ -0,0 +1,223 @@ + +#include <regex.h> +#include <stdio.h> +#include <stdlib.h> + + +#define arrlen(x) (sizeof(x)/sizeof((x)[0])) + + +enum MATERIAL { + ORE, + CLAY, + BSDN, + GEOD, +}; + + +struct blueprint { + int ore_ore; + int clay_ore; + int bsdn_ore; + int bsdn_clay; + int geod_ore; + int geod_bsdn; +}; + + +void +blueprint_ctor(struct blueprint * b, int ore_ore, int clay_ore, + int bsdn_ore, int bsdn_clay, int geod_ore, int geod_bsdn) +{ + b->ore_ore = ore_ore; + b->clay_ore = clay_ore; + b->bsdn_ore = bsdn_ore; + b->bsdn_clay = bsdn_clay; + b->geod_ore = geod_ore; + b->geod_bsdn = geod_bsdn; +} + + +struct material { + long amount; + long robots; + long pending; +}; + + +void +material_ctor(struct material * m, long amount, long robots) +{ + m->amount = amount; + m->robots = robots; + m->pending = 0; +} + + +// Tick a material. +// +// Amount increases by the number of robots +// Number of robots increases by number of pending robots +void +material_tick(struct material * m) +{ + m->amount += m->robots; + m->robots += m->pending; + m->pending = 0; +} + + +struct inventory { + struct material ore; + struct material clay; + struct material bsdn; + struct material geod; +}; + + +void +inventory_init(struct inventory * i) +{ + material_ctor(&i->ore, 0, 1); + material_ctor(&i->clay, 0, 0); + material_ctor(&i->bsdn, 0, 0); + material_ctor(&i->geod, 0, 0); +} + + +void +inventory_tick(struct inventory * i) +{ + material_tick(&i->ore); + material_tick(&i->clay); + material_tick(&i->bsdn); + material_tick(&i->geod); +} + + +// Try to build a robot out of material #m +int +inventory_build(struct inventory * i, struct blueprint const * b, enum MATERIAL m) +{ + switch (m) { + case ORE: + if (i->ore.amount < b->ore_ore) + return -1; + i->ore.amount -= b->ore_ore; + i->ore.pending += 1; + break; + + case CLAY: + if (i->ore.amount < b->clay_ore) + return -1; + i->ore.amount -= b->clay_ore; + i->clay.pending += 1; + break; + + case BSDN: + if (i->ore.amount < b->bsdn_ore + || i->clay.amount < b->bsdn_clay) + return -1; + i->ore.amount -= b->bsdn_ore; + i->clay.amount -= b->bsdn_clay; + i->bsdn.pending += 1; + break; + + case GEOD: + if (i->ore.amount < b->geod_ore + || i->bsdn.amount < b->geod_bsdn) + return -1; + i->ore.amount -= b->geod_ore; + i->bsdn.amount -= b->geod_bsdn; + i->geod.pending += 1; + break; + + default: + return -1; + } + + return 0; +} + + +// Most basic build algorithm. Build as many of the most important things that you +// can, and then as many of the next most important, and so on. +// +// Not optimal. But it helps get the structure of the program working. +void +inventory_build_basic(struct inventory * i, struct blueprint const * b, int remaining) +{ + (void) remaining; + + while (inventory_build(i, b, GEOD) == 0) + ; + + while (inventory_build(i, b, BSDN) == 0) + ; + + while (inventory_build(i, b, CLAY) == 0) + ; + + while (inventory_build(i, b, ORE) == 0) + ; +} + + +int +main() +{ + regex_t reblueprint; + char buf[BUFSIZ]; + + if (regcomp(&reblueprint, "Blueprint ([[:digit:]]+):" + " Each ore robot costs ([[:digit:]]+) ore." + " Each clay robot costs ([[:digit:]]+) ore." + " Each obsidian robot costs ([[:digit:]]+) ore and ([[:digit:]]+) clay." + " Each geode robot costs ([[:digit:]]+) ore and ([[:digit:]]+) obsidian.", + REG_EXTENDED) != 0) + { + fprintf(stderr, "Bad regex\n"); + return -1; + } + + while (fgets(buf, sizeof(buf), stdin)) { + regmatch_t rematch[8]; + int bid, t; + struct blueprint b; + struct inventory i; + + if (regexec(&reblueprint, buf, arrlen(rematch), rematch, 0) != 0) { + fprintf(stderr, "Unexpected blueprint in %s\n", buf); + continue; + } + + bid = atoi(buf + rematch[1].rm_so); + blueprint_ctor(&b, atoi(buf + rematch[2].rm_so), + atoi(buf + rematch[3].rm_so), + atoi(buf + rematch[4].rm_so), + atoi(buf + rematch[5].rm_so), + atoi(buf + rematch[6].rm_so), + atoi(buf + rematch[7].rm_so)); + + inventory_init(&i); + for (t = 0; t < 24; ++t) { + inventory_build_basic(&i, &b, 24 - t); + + inventory_tick(&i); + + fprintf(stderr, "Blueprint %d tick %d, ore: %ld/%ld, clay %ld/%ld, bsdn %ld/%ld, geod %ld/%ld\n", + bid, t + 1, + i.ore.amount, i.ore.robots, + i.clay.amount, i.clay.robots, + i.bsdn.amount, i.bsdn.robots, + i.bsdn.amount, i.bsdn.robots); + } + + printf("Blueprint %d geodes = %ld\n", bid, i.geod.amount); + } + + regfree(&reblueprint); + + return 0; +} + |