Guest User

Untitled

a guest
Dec 7th, 2024
41
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.54 KB | None | 0 0
  1. #include <iostream>
  2. #include <stdexcept>
  3. #include <unordered_map>
  4. #include <algorithm>
  5. #include <sstream>
  6. #include <climits>
  7. #include <fstream>
  8. #include <vector>
  9. #include <string>
  10. #include <cctype>
  11. #include <cmath>
  12.  
  13. // Uncomment when solving for CF
  14. #include <stack>
  15. #define Stack stack
  16.  
  17. // Uncomment when using local files
  18. //#include "stack.cpp" // User-defined implementation of Stack
  19.  
  20. using namespace std;
  21.  
  22. unordered_map<string, int> variables;
  23. const string throwMessage = "Invalid Syntax";
  24.  
  25. string trim(const string &s)
  26. {
  27.     size_t start = s.find_first_not_of(" \t\n\r\f\v");
  28.  
  29.     size_t end = s.find_last_not_of(" \t\n\r\f\v");
  30.  
  31.     if (start == string::npos)
  32.         return "";
  33.  
  34.     return s.substr(start, end - start + 1);
  35. }
  36.  
  37. vector<string> split(const string &s, char delimiter, int maxSplits = INT_MAX)
  38. {
  39.     vector<string> tokens;
  40.     string token;
  41.  
  42.     int i = 0;
  43.     for (; i < s.size() && maxSplits > 0; i++)
  44.     {
  45.         if (s[i] == delimiter)
  46.         {
  47.             token = trim(token);
  48.             tokens.push_back(token);
  49.             maxSplits--;
  50.             token = "";
  51.         }
  52.         else
  53.         {
  54.             token += s[i];
  55.         }
  56.     }
  57.  
  58.     token = trim(token);
  59.     if (token != "")
  60.         tokens.push_back(token);
  61.  
  62.     token = "";
  63.  
  64.     while (i < s.size())
  65.     {
  66.         token += s[i];
  67.         i++;
  68.     }
  69.  
  70.     token = trim(token);
  71.     if (token != "")
  72.         tokens.push_back(token);
  73.  
  74.     return tokens;
  75. }
  76.  
  77. bool isAllDigits(string &s)
  78. {
  79.     for (char c : s)
  80.     {
  81.         if (!isdigit(c))
  82.         {
  83.             return false;
  84.         }
  85.     }
  86.     return true;
  87. }
  88.  
  89. bool isAllAlpha(const string &s)
  90. {
  91.     for (char c : s)
  92.     {
  93.         if (!isalpha(c))
  94.         {
  95.             return false;
  96.         }
  97.     }
  98.     return true;
  99. }
  100.  
  101. bool isOperator(const string &token)
  102. {
  103.     return token == "+" || token == "-" || token == "*" ||
  104.            token == "/" || token == ">" || token == "<" ||
  105.            token == ">=" || token == "<=" || token == "==" ||
  106.            token == "!=" || token == "%" || token == "**" ||
  107.            token == "||" || token == "&&" ||
  108.            token == "^" || token == "|" || token == "&";
  109. }
  110.  
  111. int getPrecedence(const string &op)
  112. {
  113.     if (op == "**")
  114.         return 5;
  115.     if (op == "*" || op == "/" || op == "%")
  116.         return 4;
  117.     if (op == "+" || op == "-")
  118.         return 3;
  119.     if (op == ">" || op == "<")
  120.         return 2;
  121.     if (op == ">=" || op == "<=")
  122.         return 2;
  123.     if (op == "==" || op == "!=")
  124.         return 2;
  125.     if (op == "&&" || op == "||")
  126.         return 1;
  127.     if (op == "^" || op == "|" || op == "&")
  128.         return 0;
  129.     return -1;
  130. }
  131.  
  132. vector<string> normalToRPN(vector<string> &tokens)
  133. {
  134.     Stack<string> st;
  135.     vector<string> result;
  136.  
  137.     for (string &token : tokens)
  138.     {
  139.         if (isAllDigits(token))
  140.         {
  141.             result.push_back(token);
  142.         }
  143.         else if (isAllAlpha(token))
  144.         {
  145.             result.push_back(token);
  146.         }
  147.         else if (isOperator(token))
  148.         {
  149.             while (!st.empty() && getPrecedence(st.top()) >= getPrecedence(token))
  150.             {
  151.                 result.push_back(st.top());
  152.                 st.pop();
  153.             }
  154.             st.push(token);
  155.         }
  156.         else if (token == "(")
  157.         {
  158.             st.push(token);
  159.         }
  160.         else if (token == ")")
  161.         {
  162.             while (!st.empty() && st.top() != "(")
  163.             {
  164.                 result.push_back(st.top());
  165.                 st.pop();
  166.             }
  167.             if (st.empty())
  168.             {
  169.                 throw invalid_argument(throwMessage);
  170.             }
  171.             st.pop();
  172.         }
  173.         else
  174.         {
  175.             throw invalid_argument(throwMessage);
  176.         }
  177.     }
  178.  
  179.     while (!st.empty())
  180.     {
  181.         if (st.top() == "(" || st.top() == ")")
  182.         {
  183.             throw invalid_argument(throwMessage);
  184.         }
  185.         result.push_back(st.top());
  186.         st.pop();
  187.     }
  188.  
  189.     return result;
  190. }
  191.  
  192. int evaluate(string &expression)
  193. {
  194.     vector<string> tokens = split(expression, ' ');
  195.     vector<string> rpn = normalToRPN(tokens);
  196.  
  197.     Stack<int> result;
  198.     for (string token : rpn)
  199.     {
  200.         if (!isOperator(token))
  201.         {
  202.             if (isAllDigits(token))
  203.             {
  204.                 result.push(stoi(token));
  205.             }
  206.             else if (isAllAlpha(token) && variables.count(token))
  207.             {
  208.                 result.push(variables[token]);
  209.             }
  210.             else
  211.             {
  212.                 throw invalid_argument("Invalid Expression");
  213.             }
  214.         }
  215.         else
  216.         {
  217.             if (result.size() < 2)
  218.                 throw invalid_argument("Invalid Expression");
  219.  
  220.             int num2 = result.top();
  221.             result.pop();
  222.             int num1 = result.top();
  223.             result.pop();
  224.  
  225.             int value = 0;
  226.             if (token == "-")
  227.                 value = num1 - num2;
  228.             if (token == "+")
  229.                 value = num1 + num2;
  230.             if (token == "&&")
  231.                 value = num1 && num2;
  232.             if (token == "||")
  233.                 value = num1 || num2;
  234.             if (token == "^")
  235.                 value = num1 ^ num2;
  236.             if (token == "|")
  237.                 value = num1 | num2;
  238.             if (token == "&")
  239.                 value = num1 & num2;
  240.             if (token == "**")
  241.             {
  242.                 if (num1 == 0 && num2 == 0)
  243.                     throw invalid_argument("Zero to the power of Zero is Undefined");
  244.                 value = pow(num1, num2);
  245.             }
  246.             if (token == "*")
  247.                 value = num1 * num2;
  248.             if (token == "/")
  249.             {
  250.                 if (num2 == 0)
  251.                     throw invalid_argument("Dividing by Zero is Undefined");
  252.                 value = num1 / num2;
  253.             }
  254.             if (token == "%")
  255.             {
  256.                 if (num2 == 0)
  257.                     throw invalid_argument("Mod by Zero is Undefined");
  258.                 value = num1 % num2;
  259.             }
  260.             if (token == ">")
  261.             {
  262.                 value = (num1 > num2) ? 1 : 0;
  263.             }
  264.             if (token == "<")
  265.             {
  266.                 value = (num1 < num2) ? 1 : 0;
  267.             }
  268.             if (token == ">=")
  269.             {
  270.                 value = (num1 >= num2) ? 1 : 0;
  271.             }
  272.             if (token == "<=")
  273.             {
  274.                 value = (num1 <= num2) ? 1 : 0;
  275.             }
  276.             if (token == "==")
  277.             {
  278.                 value = (num1 == num2) ? 1 : 0;
  279.             }
  280.             if (token == "!=")
  281.             {
  282.                 value = (num1 != num2) ? 1 : 0;
  283.             }
  284.  
  285.             result.push(value);
  286.         }
  287.     }
  288.  
  289.     if (result.size() != 1)
  290.         throw invalid_argument("Invalid Expression");
  291.     return result.top();
  292. };
  293.  
  294. void executeLine(string &line)
  295. {
  296.     if (line[0] == '#')
  297.         return;
  298.     if (line.find(" = ") != string::npos)
  299.     {
  300.         vector<string> tokens = split(line, '=', 1);
  301.         variables[tokens[0]] = evaluate(tokens[1]);
  302.     }
  303.     else if (isAllAlpha(line))
  304.     {
  305.         if (!variables.count(line))
  306.             throw invalid_argument("Identifier " + line + " is undefined");
  307.  
  308.         cout << variables[line] << endl;
  309.     }
  310.     else
  311.     {
  312.         cout << evaluate(line) << endl;
  313.     }
  314. };
  315.  
  316. void executePrint(string content)
  317. {
  318.     content = trim(content);
  319.     if (content == "")
  320.         throw invalid_argument("Empty Print Statement");
  321.  
  322.     if (variables.count(content))
  323.     {
  324.         cout << variables[content];
  325.     }
  326.     else
  327.     {
  328.         if (content[0] == '"' && content.back() == '"')
  329.         {
  330.             cout << content.substr(1, content.size() - 2);
  331.         }
  332.         else
  333.         {
  334.             throw invalid_argument("Undefined variable or invalid string: " + content);
  335.         }
  336.     }
  337. }
  338.  
  339. void executePrintln(string content)
  340. {
  341.     content = trim(content);
  342.     if (content == "")
  343.         throw invalid_argument("Empty Print Statement");
  344.  
  345.     if (variables.count(content))
  346.     {
  347.         cout << variables[content] << endl;
  348.     }
  349.     else
  350.     {
  351.         if (content[0] == '"' && content.back() == '"')
  352.         {
  353.             cout << content.substr(1, content.size() - 2) << endl;
  354.         }
  355.         else
  356.         {
  357.             throw invalid_argument("Undefined variable or invalid string: " + content);
  358.         }
  359.     }
  360. }
  361.  
  362. void executeRead(string variableName)
  363. {
  364.     variableName = trim(variableName);
  365.     if (variableName == "")
  366.         throw invalid_argument("Empty Read Statement");
  367.  
  368.     if (!isAllAlpha(variableName))
  369.         throw invalid_argument("Variable name must contain only alphabetic characters");
  370.  
  371.     int value;
  372.     cin >> value;
  373.  
  374.     variables[variableName] = value;
  375. }
  376.  
  377. void executeIfStatement(const vector<string> &lines, int &currentLineIndex)
  378. {
  379.     string ifLine = lines[currentLineIndex];
  380.     size_t start = ifLine.find(' ');
  381.  
  382.     if (start == string::npos)
  383.         throw invalid_argument("Invalid If Statement Syntax");
  384.  
  385.     string condition = trim(ifLine.substr(start + 1));
  386.     if (condition.empty())
  387.         throw invalid_argument("If statement missing condition");
  388.  
  389.     vector<string> ifBody;
  390.     currentLineIndex++;
  391.     while (currentLineIndex < lines.size() && lines[currentLineIndex][0] == ' ')
  392.     {
  393.         ifBody.push_back(trim(lines[currentLineIndex]));
  394.         currentLineIndex++;
  395.     }
  396.     currentLineIndex--;
  397.  
  398.     if (evaluate(condition) != 0)
  399.     {
  400.         for (string &line : ifBody)
  401.         {
  402.             executeLine(line);
  403.         }
  404.     }
  405. }
  406.  
  407. void excuteInstruction(string line)
  408. {
  409.     if (line.substr(0, 7) == "println")
  410.     {
  411.         executePrintln(trim(line.substr(8)));
  412.     }
  413.     else if (line.substr(0, 5) == "print")
  414.     {
  415.         executePrint(trim(line.substr(6)));
  416.     }
  417.     else if (line.substr(0, 4) == "read")
  418.     {
  419.         executeRead(trim(line.substr(5)));
  420.     }
  421.     else
  422.     {
  423.         executeLine(line);
  424.     }
  425. }
  426.  
  427. void executeWhileLoop(const vector<string> &lines, int &currentLineIndex)
  428. {
  429.     string whileLine = lines[currentLineIndex];
  430.     size_t start = whileLine.find(' ');
  431.     if (start == string::npos)
  432.         throw invalid_argument("Invalid While Loop Syntax");
  433.  
  434.     string condition = trim(whileLine.substr(start + 1));
  435.     if (condition.empty())
  436.         throw invalid_argument("While loop missing condition");
  437.  
  438.     vector<string> loopBody;
  439.     currentLineIndex++;
  440.     while (currentLineIndex < lines.size() && lines[currentLineIndex][0] == ' ')
  441.     {
  442.         loopBody.push_back(trim(lines[currentLineIndex]));
  443.         currentLineIndex++;
  444.     }
  445.     currentLineIndex--;
  446.  
  447.     int maxIterations = 1000;
  448.     int iteration = 0;
  449.  
  450.     while (evaluate(condition) != 0)
  451.     {
  452.         if (++iteration > maxIterations)
  453.             throw runtime_error("Infinite loop detected");
  454.         for (string &line : loopBody)
  455.         {
  456.             excuteInstruction(trim(line));
  457.         }
  458.     }
  459. }
  460.  
  461. void handleInputLines(vector<string> &lines)
  462. {
  463.     for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++)
  464.     {
  465.         string line = lines[lineNumber];
  466.         if (line.substr(0, 7) == "println")
  467.         {
  468.             executePrintln(trim(line.substr(8)));
  469.         }
  470.         else if (line.substr(0, 5) == "print")
  471.         {
  472.             executePrint(trim(line.substr(6)));
  473.         }
  474.         else if (line.substr(0, 4) == "read")
  475.         {
  476.             executeRead(trim(line.substr(5)));
  477.         }
  478.         else if (line.substr(0, 5) == "while")
  479.         {
  480.             executeWhileLoop(lines, lineNumber);
  481.         }
  482.         else if (line.substr(0, 2) == "if")
  483.         {
  484.             executeIfStatement(lines, lineNumber);
  485.         }
  486.         else
  487.         {
  488.             executeLine(line);
  489.         }
  490.     }
  491. }
  492.  
  493. int main(int argc, char **argv)
  494. {
  495.     if (argc == 1) {
  496.         // used for solving problems in Codeforces, Codechef, Atcoder, etc
  497.         // exampe code for solving this problem in CF using this language
  498.         // link : https://codeforces.com/contest/2009/problem/A
  499.         string instructions = "\nread test\nwhile test > 0\n    read a\n    read b\n    b - a\n    test = test - 1";
  500.  
  501.         istringstream fileStream(instructions);
  502.         string line;
  503.         vector<string> lines;
  504.  
  505.         while (getline(fileStream, line)) {
  506.             if (line[0] == ' ') {
  507.                 lines.push_back(line);
  508.                 continue;
  509.             }
  510.             line = trim(line);
  511.             if (line == "") {
  512.                 continue;
  513.             }
  514.             lines.push_back(line);
  515.  
  516.         }
  517.  
  518.         handleInputLines(lines);
  519.         return 0;
  520.     }
  521.     else if (argc == 2)
  522.     {
  523.  
  524.         ifstream file(argv[1]);
  525.  
  526.         if (!file)
  527.         {
  528.             cerr << "Error opening the file" << endl;
  529.             return 1;
  530.         }
  531.  
  532.         string line = "";
  533.         vector<string> lines;
  534.         while (getline(file, line))
  535.         {
  536.             if (line[0] == ' ')
  537.             {
  538.                 lines.push_back(line);
  539.                 continue;
  540.             }
  541.             line = trim(line);
  542.             if (line == "")
  543.                 continue;
  544.             lines.push_back(line);
  545.         }
  546.  
  547.         try
  548.         {
  549.             handleInputLines(lines);
  550.         }
  551.         catch (exception &e)
  552.         {
  553.             cerr << e.what() << endl;
  554.             return 1;
  555.         }
  556.     }
  557.     else
  558.     {
  559.         cerr << "Must provide file name" << endl;
  560.         return 1;
  561.     }
  562.  
  563.     return 0;
  564. }
Advertisement
Add Comment
Please, Sign In to add comment