diff --git a/day19/input.txt b/day19/input.txt new file mode 100644 index 0000000..2c1044f --- /dev/null +++ b/day19/input.txt @@ -0,0 +1,30 @@ +Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 12 clay. Each geode robot costs 4 ore and 19 obsidian. +Blueprint 2: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 11 clay. Each geode robot costs 4 ore and 12 obsidian. +Blueprint 3: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 2 ore and 11 obsidian. +Blueprint 4: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 15 clay. Each geode robot costs 4 ore and 20 obsidian. +Blueprint 5: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 16 clay. Each geode robot costs 4 ore and 17 obsidian. +Blueprint 6: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 19 clay. Each geode robot costs 2 ore and 12 obsidian. +Blueprint 7: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 9 clay. Each geode robot costs 2 ore and 10 obsidian. +Blueprint 8: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 3 ore and 7 obsidian. +Blueprint 9: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 11 clay. Each geode robot costs 4 ore and 8 obsidian. +Blueprint 10: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 16 clay. Each geode robot costs 2 ore and 15 obsidian. +Blueprint 11: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 20 clay. Each geode robot costs 2 ore and 19 obsidian. +Blueprint 12: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 16 clay. Each geode robot costs 3 ore and 20 obsidian. +Blueprint 13: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 20 clay. Each geode robot costs 3 ore and 14 obsidian. +Blueprint 14: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 20 clay. Each geode robot costs 2 ore and 15 obsidian. +Blueprint 15: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 15 clay. Each geode robot costs 3 ore and 12 obsidian. +Blueprint 16: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 17 clay. Each geode robot costs 3 ore and 19 obsidian. +Blueprint 17: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 4 ore and 9 obsidian. +Blueprint 18: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 6 clay. Each geode robot costs 3 ore and 16 obsidian. +Blueprint 19: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 6 clay. Each geode robot costs 2 ore and 14 obsidian. +Blueprint 20: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 11 clay. Each geode robot costs 3 ore and 15 obsidian. +Blueprint 21: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 18 clay. Each geode robot costs 4 ore and 19 obsidian. +Blueprint 22: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 15 clay. Each geode robot costs 2 ore and 20 obsidian. +Blueprint 23: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 5 clay. Each geode robot costs 2 ore and 10 obsidian. +Blueprint 24: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 10 clay. Each geode robot costs 2 ore and 14 obsidian. +Blueprint 25: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 7 clay. Each geode robot costs 4 ore and 13 obsidian. +Blueprint 26: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 2 ore and 20 obsidian. +Blueprint 27: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 18 clay. Each geode robot costs 2 ore and 19 obsidian. +Blueprint 28: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 10 clay. Each geode robot costs 2 ore and 7 obsidian. +Blueprint 29: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 15 clay. Each geode robot costs 3 ore and 7 obsidian. +Blueprint 30: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 20 clay. Each geode robot costs 4 ore and 18 obsidian. diff --git a/day19/robot b/day19/robot new file mode 100755 index 0000000..15b6368 Binary files /dev/null and b/day19/robot differ diff --git a/day19/robot.c b/day19/robot.c new file mode 100644 index 0000000..4553fb0 --- /dev/null +++ b/day19/robot.c @@ -0,0 +1,206 @@ +#include +#include +#include +#include + +#define BUFFER_SIZE 256 +#define MAX_BLUEPRINT 128 +#define MAX_TIME 24 +#define PART_TWO_NUM 3 +#define PART_TWO_TIME 32 + +#define max(a,b) (a >= b ? a : b) + +typedef struct blueprint { + int ore_cost; + int clay_cost; + int obsidian_cost[2]; + int geode_cost[2]; +} BLUEPRINT; + +int bestGeode(BLUEPRINT, int[], int[], int, int); + +int bestMax = 0; + +int main() { + char buf[BUFFER_SIZE], *p, c; + memset(buf, 0, BUFFER_SIZE); + p = buf; + BLUEPRINT blueprints[MAX_BLUEPRINT]; + int blueprint_count = 0; + + while ((c = getchar()) != EOF) { + *p++ = c; + if (c == '\n') { + sscanf(buf, "Blueprint %*i: Each ore robot costs %i ore. Each clay robot costs %i ore. Each obsidian robot costs %i ore and %i clay. Each geode robot costs %i ore and %i obsidian.", &blueprints[blueprint_count].ore_cost, &blueprints[blueprint_count].clay_cost, &blueprints[blueprint_count].obsidian_cost[0], &blueprints[blueprint_count].obsidian_cost[1], &blueprints[blueprint_count].geode_cost[0], &blueprints[blueprint_count].geode_cost[1]); + blueprint_count++; + memset(buf, 0, BUFFER_SIZE); + p = buf; + } + } + + int *quality_levels = (int*)malloc(blueprint_count * sizeof(int)); + memset(quality_levels, 0, blueprint_count * sizeof(int)); + // Check each blueprint + for (int i = 0; i < blueprint_count; i++) { + bestMax = 0; + int stash[4] = {0,0,0,0}; + int robots[4] = {1,0,0,0}; + + + quality_levels[i] = bestGeode(blueprints[i], stash, robots, 0, MAX_TIME); + } + + int sum = 0; + for (int i = 0; i < blueprint_count; i++) { + sum += (i+1) * quality_levels[i]; + } + + printf("%i\n", sum); + free(quality_levels); + + + unsigned product = 1; + for (int i = 0; i < PART_TWO_NUM; i++) { + bestMax = 0; + int stash[4] = {0,0,0,0}; + int robots[4] = {1,0,0,0}; + + product *= bestGeode(blueprints[i], stash, robots, 0, PART_TWO_TIME); + } + printf("%u\n", product); +} + +int bestGeode(BLUEPRINT blueprint, int stash[], int robots[], int sum, int time) { + if (time <= 0) { + return sum; + } + + int pompom = 0; + for (int i = 1; i <= time; i+=2) { + pompom += i; + } + if (bestMax > sum + pompom) { + return sum; + } + + int max = sum; + int stashCopy[4]; + memcpy(stashCopy, stash, 4*sizeof(int)); + int robotsCopy[4]; + memcpy(robotsCopy, robots, 4*sizeof(int)); + + // At every step we decide what robot will we build next (if we can) + int mostGeodes = 0; + + // Ore robot + int timeCost = 0, timeCost2 = 0; + while (stash[0] + timeCost*robots[0] < blueprint.ore_cost) { + timeCost++; + } + // Build time + timeCost++; + // We don't have the time left to build this + if (time - timeCost >= 0) { + for (int j = 0; j < 4; j++) { + stash[j] = stash[j] + timeCost * robots[j]; + } + stash[0] -= blueprint.ore_cost; + robots[0]++; + mostGeodes = bestGeode(blueprint, stash, robots, sum, time - timeCost); + memcpy(stash, stashCopy, 4*sizeof(int)); + memcpy(robots, robotsCopy, 4*sizeof(int)); + + if (mostGeodes > max) { + max = mostGeodes; + } + } + + // Clay robot + timeCost = 0; + while (stash[0] + timeCost*robots[0] < blueprint.clay_cost) { + timeCost++; + } + // Build time + timeCost++; + // We don't have the time left to build this + if (time - timeCost >= 0) { + for (int j = 0; j < 4; j++) { + stash[j] = stash[j] + timeCost * robots[j]; + } + stash[0] -= blueprint.clay_cost; + robots[1]++; + mostGeodes = bestGeode(blueprint, stash, robots, sum, time - timeCost); + memcpy(stash, stashCopy, 4*sizeof(int)); + memcpy(robots, robotsCopy, 4*sizeof(int)); + if (mostGeodes > max) { + max = mostGeodes; + } + } + + // Obsidian robot + // Only if we have at least 1 clay robot + if (robots[1] > 0) { + timeCost = timeCost2 = 0; + while (stash[0] + timeCost*robots[0] < blueprint.obsidian_cost[0]) { + timeCost++; + } + while (stash[1] + timeCost2*robots[1] < blueprint.obsidian_cost[1]) { + timeCost2++; + } + + timeCost = max(timeCost, timeCost2); + // build time + timeCost++; + if (time - timeCost >= 0) { + for (int j = 0; j < 4; j++) { + stash[j] = stash[j] + timeCost * robots[j]; + } + stash[0] -= blueprint.obsidian_cost[0]; + stash[1] -= blueprint.obsidian_cost[1]; + robots[2]++; + mostGeodes = bestGeode(blueprint, stash, robots, sum, time - timeCost); + memcpy(stash, stashCopy, 4*sizeof(int)); + memcpy(robots, robotsCopy, 4*sizeof(int)); + if (mostGeodes > max) { + max = mostGeodes; + } + } + } + + // Geode robot + // Only if we have at least 1 obsidian robot + if (robots[2] > 0) { + timeCost = timeCost2 = 0; + while (stash[0] + timeCost*robots[0] < blueprint.geode_cost[0]) { + timeCost++; + } + while (stash[2] + timeCost2*robots[2] < blueprint.geode_cost[1]) { + timeCost2++; + } + + timeCost = max(timeCost, timeCost2); + // build time + timeCost++; + if (time - timeCost >= 0) { + for (int j = 0; j < 4; j++) { + stash[j] = stash[j] + timeCost * robots[j]; + } + stash[0] -= blueprint.geode_cost[0]; + stash[2] -= blueprint.geode_cost[1]; + robots[3]++; + mostGeodes = bestGeode(blueprint, stash, robots, sum + (time - timeCost), time - timeCost); + memcpy(stash, stashCopy, 4*sizeof(int)); + memcpy(robots, robotsCopy, 4*sizeof(int)); + if (mostGeodes > max) { + max = mostGeodes; + } + } + } + + if (max > bestMax) { + bestMax = max; + } + + return max; +}