diff --git a/DIRECTORY.md b/DIRECTORY.md index e68f68aec..b38f5fdbb 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -190,6 +190,7 @@ * [Palindrome Of Number](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/palindrome_of_number.cpp) * [Paranthesis Matching](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/paranthesis_matching.cpp) * [Pascal Triangle](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/pascal_triangle.cpp) + * [Postfix Evaluation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/postfix_evaluation.cpp) * [Primality Test](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/primality_test.cpp) * [Smallest Circle](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/smallest_circle.cpp) * [Sparse Matrix](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/sparse_matrix.cpp) diff --git a/others/postfix_evaluation.cpp b/others/postfix_evaluation.cpp new file mode 100644 index 000000000..1ea77c6f8 --- /dev/null +++ b/others/postfix_evaluation.cpp @@ -0,0 +1,178 @@ +/** + * @file + * @brief Evaluation of [Postfix Expression](https://en.wikipedia.org/wiki/Reverse_Polish_notation) + * @author [Darshana Sarma](https://github.com/Darshana-Sarma) + * @details + * Create a stack to store operands (or values). + * Scan the given expression and do following for every scanned element. + * If the element is a number, push it into the stack + * If the element is a operator, pop operands for the operator from stack. + * Evaluate the operator and push the result back to the stack + * When the expression is ended, the number in the stack is the final answer + */ +#include // for all_of +#include // for std::array +#include // for assert +#include // for io operations +#include // for stof + +/** + * @namespace others + * @brief Other algorithms + */ +namespace others { +/** + * @namespace postfix_expression + * @brief Functions for Postfix Expression algorithm + */ +namespace postfix_expression { + /** + * @brief Creates an array to be used as stack for storing values + */ +class Stack { + public: + std::array stack{}; ///< Array which will be used to store numbers in the input + int stackTop = -1; ///< Represents the index of the last value added to array. -1 means array is empty +}; + +/** + * @brief Pushing operand, also called the number in the array to the stack + * @param operand float value from the input array or evaluation + * @param stack stack containing numbers + * @returns none + */ +void push(float operand, Stack *stack) { + stack->stackTop++; + stack->stack[stack->stackTop] = operand; +} + +/** + * @brief Popping operand, also called the number from the stack + * @param stack stack containing numbers + * @returns operand float on top of stack + */ +float pop(Stack *stack) { + float operand = stack->stack[stack->stackTop]; + stack->stackTop--; + return operand; +} + +/** + * @brief Checks if scanned string is a number + * @param s scanned string + * @returns bool boolean value if string is number + */ +bool is_number(const std::string &s) { + return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit); +} + +/** + * @brief Evaluate answer using given last two operands from and operation + * @param a second last added operand which will be used for evaluation + * @param b last added operand which will be used for evaluation + * @param operation to be performed with respective floats + * @param stack containing numbers + * @returns none + */ +void evaluate(float a, float b, const std::string &operation, Stack *stack) { + float c = 0; + const char *op = operation.c_str(); + switch (*op) { + case '+': + c = a + b; // Addition of numbers + others::postfix_expression::push(c, stack); + break; + + case '-': + c = a - b; // Subtraction of numbers + others::postfix_expression::push(c, stack); + break; + + case '*': + c = a * b; // Multiplication of numbers + others::postfix_expression::push(c, stack); + break; + + case '/': + c = a / b; // Division of numbers + others::postfix_expression::push(c, stack); + break; + + default: + std::cout << "Operator not defined\n"; + break; + } +} + +/** + * @brief Postfix Evaluation algorithm to compute the value from given input + * array + * @tparam N number of array size + * @param input Array of characters consisting of numbers and operations + * @returns stack[stackTop] returns the top value from the stack + */ +template +float postfix_evaluation(std::array input) { + Stack stack; + int j = 0; + + while (j < N) { + std::string scan = input[j]; + if (is_number(scan)) { + push(std::stof(scan), &stack); + + } else { + float op2 = pop(&stack); + float op1 = pop(&stack); + + evaluate(op1, op2, scan, &stack); + } + j++; + } + + std::cout << stack.stack[stack.stackTop] << "\n"; + + return stack.stack[stack.stackTop]; +} +} // namespace postfix_expression +} // namespace others + + +/** + * @brief Test function 1 with input array + * {'2', '3', '1', '*', '+', '9', '-'} + * @returns none + */ +static void test_function_1() { + std::array input = {"2", "3", "1", "*", "+", "9", "-"}; + + float answer = others::postfix_expression::postfix_evaluation(input); + + assert(answer == -4); +} + +/** + * @brief Test function 2 with input array + * {'1', '2', '+', '2', '/', '5', '*', '7', '+'} + * @returns none + */ +static void test_function_2() { + std::array input = {"100", "200", "+", "2", "/", + "5", "*", "7", "+"}; + float answer = others::postfix_expression::postfix_evaluation(input); + + assert(answer == 757); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test_function_1(); + test_function_2(); + + std::cout << "\nTest implementations passed!\n"; + + return 0; +}