#include #include #include #include #include #include #include #include #include long long defaultX = 0; long long totalUses = 0; // #define DEBUG namespace Variables { std::map variables; long long get(const std::string& key) { auto it = variables.find(key); if (it == variables.end()) { long long defaultVal = key == "X" ? defaultX : 0; variables.insert({key, defaultVal}); return defaultVal; } return it->second; } void reset() { variables.clear(); } void increase(const std::string& key) { long long value = get(key) + 1; variables[key] = value; } void clear(const std::string& key) { variables[key] = 0; } }; class Instruction { public: std::string variable; std::string type; int uses = 0; virtual void handle() = 0; virtual void printUses(int indentation) { for (int i = 0; i < indentation; i++) { std::cout << "| "; } std::cout << type << " " << variable << " " << uses << std::endl; } virtual ~Instruction() = default; Instruction(std::string variable, std::string type) : variable(variable), type(type) { } }; class PrintInstruction : public Instruction { public: PrintInstruction(const std::string& variable) : Instruction(variable, "print") { } void handle() override { std::cout << Variables::get(variable) << " "; } }; class ClearInstruction : public Instruction { public: ClearInstruction(const std::string& variable) : Instruction(variable, "clear") { } void handle() override { Variables::clear(variable); } }; class IncreaseInstruction : public Instruction { public: IncreaseInstruction(const std::string& variable) : Instruction(variable, "increase") { } void handle() override { Variables::increase(variable); } }; class RepeatInstruction : public Instruction { public: std::vector> instructions; void handle() override { auto guh = variable == "" ? 1 : Variables::get(variable); for (int i = 0; i < guh; i++) { for (auto ins : instructions) { totalUses++; ins->uses++; ins->handle(); } } } RepeatInstruction(std::string variable = "") : Instruction(variable, "repeat") { } void printUses(int indentation) override { for (int i = 0; i < indentation; i++) { std::cout << "| "; } std::cout << type << " " << variable << " " << uses << std::endl; for (auto ins : instructions) { ins->printUses(indentation + 1); } } }; std::shared_ptr readPrint(const std::vector& words, std::size_t& index) { std::string str = words.at(++index); return std::make_shared(str); } std::shared_ptr readClear(const std::vector& words, std::size_t& index) { std::string str = words.at(++index); return std::make_shared(str); } std::shared_ptr readIncrease(const std::vector& words, std::size_t& index) { std::string str = words.at(++index); return std::make_shared(str); } std::shared_ptr readRepeat(const std::vector& words, std::size_t& index) { std::string times = words.at(++index); index += 2; return std::make_shared(times); } int calcSteps(int collatz) { int steps = 0; while (true) { steps++; if (collatz % 2 == 0) collatz /= 2; else collatz = collatz * 3 + 1; if (collatz == 1) return steps; } } void collatzCheck() { // std::vector> guh; // // int largest = 0; // for (int i = 1; i < 1000; i++) { // int n = calcSteps(i); // int g = std::ceil(( n - 40 ) / i); // // if (g > largest) { // std::cout << g << " at " << i << std::endl; // largest = g; // } // guh.push_back({i, n}); // } // // std::sort(guh.begin(), guh.end(), [](std::pair i1, std::pair i2) { return i1.second < i2.second; }); // for (auto [i, n] : guh) { // std::cout << i << ": " << n << std::endl; // } } int main([[maybe_unused]] int argc, [[maybe_unused]] char *argv[]) { collatzCheck(); auto base = std::make_shared(); std::stack> stack; stack.push(base); std::vector words; std::string temp; while (std::cin >> temp) { int commentIndex = temp.find('#'); if (commentIndex >= 0) { if (commentIndex > 0) { temp = temp.substr(0, commentIndex); words.push_back(temp); } std::string line; std::getline(std::cin, line); continue; } if (temp == "END") { goto END; } else { words.push_back(temp); } } END: std::size_t index = 0; while (index < words.size()) { std::string str = words.at(index); switch (str.at(0)) { case 'P' /* Print */: { stack.top()->instructions.push_back(readPrint(words, index)); break; } case 'C' /* Clear */: { stack.top()->instructions.push_back(readClear(words, index)); break; } case 'I' /* Increase */: { stack.top()->instructions.push_back(readIncrease(words, index)); break; } case 'R' /* Repeat */: { auto guh = readRepeat(words, index); stack.top()->instructions.push_back(guh); stack.push(guh); break; } case ')' /* Repeat end */: { stack.pop(); break; } } index++; } if (false) { defaultX = 100; Variables::reset(); base->handle(); base->printUses(0); std::cout << "total" << totalUses << std::endl; } else { for (int i = 1; i <= 1000; i++) { defaultX = i; Variables::reset(); base->handle(); if (totalUses >= 60'000'000) { base->printUses(0); break; } } } std::cout << "total" << totalUses << std::endl; } // Tuleva X on parillinen kun D on pariton