Advent of Code 2019 - Day 25Cryostasis

C++ | Problem statement | Source code | Tags: IntcodePuzzleManual inspection

This is a problem I really enjoyed, especially the gaming part. I bet there are more elegant ways to do it, but C++ makes parsing strings a huge pain, so I just manually played the game and drew the map. This is the first truly "interactive" Intcode program, since day 13 was solved by an intelligence. The game loop looks like:

std::cout << "\x1b[2J\x1b[1;1H" << start_prog(prog);
while (!prog.halted) {
std::string command;
std::getline(std::cin, command);
std::cout << "\x1b[2J\x1b[1;1H" << exchange_msg(prog, command);
}
cpp

I need to step over all input instructions and then all output instructions, so exchange_msg looks like:

std::string exchange_msg(Program &prog, const std::string &msg) {
prog.send_input(msg);
prog.send_input('\n');
prog.run_until_output(); // Step over input instructions
prog.run_until_input(); // Step over output instructions
return prog.pop_str_output();
}
cpp

The map I drew is as follows:

east

south

south

west

north

north

west

west

north

south

west

south

west

south

south

south

east

west

Hull Breach

Stables

Storage
giant electromagnet

Arcade
hologram

Science Lab

Hot Chocolate Fountain
molten lava

Gift Wrapping Center
infinite loop

Hallway
semiconductor

Passages

Corridor

Crew Quarters
hypercube

Holodeck
antenna

Kitchen
spool of cat6

Warp Drive Maintenance
photons

Navigation
escape pod

Security Checkpoint

Observatory
mouse

Engineering
shell

Sick Bay
whirled peas

I also experimented with which items are takeable. The final commands are:

std::vector<std::string> take_everything = {
"east", "south", "south", "take hologram",
"north", "north", "west", "south", "take mouse",
"east", "take shell",
"west", "west", "take whirled peas",
"east", "north", "west", "north", "north", "west", "take semiconductor",
"east", "south", "west", "south", "take hypercube",
"north", "east", "south", "west", "take antenna",
"south", "take spool of cat6",
"north", "west", "south", "south"
};
cpp

Once I execute these commands, I am at the security checkpoint with all items. The final step is to try all combinations of items to pass the checkpoint. There are 8 items, so I can just enumerate all combinations of drop x and take x commands. If the program halts after going south, I know I passed the checkpoint.

int n = items.size();
for (int mask = 0; mask < (1 << n); mask++) {
std::vector<std::string> to_drop;
std::vector<std::string> to_take;
for (int i = 0; i < n; i++) {
if (mask & (1 << i)) {
exchange_msg(prog, "drop " + items[i]);
} else {
exchange_msg(prog, "take " + items[i]);
}
}
auto output = exchange_msg(prog, "south");
if (prog.halted) {
std::cout << output;
break;
}
}
cpp