#include #include #include #include #include enum Command { NOOP = 1, ADDX, }; Command ParseCommand(const std::string &str) { if(str.size() < 4) return Command::NOOP; std::string head = str.substr(0, 4); if(head == "noop") return Command::NOOP; else if(head == "addx") return Command::ADDX; std::cerr << "Missing command type \"" << head << "\"." << std::endl; exit(-1); } void StepCycles(long &cycle, const Command &command, const long &x); void IncrementAndDraw(const long &x, long &cycle); long Report(const long &cycle, const long &x); void ApplyAction(const std::pair &command, long &x); int main() { std::ifstream ifs("data.txt"); if(!ifs.is_open()) { std::cerr << "Missing data.txt." << std::endl; return -1; } unsigned long total = 0; unsigned long total_pt2 = 0; std::vector > commands; for(std::string line; std::getline(ifs, line); ) { if(line == "") continue; auto cmd = ParseCommand(line); if(cmd == Command::NOOP) commands.push_back({cmd, ""}); else commands.push_back({cmd, line.substr(5)}); } long cycle = 1; long x = 1; for(const auto &command : commands) { // Step 1: Increase cycle count of command to see if we would have reported StepCycles(cycle, command.first, x); // Step 2: Report, if needed: total += Report(cycle, x); // Step 3: Perform command action: ApplyAction(command, x); } while(cycle <= 220) { StepCycles(cycle, Command::NOOP, x); total += Report(cycle, x); } std::cout << "Ended on cycle #" << cycle << ", value of x: " << x << std::endl; std::cout << " Total: " << total << std::endl; std::cout << "PT2 Total: " << total_pt2 << std::endl; return 0; } void StepCycles(long &cycle, const Command &command, const long &x) { switch(command) { case Command::NOOP: IncrementAndDraw(x, cycle); break; case Command::ADDX: for(auto i = 0; i < 2; ++i) IncrementAndDraw(x, cycle); break; default: std::cerr << "Missing ability to parse command type." << std::endl; exit(-1); break; }; } long Report(const long &cycle, const long &x) { static long last_reported_cycle = -20; auto next_cycle = last_reported_cycle + 40; if(cycle > next_cycle) { // std::cout << "Cycle #" << next_cycle << ": " // << next_cycle << " * " << x << " = " // << next_cycle * x << std::endl; last_reported_cycle += 40; return next_cycle * x; } return 0; // no change } void ApplyAction(const std::pair &command, long &x) { switch(command.first) { case Command::NOOP: // std::cout << "NOOP" << std::endl; // noop break; case Command::ADDX: // std::cout << "ADDX " << command.second << ": x goes from " << x << " to "; x += std::atoi(command.second.c_str()); // std::cout << x << std::endl; break; default: std::cerr << "Missing ability to parse command type." << std::endl; exit(-1); break; }; } void IncrementAndDraw(const long &x, long &cycle) { static int drawing_index = 1; // 1 to 40 // NOTE(dev): using -0 and +2 instead of -1 and +1 to account for 0-based vs 1-based if(drawing_index >= x - 0 && drawing_index <= x + 2) // within one or on target std::cout << "#"; else std::cout << "."; ++cycle; if(++drawing_index > 40) { std::cout << std::endl; drawing_index = 1; } }