Skip to content

Commit

Permalink
Advent of Code day 19
Browse files Browse the repository at this point in the history
  • Loading branch information
lerno committed Dec 20, 2022
1 parent f025c77 commit 3600745
Show file tree
Hide file tree
Showing 2 changed files with 209 additions and 0 deletions.
30 changes: 30 additions & 0 deletions blueprint.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Blueprint 1: 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 2: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 9 clay. Each geode robot costs 3 ore and 9 obsidian.
Blueprint 3: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 2 ore and 12 obsidian.
Blueprint 4: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 19 clay. Each geode robot costs 3 ore and 10 obsidian.
Blueprint 5: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 14 clay. Each geode robot costs 3 ore and 16 obsidian.
Blueprint 6: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 4 ore and 8 obsidian.
Blueprint 7: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 14 clay. Each geode robot costs 4 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 12 clay. Each geode robot costs 4 ore and 19 obsidian.
Blueprint 9: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 4 ore and 11 obsidian.
Blueprint 10: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 3 ore and 10 obsidian.
Blueprint 11: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 7 clay. Each geode robot costs 2 ore and 19 obsidian.
Blueprint 12: 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 3 ore and 14 obsidian.
Blueprint 13: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 8 clay. Each geode robot costs 2 ore and 14 obsidian.
Blueprint 14: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 17 clay. Each geode robot costs 2 ore and 10 obsidian.
Blueprint 15: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 9 clay. Each geode robot costs 3 ore and 15 obsidian.
Blueprint 16: 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 17: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 9 clay. Each geode robot costs 3 ore and 9 obsidian.
Blueprint 18: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 20 obsidian.
Blueprint 19: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 3 ore and 13 obsidian.
Blueprint 20: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 4 ore and 8 obsidian.
Blueprint 21: 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 22: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 20 obsidian.
Blueprint 23: 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 24: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 13 clay. Each geode robot costs 2 ore and 9 obsidian.
Blueprint 25: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 12 clay. Each geode robot costs 3 ore and 15 obsidian.
Blueprint 26: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 18 clay. Each geode robot costs 4 ore and 8 obsidian.
Blueprint 27: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 19 clay. Each geode robot costs 4 ore and 15 obsidian.
Blueprint 28: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 20 clay. Each geode robot costs 3 ore and 14 obsidian.
Blueprint 29: 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 30: 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 3 ore and 7 obsidian.
179 changes: 179 additions & 0 deletions day19.c3
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
module day19;
import std::io;
import std::math;
import std::map;
import std::array::list;

define BlueprintList = List<Blueprint>;

const usz ORE = 0;
const usz CLAY = 1;
const usz OBSIDIAN = 2;
const usz GEODE = 3;

BlueprintList blueprints;
struct Blueprint
{
int[<4>] ore_cost;
int[<4>] clay_cost;
int[<4>] obsidian_cost;
int[<4>] geode_cost;
int[<4>] max_cost;
}

struct GameState
{
int[<4>] goods;
int[<4>] robots;
bool[<4>] block_robot;
bool[<4>] temp_block;
}

fn void load_blueprints()
{
File f;
f.open("blueprint.txt", "rb")!!;
blueprints.init();
defer catch(f.close());
while (!f.eof())
{
@pool()
{
Blueprint print;
char[] line = f.tgetline();
char[][] split = str::tsplit(line, "Each ore robot costs ");
split = str::tsplit(split[1], " ore. Each clay robot costs ");
print.ore_cost = { [ORE] = str::to_int(split[0])!! };
split = str::tsplit(split[1], " ore. Each obsidian robot costs ");
print.clay_cost = { [ORE] = str::to_int(split[0])!! };
split = str::tsplit(split[1], " clay. Each geode robot costs ");
char[][] split2 = str::tsplit(split[0], " ore and ");
print.obsidian_cost = {
[ORE] = str::to_int(split2[0])!!,
[CLAY] = str::to_int(split2[1])!!
};
split2 = str::tsplit(split[1], " ore and ");
print.geode_cost = {
[ORE] = str::to_int(split2[0])!!,
[OBSIDIAN] = str::to_int(split2[1][..^11])!!
};
print.max_cost = math::max(math::max(math::max(print.geode_cost, print.obsidian_cost), print.clay_cost), print.ore_cost);
blueprints.append(print);
};
}
}

