Stack with char array.How to execute "+" and "*" operations? - c++

I need to sum up or multiplie(it depends on which operation i push in array) first two numbers in stack. If I push operation + and my first two numbers are one and two then my stack value where I pushed + must be 3 , but in my result i get some symbol.
#include<iostream>
using namespace std;
#define MAX 10
int sp=-1;
char stack[MAX];
void push(){
if(sp==MAX-1){
cout<<"Error: stack overflow"<<endl;
return;
}
else{
char x;
cout<<"Insert value in stack: ";
cin>>x;
if(x=='*'){
if(sp>=1){
stack[++sp]=stack[1]*stack[0];
return;
}
else {
stack[++sp]=x;
return;
}
}
else if(x=='+'){
if(sp>=1){
stack[++sp]=stack[0]+stack[1];
return;
}
else {
stack[++sp]=x;
return;
}
}
else stack[++sp]=x;
}
}
void pop(){
if(sp==-1){
cout<<"Error: Stack empty";
return;
}
else{
cout<<stack[sp]<<endl;
sp--;
}
}
void top(){
if(sp==-1){
cout<<"Error: Stack empty";
return;
}
else{
cout<<stack[sp]<<endl;
}
}
void isEmpty(){
if(sp==-1){
cout<<"Stack is empty"<<endl;
return;
}
else{
cout<<"Stack is not empty"<<endl;
}
}
int main(){
for(int i=0;i<8;i++){
push();
}
top();
return 0;
}
Original stack:
3 4 3 + 1 2 * *
Stack that I need to get:
3 4 3 7 1 2 12 12
Stack that I get:
3 4 3 \ 1 2 _ _ (let's say something like that)

So you wanted to implement some postfix calculator. Very good that you noticed that a stack is needed.
For calculators you normally parse the input, store some results on a stack and then operate on the stack elements.
In contrast to what timo said, a parse stack can never be implemented with a std::stack because several top stack elements must be matched against the production in the grammar. For that reason a std::vector is the ideal container.
Now to the problem in the program. OP tries to store integer values and operators like "+" and "*" and results of calculations in the same datatype char. That cannot work. char stores characters like '+' or '*' or '1' but not 1. Internally a character is also encoded as a number (for example using ASCII) and a '1' would be equal to 49. And, if you look at results you cannot store '12' (for all the pros. Yes of course I know) in a char. 12 is a number, not a character.
And if you mix these types and do calculations with that then you get wrong results.
The solutions is to use Tokens and implement them as a std::variant. The variant can have a char an an int. Then your parse stack should be a std:::vector of Token.
This the right approach.
Additionally. In all standard recursive descent parsers you do not operate always on elements 0 and 1. You would replace the used values with the newly calculated one.
There is always the same approach
Read next Token and shift it on a stack
Match the top elements of the stack against a production
Reduce. Replace used elements with result
Some example of a different parser: See here.
This is somehow complicated. You may want to read about formal languages and parser.

Related

How to memoize or make recursive function with no apparent pattern?

Consider the following code, it was done for the Codeforces Round #731 (Div. 3), problem B https://codeforces.com/contest/1547/problem/B
In short, you are given a string and you are supposed to check if it's possible to create that string by sequentially adding letters in alphabetical order in either the front to the back of a string that starts empty.
Ex. the string "bac", you would first make the empty string be "a", then it can be either "ba" or "ab", then we try again and we get that based on the last result it now can be "bac", "cba", "abc", "cab". We get that is possible so we return true.
We can only do this procedure up to 26 times.
My code would make a tree, grabbing a base string as the head, and two children nodes, one with the letter added to the front and one with the letter added to the back, if neither worked out, then I would repeat it again with the children nodes.
I rewrote my solution and sent a completely different one, but I still wanted to know if there was a way to optimize so it could actually be executed. The code works if n is around 14 or 15, it stutters a little bit but can finish; but once it goes to 20 it will not even finish.
#include <iostream>
#include <string>
using namespace std;
bool solve(string fs,string s = "", int n = 0){
if(s == fs){
return true;
}
if(n > 26 || s.size() > fs.size()){
return false;
}
if(solve(fs,s+(char)(96+n+1),n+1) ||solve(fs,(char)(96+n+1)+s,n+1)){
return true;
}
return false;
}
int main(){
int t;cin>>t;
for(int i = 0; i < t; i++){
string p;
cin>>p;
if(solve(p)){
cout<<"YES"<<endl;
}
else{
cout<<"NO"<<endl;
}
}
}```
You are doing brute force approach which is time complexity of n * 2^n. And it looks pretty reasonable to fail(TLE) when n is around 20 (taking into account that t is up to 10000)
I cannot come up with a way for efficient memoization, however this problem can easily be solved with greedy approach. You don't have to check all the combinations. Check out the official editorial

Converting infix to postfix using c++

I'm trying to convert infix to postfix. I don't think my code is wrong but apparently it is because it doesn't work. I don't know what to change to make my code work properly.
(It worked for a bit before and now it doesn't)
I followed this code from geeksforgeeks: https://www.geeksforgeeks.org/stack-set-2-infix-to-postfix/ but I changed some of it because the code from the website was also wrong.
Sorry if my explanation is a bit unclear. Here's my code:
#include <bits/stdc++.h>
using namespace std;
int checks(char c)
{
if (c=='^')
{
return 1;
}
else if (c=='+' || c=='-')
{
return 2;
}
else if (c=='*' || c=='/')
{
return 3;
} else
{
return -1;
}
}
int main()
{
stack <char> stack;
string result, input;
cout<<"Enter your equation: ";
cin>> input;
for (int i=0; i<input.length(); i+=1)
{
if (input[i]=='(')
{
stack.push(input[i]);
} else if (isalnum(input[i]))
{
result+=input[i];
} else if (input[i]==')')
{
while(!stack.empty() && stack.top() != '(')
{
char c = stack.top();
stack.pop();
result += c;
}
if(stack.top() == '(')
{
char c = stack.top();
stack.pop();
}
} else
{
if (checks(stack.top()) >= checks(input[i]))
{
result+=stack.top();
stack.pop();
} else
{
stack.push(input[i]);
}
}
}
while(!stack.empty())
{
if (stack.top()=='(' || stack.top()==')')
{
stack.pop();
} else
{
result+=stack.top();
stack.pop();
}
}
cout<<"Result is: ";
cout<<result<<endl;
return 0;
}
Are your infix expressions using standard mathematical precedence? If so this will change things significantly compared to simple left to right evaluation.
You need to split your program into two phases. In the first phase you will parse the expression and build up the stack. In the second you will iterate over the stack and evaluate the result.
As I said, the parsing will be determined by the precedence. If you are using standard precedence then the usual approach (which you can read in Stroustrup's "The C++ Programming Language") is to use recursive descent. You would then have different precedences for parens, terms, factors, unary operators and literals. Use an enum for these, not magic numbers like 1, 2, 3.
You may skip step to actually create a tree structure , but have to keep in mind that infix notation is representable by tree while Polish notation is representable by stack. In (a+b)*(c+d) the * is topmost node, next level are two + and a, b,c,d. it's a symmetric tree because all operations commutative. But ((a+b)*(c+d))/3 is asymmetric, topmost node / is not commutative. Similar problem arise with -, because it's not commutative either.
E.g. possible option at each step can be (not a strict algorithm, but illustration how one should act, irt requires defense against malformed syntax)
Token is an "id".It's current level of tree node, scan further right
Token is a commutative operation. It's upper level of node. Next token would be a node of same level
Token is a non-commutative operation, / or -. It's upper level of node. Next token relates to node between current one and operation.
* and / have precedence above + and -, so they are nodes of lower level. E.g. a+b*c, First our tree was +: [a,b], then it is +:[a,*:[b,c]].
Token is (. Scan string and count all braces until you find matching ). E.g. each ( increases counter, each ) decreases. You found match if counter is 0. You have syntax error at hand if you get positive or negative while reaching terminal character..
Everything inside of () is a node of lower level. Scan it after finishing all upper levels.
To actually scan string, a state machine running in loop is required, the sign of finishing would be that there will be no tokens left to process. Can be recursive or not.
If you avoid creating tree, you have to go down and up along tokens in string itself, finding topmost node, push it to stack, then right and left nodes (in that order), push to stack, etc. When you pop stack, last-in first-out, operations would appear in proper order.
Paul Floyd is right to remind of that operator precedence can be used to sort order nodes or tokens, albeit doing it in std::stack is not possible because it got only push and pop operations and no reordering is possible, so you have to store that separately or scan and rescan string to push appropriate elements in.
(Note, than when you use some RPN calculator like on of those TI ones the stack of operations acts as a LILO stack, while when convert from syntax tree to RPN, it's LIFO)

Why is an error showing in my code for : Remove k duplicates in a string II #Leetcode 1209

In the question, for input: deeedbbcccbdaa and k=3 the output: aa. The explanation is that all 3 duplicates of every character are removed repeatedly. Since a has less than k=3 duplicates,and all the other characters have exactly 3 duplicates each, the final output is aa.
I have tried to solve the question as follows:
class Solution {
public:
string removeDuplicates(string s, int k) {
stack<pair<char,int>> st; // to store elements with their counts
string res; //final result string
pair<char,int> t; //to access the top
int n=s.size();
st.push({s[0],1});
for(char c: s){
t=st.top();
if (c!=t.first){
st.push(make_pair(c,1));
}
else{
t.second++;
}
if (t.second==k){
st.pop();
}
}
while(!st.empty()){
res=res+st.top().first;
st.pop();
}
reverse(res.begin(),res.end());
return res;
}
};
It is not running and a memory error is being displayed.Please help me out with the solution.
Edit:
the exact error shown is
Line 153: Char 16: runtime error: reference binding to misaligned address 0xbebebebebebec0b6 for type 'std::pair<char, int>', which requires 4 byte alignment (stl_deque.h)
0xbebebebebebec0b6: note: pointer points here
<memory cannot be printed>
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_deque.h:162:16
I think there is something wrong in the step where I compare each element of the string with the character in the top of the stack. I have tried searching for other answers in google and stackoverflow too and made a few changes to debug it.Maybe there is some core issue I am not aware of.

infinite loop in stack implementation c++

this is my first data structure program. I am implementing a simple stack using array with push, pop and initialize functions. I am getting an infinite loop as the output. Could you please tell me why is this so?
#include<iostream>
using namespace std;
# define SIZE 6
class stack{
public:
void init();
void push(int i);
int pop();
int top;
int stck[SIZE];//bydefault private
};
void stack::init()
{
top=0;
return;
}
void stack::push(int i)
{
if(top==SIZE)
{
cout<<"stack is full";
return;
}
else
{
top=top+1;
stck[top]= i;
return;
}
}
int stack::pop()
{
if(top==0)
{
cout<<"stack is empty. \n";
return 0;
}
else
{
top = top-1;
return(stck[top-1]);
}
}
int main()
{
stack stack1;
stack1.init();
int a;
int m;
while(a!=4)
{
cout<<"1. push 2. pop 3.display 4.exit .\n";
cin>>a;
if(a==1){
cout<< "enter value";
cin>>m;
stack1.push(m);
}
if(a==2)
{
cout<<"popped"<< stack1.pop();
}
if(a==3)
{
for(int k=0; k<=stack1.top;k++)
{
cout<<stack1.stck[k];
}
}
}
}
You never initialize a, so your program has undefined behaviour. Specifically, the while (a != 4) line performs an lvalue-to-rvalue conversion of a while its value is indeterminate, which the C++ standard explicitly states as undefined behaviour in section 4.1.
However, I doubt this is causing the issue at hand. In practice, unless the optimizer just optimized all your code out, your program should usually behave as expected; it's only when a == 4 on the first loop that you have problems. This doesn't make the code acceptable, but there's probably more to it.
I suspect the problem is that you use top to represent one past the number of elements. When you have zero elements, you point to the first; when you have one, you point to the second, etc. This means you're pointing to the first unused element.
However, in both your push and pop functions, you change top first and only then access the stack, but acting as if you didn't change it:
top = top + 1;
stck[top] = i;
When your stack is empty, this will set top to 1 and then access stck[1]. Meanwhile, stck[0] is left unset. When popping, you have the opposite:
top = top - 1;
return stck[top-1];
This sets top back to 0, but returns stck[-1], which is out of bounds.
I suspect that if you push SIZE values onto the stack, you will end up overwriting unrelated memory, which could cause all kinds of trouble. I still don't see how an infinite loop will follow, but given the behaviour is undefined, it is certainly a possible result.
(The alternative is that you at some point enter something other than a number. Seeing as you never check whether your input succeeded, if a != 4 and you enter something invalid, all further reads will fail, and a will remain unequal to 4. You could fix this by making changing your while to be
while (a != 4 && std::cin)
In that case, if you enter something invalid and std::cin goes into a non-good state, your loop (and thus program) will end.)
You only have a single loop, terminated based on user input.
If cin>>a fails, a will have whatever value it started with (undefined in your code), and you will loop on that unchanging value.
Typical ways for the input call to fail include
pressing control+D (on a *nix system)
pressing control+Z (on a Windows system)
redirected input from a pipe or file which is exhausted
There may be other causes of failed input as well.

Using Stacks in C++ to Evaluate the Postfix Expression

Ok, I already have it in postfix notation and I am sending over a string variable that will have the postfix notation as something such as: 5 15 2 *+
Here is my code:
int evaluatePostFix(string postfix_expression){
//Create a new stack
stack<int> theStack;
//Loops while the postfix expression string still contains values
while(postfix_expression.length()>=1){
//Loops on a number an whitespace
while(isdigit(postfix_expression.at(0)) || isspace(postfix_expression.at(0))){
//Holds a number that is above two digits to be added to the stack
string completeNum;
if(isdigit(postfix_expression.at(0))){
//Add the digit so it can become a full number if needed
completeNum+=postfix_expression.at(1);
}
else {
//Holds the integer version of completeNum
int intNum;
//Make completeNum an int
intNum=atoi(completeNum.c_str());
//push the number onto the stack
theStack.push(intNum);
}
//Check to see if it can be shortened
if(postfix_expression.length()>=1){
//Shorten the postfix expression
postfix_expression=postfix_expression.substr(1);
}
}
//An Operator has been found
while(isOperator(postfix_expression.at(0))){
int num1, num2;
char op;
//Grabs from the top of the stack
num1=theStack.top();
//Pops the value from the top of the stack - kinda stupid how it can return the value too
theStack.pop();
//Grabs the value from the top of the stack
num2=theStack.top();
//Pops the value from the top of the stack
theStack.pop();
//Grab the operation
op=postfix_expression.at(0);
//Shorten the postfix_expression
postfix_expression=postfix_expression.substr(1);
//Push result onto the stack
theStack.push(Calculate(num1,num2, op));
}
}
return theStack.top();
}
The error I get is "Deque iterator not deferencable"
Any help that I can get on this error would be much appreciated.
btw I haven't used C++ in a couple of years so I'm a bit rusty.
It would be easier if you told us which line was causing the error by stepping through with a debugger. However, I think I may have spotted the error.
In this block of code
if(isdigit(postfix_expression.at(0))){
//Add the digit so it can become a full number if needed
completeNum+=postfix_expression.at(1);
}
You ask for the postfix_expression.at(1) without ever checking if that element exists. Since there is no check, you might be accessing bad memory locations.