#include #include #include #include #include #include using Int = long; using Register = char; using Operand = std::variant; enum class Opcode { set, sub, mul, jnz }; auto to_opcode(std::string const& s) -> Opcode { if (s == "set") { return Opcode::set; } if (s == "sub") { return Opcode::sub; } if (s == "mul") { return Opcode::mul; } if (s == "jnz") { return Opcode::jnz; } abort(); } static auto operand(std::string const& s, std::size_t idx) -> std::pair { if (idx >= s.size()) { return {std::monostate{}, idx}; } if (s[idx] >= 'a' && s[idx] <= 'z') { return {s[idx], idx + 1}; } std::size_t end{0}; auto v{std::stol(s.substr(idx), &end)}; return {v, idx + end}; } struct Instruction { auto opcode() const noexcept -> Opcode { return opcode_; } auto op1() const noexcept -> Operand { return op1_; } auto op2() const noexcept -> Operand { return op2_; } static auto instruction(std::string const& s) -> Instruction { auto opcode{to_opcode(s.substr(0, 3))}; auto [op1, idx] = operand(s, 4); auto [op2, idx2] = operand(s, idx + 1); return {opcode, op1, op2}; } private: Instruction(Opcode opcode, Operand op1, Operand op2) : opcode_(opcode), op1_(op1), op2_(op2) {} Opcode opcode_; Operand op1_; Operand op2_; }; using Instructions = std::vector; struct State { explicit State(Instructions const& instructions) : instructions_(instructions) {} void execute() { while (pc_ >= 0 && pc_ < instructions_.size()) { auto const& instruction{instructions_[pc_]}; switch (instruction.opcode()) { case Opcode::sub: set(instruction.op1(), value(instruction.op1()) - value(instruction.op2())); break; case Opcode::jnz: if (value(instruction.op1()) != 0) { pc_ += value(instruction.op2()) - 1; } break; case Opcode::mul: set(instruction.op1(), value(instruction.op1()) * value(instruction.op2())); ++mul_count_; break; case Opcode::set: set(instruction.op1(), value(instruction.op2())); break; default: abort(); } ++pc_; } std::cout << "Mul executed: " << mul_count_ << " times.\n"; } void set(Register r, Int value) { registers_.insert_or_assign(r, value); } private: void set(Operand const& op, Int value) { if (std::holds_alternative(op)) { registers_.insert_or_assign(std::get(op), value); } else { abort(); } } auto value(Operand const& op) const -> Int { if (std::holds_alternative(op)) { auto it{registers_.find(std::get(op))}; return it == registers_.end() ? 0 : it->second; } if (std::holds_alternative(op)) { return std::get(op); } abort(); } Instructions instructions_; std::map registers_; Int pc_{0}; Int mul_count_{0}; }; auto main() -> int { Instructions instructions; std::string line; while (std::getline(std::cin, line) && !line.empty()) { instructions.push_back(Instruction::instruction(line)); } State cpu{instructions}; cpu.execute(); return 0; }