fn int do_next_day(int day, GameState state, Blueprint* b)
{
if (day == 0) return state.goods[GEODE];
if (day == 1) return state.goods[GEODE] + state.robots[GEODE];
int best_result = -1;
bool[<4>] temp_block = { };
if (state.goods.comp_ge(b.geode_cost).and())
{
return {|
GameState copy_state = state;
copy_state.temp_block = {};
copy_state.goods += state.robots;
copy_state.goods -= b.geode_cost;
copy_state.robots[GEODE]++;
return do_next_day(day - 1, copy_state, b);
|};
}
if (day == 2) return state.goods[GEODE] + state.robots[GEODE] * 2;

bool temp_block_obsidian = false;
if EXIT: (!state.temp_block[OBSIDIAN] && !state.block_robot[OBSIDIAN] && state.goods.comp_ge(b.obsidian_cost).and())
{
if (state.robots[OBSIDIAN] * day + state.goods[OBSIDIAN] >= b.max_cost[OBSIDIAN] * day)
{
state.block_robot[OBSIDIAN] = true;
break EXIT;
}
int result = {|
GameState copy_state = state;
copy_state.temp_block = { };
copy_state.goods += state.robots;
copy_state.goods -= b.obsidian_cost;
copy_state.robots[OBSIDIAN]++;
return do_next_day(day - 1, copy_state, b);
|};
if (result > best_result) best_result = result;
temp_block[OBSIDIAN] = true;
}

if EXIT: (!state.temp_block[CLAY] && !state.block_robot[CLAY] && state.goods.comp_ge(b.clay_cost).and())
{
if (state.robots[CLAY] * day + state.goods[CLAY] >= b.max_cost[CLAY] * day)
{
state.block_robot[CLAY] = true;
break EXIT;
}
int result = {|
GameState copy_state = state;
copy_state.temp_block = { };
copy_state.goods += state.robots;
copy_state.goods -= b.clay_cost;
copy_state.robots[CLAY]++;
return do_next_day(day - 1, copy_state, b);
|};
if (result > best_result) best_result = result;
temp_block[CLAY] = true;
}
if EXIT: (!state.block_robot[ORE] && state.goods.comp_ge(b.ore_cost).and())
{
if (state.robots[ORE] * day + state.goods[ORE] >= b.max_cost[ORE] * day)
{
state.block_robot[ORE] = true;
break EXIT;
}
int result = {|
GameState copy_state = state;
copy_state.temp_block = { };
copy_state.goods += state.robots;
copy_state.goods -= b.ore_cost;
copy_state.robots[ORE]++;
return do_next_day(day - 1, copy_state, b);
|};
temp_block[ORE] = true;
if (result > best_result) best_result = result;
}
state.goods += state.robots;
state.temp_block = state.temp_block | temp_block;
int result = do_next_day(day - 1, state, b);
return best_result > result ? best_result : result;
}

fn void part1()
{
int quality_sum = 0;
foreach (int i, Blueprint b : blueprints)
{
GameState state = {};
state.robots[ORE] = 1;
int geodes = do_next_day(24, state, &b);
quality_sum += (i + 1) * geodes;
}
io::printfln("Quality sum: %d", quality_sum);
}

fn void part2()
{
long quality = 1;
foreach (int i, Blueprint b : blueprints)
{
if (i > 2) break;
GameState state = {};
state.robots[ORE] = 1;
long geodes = do_next_day(32, state, &b);
quality *= geodes;
}
io::printfln("Quality product: %d", quality);
}

fn void main()
{
load_blueprints();
part1();
part2();
}

0 comments on commit 3600745

Please sign in to comment.