I wanted to simplify algebraic expressions in c++. I started with something simple: removing brackets from a algebraic expression containing + and - operators. For example, a-(b-c) should be simplified to a-b+c. This link gives the answer to this question. Here is the source code:
#include <iostream>
#include <string.h>
#include <stack>
using namespace std;
// Function to simplify the string
char* simplify(string str)
{
int len = str.length();
// resultant string of max length equal
// to length of input string
char* res = new char(len);
int index = 0, i = 0;
// create empty stack
stack<int> s;
s.push(0);
while (i < len) {
if (str[i] == '+') {
// If top is 1, flip the operator
if (s.top() == 1)
res[index++] = '-';
// If top is 0, append the same operator
if (s.top() == 0)
res[index++] = '+';
} else if (str[i] == '-') {
if (s.top() == 1)
res[index++] = '+';
else if (s.top() == 0)
res[index++] = '-';
} else if (str[i] == '(' && i > 0) {
if (str[i - 1] == '-') {
// x is opposite to the top of stack
int x = (s.top() == 1) ? 0 : 1;
s.push(x);
}
// push value equal to top of the stack
else if (str[i - 1] == '+')
s.push(s.top());
}
// If closing parentheses pop the stack once
else if (str[i] == ')')
s.pop();
// copy the character to the result
else
res[index++] = str[i];
i++;
}
return res;
}
I tested the function on a-(b-c-(d+e))-f and it gave the result a-b+c+d+e-fÿï┌. Why is it producing weird characters?
Related
This question already has answers here:
How to evaluate an infix expression in just one scan using stacks?
(4 answers)
Closed 3 years ago.
I'm trying to evaluate an infix expression in 1 pass without converting it into postfix but it's not giving correct output for some expressions. For eg: 3-5*10/5+10 , (45+5)-5*(100/10)+5
Can someone provide a proper solution to this problem in cpp.
Link to the previous question asked: How to evaluate an infix expression in just one scan using stacks?
Please don't mark it as duplicate as I have tried the algorithm answered in the above given thread but to no avail.
#include<bits/stdc++.h>
int isoperand(char x)
{
if(x == '+' || x=='-'|| x=='*' || x=='/' || x==')' || x=='(')
return 0;
return 1;
}
int Pre(char x)
{
if(x == '+' || x == '-')
return 1;
if(x == '*' || x == '/')
return 3;
return 0;
}
int infixevaluation(std::string exp)
{
std::stack<int> s1; //Operand Stack
std::stack<char> s2; //Operator Stack
int i,x,y,z,key;
i=0;
while(exp[i]!='\0')
{
if(isoperand(exp[i]))
{
key = exp[i]-'0';
s1.push(key);
i++;
}
else if(!isoperand(exp[i]) && s2.empty())
s2.push(exp[i++]);
else if(!isoperand(exp[i]) && !s2.empty())
{
if(Pre(exp[i])>Pre(s2.top()) && exp[i]!=')')
s2.push(exp[i++]);
else if(exp[i]==')' && s2.top() == '(')
{
s2.pop();
i++;
}
else if(exp[i]=='(')
s2.push(exp[i++]);
else
{
x = s1.top();
s1.pop();
y = s2.top();
s2.pop();
z = s1.top();
s1.pop();
if(y == '+')
s1.push(z+x);
else if(y == '-')
s1.push(z-x);
else if(y == '*')
s1.push(x*z);
else if(y == '/')
s1.push(z/x);
}
}
}
while(!s2.empty())
{
x = s1.top();
s1.pop();
y = s2.top();
s2.pop();
z = s1.top();
s1.pop();
if(y == '+')
s1.push(x+z);
else if(y == '-')
s1.push(z-x);
else if(y == '*')
s1.push(x*z);
else if(y == '/')
s1.push(z/x);
}
return s1.top();
}
int main(int argc, char const *argv[])
{
std::string s;
getline(std::cin,s);
std::cout<<infixevaluation(s)<<std::endl;
return 0;
}
Your code can only deal with single-digit operands -- and it has no checks for malformed input, so when you have a multi-digit operand, it runs off the rails.
The easiest fix for the former is just to scan digits when you see a digit -- change the if (isoperand(exp[i]) clause to:
if (isdigit(exp[i])) {
int value = 0;
while (isdigit(exp[i]))
value = value * 10 + exp[i++] - '0';
s1.push(value);
} else ...
For error checking, you should do things like
check for spaces and other invalid characters and reject or skip them
keep track of whether the last token matched was an operand or an operator, and give errors for two consecutive operands, or two consecutive operators other than ( and )
The Problem :-
I am trying to solve a 2d maze navigation problem in C++ using 2-dimensional array. To give a concise idea about the problem itself, I intend to navigate from node 'S' in the array to node 'G' by walking through free spaces denoted by '.' The nodes '#' are obstacles. One is not allowed to move on spaces denoted as obstacles. Care must also be taken to make all moves as legal moves (within configuration space). I denote the valid move with a '+' after replacement of the '.' If you like to know more about this problem (not necessary) then please refer this link.
What is the issue ?
I coded a recursive algorithm for this problem where we receive an array and a start node position, and then try to navigate to the goal node using recursion. However, I am getting a stack overflow error. It seems like my recursion never stops. I strongly believe there is some problem in my play() function or my check() function. I am not sure what actually is the problem.
What did I try ?
I am reproducing my code below :
void spawn(std::string (&board)[6]) {
for (int i = 0; i <= 6; i++) {
std::cout << board[i] << std::endl;
}
}
bool check(size_t a, size_t b, const std::string (&board)[6]) {
if (a < board[1].size() && a >= 0 && b < board[1].size() && b >= 0) {
if (board[a][b] == '#' || board[a][b] == '+')
return false;
else if (board[a][b] == '.')
return true;
}
return false;
}
void play(std::string (&board)[6], size_t a, size_t b) {
auto status = check(a, b, board);
if (board[a][b] == 'G' || board[a][b] == 'g') {
spawn(board);
return;
}
if (status) {
board[a][b] = '+';
play(board, ++a, b);
play(board, --a, b);
play(board, a, ++b);
play(board, a, --b);
}
}
int main() {
std::string grid[6] = {{"S#####"},
{".....#"},
{"#.####"},
{"#.####"},
{"...#.G"},
{"##...#"}};
play(grid, 0, 0);
return 0;
}
The check function prevents recursion because it sees the 'S' in the grid at the starting location. Changing:
else if (board[a][b] == '.')
to
else if (board[a][b] == '.' || board[a][b] == 'S')
got it to work for me.
Thanks for the insights Perette and Retired Ninja. I refactored the play() and check() functions in light of your suggestions and also some more ideas by myself.
I figured out that the main issue with the segmentation fault error was not providing accommodation for the '\0' character at the end of array of strings grid. I overlooked it because I considered array of strings to function in a different way than array of chars (since they are not the same species). Now I realize that the '\0' is necessary even for an array of strings !
I am reproducing the refactored functions for the purpose of completeness of this post :
void spawn(std::string board[6]) {
for (int i = 0; i <= 6; i++) {
std::cout << board[i] << std::endl;
}
}
bool check(int a, int b, const std::string board[6]) {
if (a < board[1].size() && a >= 0 && b <
board[1].size() && b >= 0) {
if (board[a][b] == '#' || board[a][b] == '+') {
return false;
} else if (board[a][b] == '.' ||
board[a][b] == 'S' ||
board[a][b] == 'G') {
return true;
}
}
return false;
}
void play(std::string board[6], int a, int b) {
if (board[a][b] == 'G' || board[a][b] == 'g') {
board[0][0] = 'S';
spawn(board);
return;
}
if (board[a][b] == '.' || board[a][b] == 'S')
board[a][b] = '+';
if (check(a + 1, b, board)) play(board, a + 1, b);
if (check(a - 1, b, board)) play(board, a - 1, b);
if (check(a, b + 1, board)) play(board, a, b + 1);
if (check(a, b - 1, board)) play(board, a, b - 1);
if (board[a][b] == '+') board[a][b] = '.';
}
int main() {
std::string grid[7] = {{"S#####"},
{".....#"},
{"#.####"},
{"#.####"},
{"...#.G"},
{"##...#"}};
play(grid, 0, 0);
return 0;
}
I am trying to figure out why I get segmentation fault, and my guess is that it is in my recursive function, which simplifies a prefix notation operation.
For example:
"m + 4 4" Returns: "+ m 8"
During testing I get a segmentation fault signal:
Exited with signal 11 (SIGSEGV)
I believe though that the problem lies in my recusive function "Operate"
string Operate(stack<string> &S, queue<string> &Q)
{
S.push(Q.front());
Q.pop();
std::string::size_type sz;
string result = "";
if (IsOperator(S.top()) == true)
{
S.push(Operate(S, Q));
}
if (Q.empty() == false)
{
S.push(Q.front());
Q.pop();
if (IsOperator(S.top()) == true)
{
S.push(Operate(S, Q));
}
if (S.size() < 3)
return "wrong input";
string arg1 = S.top();
S.pop();
string arg2 = S.top();
S.pop();
string oper = S.top();
S.pop();
if (StringIsDigit(arg1) && StringIsDigit(arg2))
{
int a = stoi(arg1, &sz);
int b = stoi(arg2, &sz);
char o = oper.at(0);
int c = 0;
if (o == '+')
c = b + a;
else if (o == '-')
c = b - a;
else if (o == '*')
c = b * a;
else
return "e";
result = to_string(c);
}
else
result = oper + " " + arg2 + " " + arg1;
}
else
{
result = S.top();
S.pop();
}
return result;
}
or in the function StringIsDigit:
bool StringIsDigit(string arg)
{
bool result = true;
for (int i = 0; i < arg.size() && result == true; i++)
{
if ((arg.size() != 1) && (arg.at(0) == '-') && (arg.at(i + 1) != ' '))
i++;
else
result = isdigit(arg.at(i));
}
return result;
}
Link to the whole program code:
https://pastebin.com/04pfE55N
The answer was quite simple, my error: SEGFAULT was as many pointed out for me error in reading from memory, segmentation fault, wiki.
When did the segfault occur?
It was when my function StringIsDigit() tried to figure out if negative values over 2 characters was an integer. In the "if statement, when checking if the string was indeed an integer, say -100", I continued to read the string until I reached the end of the arg string, but with arg.at(i + 1). Leading to the code trying to access memory outside the string array.Thanks Struthersneil for finding this flaw!
Please look at my old StringIsDigit() to find out the of by one value error I made:
bool StringIsDigit(string arg)
{
bool result = true;
for (int i = 0; i < arg.size() && result == true; i++)
{
if ((arg.size() != 1) && (arg.at(0) == '-') && (arg.at(i + 1) != ' '))
i++;
else
result = isdigit(arg.at(i));
}
return result;
}
The solution
The solution I want to make sure that the string was an integer since my algorithm supports expressions, such as x+3. This means that I need to iterate through the string is call isdigit() on every character in the string array. Though '-' is not an integer, '-' is needed obviously to express a negative integer, so I made a flawed check as you can see in my old StringIsDigit(). Instead of using that conditional if statement, I checked if the first character '-' and the second is not a whitespace ' ', and then I just let the isdigit() function do the rest of the work.
bool StringIsDigit(string arg)
{
bool result = true;
//I only need to check if the first is a '-' char and
//the next char is not ' '.
for (int i = 0; i < arg.size() && result == true; i++)
{
if ((arg.size() != 1) && (arg.at(0) == '-') && (arg.at(1) != ' '))
i++;
else
result = isdigit(arg.at(i));
}
return result;
}
The object of this code is to take the command line argument ./Program -encode|decode 0-9 and apply it to a text string written on the next line. IF encode, then shift each character of the text however many places specified in the alphabet. Decode does the opposite. I've gotten it good enough that the compiler finds nothing wrong, but when running the program nothing returns after entering the text string.
#include <iostream>
#include <string>
#include <cctype>
#include <cstdlib>
#include <cstring>
using namespace std;
string encode(string& to_encode, int to_shift)
{for(int i = 0; I < to_encode.length(); i++)
{if(isalpha(to_encode[i]))
{char sum = to_encode[i] + to_shift;
if(isupper(to_encode[i]) != 0 && isupper(sum) == 0)
{to_encode[i] = sum - 'Z' + 'A';
}
if(isupper(to_encode[i]) != 0 && isupper(sum) != 0)
{to_encode[i] = sum;
}
if(islower(to_encode[i]) != 0 && islower(sum) == 0)
{to_encode[i] = sum - 'z' + 'a';
}
if(islower(to_encode[i]) != 0 && islower(sum) != 0)
{to_encode[i] = sum;
}
}
}
return to_encode;
}
string decode(string& to_decode, int to_shift)
{for(int i = 0; I < to_decode.length(); i++)
{if(isalpha(to_decode[i]))
{char difference = to_decode[i] + to_shift;
if(isupper(to_decode[i]) != 0 && isupper(difference) == 0)
{to_encode[i] = difference + 'Z' - 'A';
}
if(isupper(to_decode[i]) != 0 && isupper(difference) != 0)
{to_encode[i] = difference;
}
if(islower(to_decode[i]) != 0 && islower(difference) == 0)
{to_encode[i] = difference + 'z' - 'a';
}
if(islower(to_decode[i]) != 0 && islower(difference) != 0)
{to_encode[i] = difference;
}
}
}
return to_decode;
}
int main(int argc, char* argv[])
{string cryption;
in shift;
if(argc != 3)
{cerr<<"Usage: ./Prog1d -encode|decode 0-9"<<endl;
return -1;
}
if(!(strcmp(argv[1],"-encode") == 0 || strcmp(argv[1],"-decode") == 0)
{cerr<<"Usage: ./Prog1d -encode|decode 0-9"<<endl;
return -1;
}
shift = atoi(argv[2]);
if(shift > 0 && shift <= 9)
{while(getline(cin,cryption))
{if(argv[1] == "-encode")
{encode(cryption, shift);
}
else
{decode(cryption, shift);
}
}
}
else
{cerr<<"Usage: ./Prog1d -encode|decode 0-9"<<endl;
return -1;
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to convert integer value to Roman numeral string?
first time asking a question here. I have a project on the horizon I've been working a bit on, and can't seem to find anything like it asked here or elsewhere. The goal is to accept an integer with no upper constraint, and convert that into a roman numeral. Since integers do in fact have an upper boundary, I have to convert it into a string before parsing it, using apostrophes to denote each set of three characters placed into a sub-string. I'm having trouble conceptualizing the loops that a)assign roman numerals to what they see based on their location b)count each set of three by displaying apostrophes.
So far I have:
for(int i=0;i<(int)input.length()/3;i++){
temp=input.substr(i,3);
for(int j = 0; j < (int)temp.length(); j++){
if(j == 0){
if(temp[j] == '9') cout<<"CM";
else if(temp[j] >= '8') cout<<"DCCC";
else if(temp[j] >= '7') cout<<"DCC";
else if(temp[j] >= '6') cout<<"DC";
else if(temp[j] >= '5') cout<<"D";
else if(temp[j] == '4') cout<<"CD";
else if(temp[j] == '3') cout<<"CCC";
else if(temp[j] == '2') cout<<"CC";
else if(temp[j] == '1') cout<<"C";
}
else if(j == 1){
if(temp[j] == '9') cout<<"XC";
else if(temp[j] >= '8') cout<<"LXXX";
else if(temp[j] >= '7') cout<<"LXX";
else if(temp[j] >= '6') cout<<"LX";
else if(temp[j] >= '5') cout<<"L";
else if(temp[j] == '4') cout<<"XL";
else if(temp[j] == '3') cout<<"XXX";
else if(temp[j] == '2') cout<<"XX";
else if(temp[j] == '1') cout<<"X";
}
else if(j ==2){
if(temp[j] == '9') cout<<"IX";
else if(temp[j] == '8') cout<<"VIII";
else if(temp[j] == '7') cout<<"VII";
else if(temp[j] == '6') cout<<"VI";
else if(temp[j] >= '5') cout<<"V";
else if(temp[j] == '4') cout<<"IV";
else if(temp[j] == '3') cout<<"III";
else if(temp[j] == '2') cout<<"II";
else if(temp[j] == '1') cout<<"I";
}
}
}
The numerals display well enough on their own, but I'm having trouble figuring out how to tell the loop to start on the right, and work it's way left by threes, maintaining the actual place of the number in the input (e.g. 1234 should display 1 as I, not C. I also need to figure out the loop to write in the apostrophes.
Simplest way i can think of to convert to roman numerals, is to check starting from the largest possible digit/combo and work down. Include combos, and check them from largest to smallest, so that say "XC" always gets checked before "L" and you don't have to worry about "LXXXX" and "LXL" and such.
// This code requires C++11 support. Namely, initializer lists and type inference.
// If your compiler sucks, there's equivalents for the important stuff. What really
// really matters is the order of the value=>digits mappings, and the iteration over
// them in the for loop.
#include <vector>
#include <string>
#include <utility>
std::string romanNumeralFor(int n, int markCount = 0) {
typedef std::pair<int, std::string> valueMapping;
static std::vector<valueMapping> importantNumbers = {
{1000, "M"}, {900, "CM"}, {500, "D"}, {400, "CD"},
{100, "C"}, { 90, "XC"}, { 50, "L"}, { 40, "XL"},
{10, "X"}, { 9, "IX"}, { 5, "V"}, { 4, "IV"},
{1, "I"},
};
std::string result;
bool needMark = false;
std::string marks(markCount, '\'');
for (auto mapping : importantNumbers) {
int value = mapping.first;
std::string &digits = mapping.second;
while (n >= value) {
result += digits;
n -= value;
needMark = true;
}
if ((value == 1000 || value == 100 || value == 10 || value == 1) && needMark) {
result += marks;
needMark = false;
}
}
return result;
}
As for converting a string to a number:
// in C++11
int n = std::stoi(str);
// in C++03
std::istringstream iss(str);
int n;
iss >> n;
So, split your string up into three-digit chunks (starting from the end!), and pass them in with appropriate mark counts.
Not the best solution but it works.
#include <iostream>
#include <map>
#include <algorithm>
#include <string>
void replaceAll(std::string& str, const std::string& from, const std::string& to) {
if(from.empty())
return;
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length();
}
}
int romanNumeralToInt(std::string s) {
std::map<char,int> romanNum = {
{'I',1}, {'V',5}, {'X',10}, {'L',50}, {'C',100},
{'D',500}, {'M',1000}
};
//{"IIIII",5}, {"VV",10}, {"XXXXX",50}, {"LL",100}, {"CCCCC",500}, {"DD",1000}
int g = 0;
std::sort(s.begin(),s.end());
if(s.find("IIIII") != std::string::npos)
replaceAll(s,"IIIII","V");
if(s.find("VV") != std::string::npos)
replaceAll(s,"VV","X");
if(s.find("XXXXX") != std::string::npos)
replaceAll(s,"XXXXX","L");
if(s.find("LL") != std::string::npos)
replaceAll(s,"LL","C");
for(auto& i : s) {
if(romanNum[i] != 0)
g += romanNum[i];
}
return g;
}
int main() {
std::string st = "XXXXXIIIIIVVVXLLD";
int a = romanNumeralToInt(st);
std::cout << a;
}
Prints out 680.