Expedia Interview Question
Software Engineer in TestsCountry: United States
Interview Type: Phone Interview
I like this solution as well. One added idea, since you are using java, would be to use the Scanner class for string tokenization. It would make for much cleaner code
@Pankaj:
Can you explain with an example using two stacks? What you have written is confusing. In your summary of the solution you have interchangeably mentioned stacks i.e. you have not specified which stack you are referring to.
Assuming that all the integers are single digits:
int Evaluate(String str)
{
char [] eqn = str.toCharArray();
int len = str.length;
int rtnVal = -1;
boolean evaluated = false;
int prev = -1;
for(int i = 0; i < len && !evaluted; i++)
{
//Check if the current character is an operator and
//there are more characters following this
if(operator(eqn[i]) && i > 0 && i < (len - 1))
{
int a = prev;
int b = eqn[i+1] - '0'; //fetch the next int
//Evaluate various operations.
switch(eqn[i])
{
case '*':
prev = a*b; //Multiply the previous stored number with the next int
i++; //increment i to cover for the extra int that was used.
break;
case '/':
if(b != 0)
prev = a/b;
else
{
System.Out.Println("Error! Division by zero, TARDIS EXPLODED!!!");
return;
}
i++;
break;
case '+':
//Break the next half of string up to ensure that * and / get
//proper precedence. and add the result to prev.
int b = Evaluate(str.substring(i + 1));
rtnVal = a + b;
//At this point, we have evaluated the string, time to exit.
evaluated = true;
break;
case '-':
int b = Evaluate(str.substring(i + 1));
rtnVal = a - b;
evaluated = true;
break;
}
} else if(i == 0) //Else, if this is the first character, store it in prev.
{
if(checkInt(eqn[i]))
prev = eqn[i] - '0';
else
System.out.println("Error in string.");
}
}
return rtnVal;
}
boolean checkInt(char c)
{
if(c >= '0' && c <= '9')
return true;
else
return false;
}
boolean operator(char c)
{
if(c == '+' || c == '-' || c == '/' || c == '*')
return true;
else
return false;
}
I might have goofed up in the code, but i hope I am able to pass you the idea.
int calcExp(String str){
Stack st = new Stack();
int t1, t2, k;
for(int i=0; i < st.length(); i++){
if(str[i]=='+')
st.push('+');
else if(str[i]=='*'){
i++;
k=0;
while(str[i]!='+' && str[i]!='*')
k = str[i++]+ k*10;
st.push(st.pop()* k);
}
else{
k=0;
while(str[i]!='+' && str[i]!='*')
k = str[i++]+ k*10;
st.push(k);
}
}
while(true){
t1 = st.pop();
st.pop();
t2 = st.pop();
t1 = t1+t2;
if(st.empty()) return t1;
else st.push(t1);
}
}
private static boolean isValid(final String str){
return Pattern.compile("^[0-9\\*\\+]*$").matcher(str);
}
Here are two solutions, one using recursion and one that does it iterating in a single method. Single method is faster and uses fewer resources, recursion one is far easier to extend.
Recursion:
char[] buf;
int index;
char currentOperator;
int recursive(String text)
{
index = 0;
buf = text.toCharArray();
currentOperator = '+';
return parse(0);
}
int parse(int val)
{
int number = 0;
while(index < buf.length)
{
char c = buf[index++];
// if we have a digit add it to our number
if(c >= '0' && c <= '9')
{
number *= 10; // for every didgit we first multiply our number by 10 (no effect for the first digit sunce number = 0)
number += c - '0';
}
// we only come through here if we have either of these operators or we're at the end of the buffer
if(c == '+' || c == '*' || index == buf.length)
{
char performOperator = currentOperator;
currentOperator = c;
if(performOperator == '+') return add(val, number);
if(performOperator == '*') return multiply(val, number);
}
}
return val;
}
int add(int op1, int op2)
{
return op1 + parse(op2);
}
int multiply(int op1, int op2)
{
int v = op1 * op2;
return parse(v);
}
Single method:
int singleMethod(String text)
{
char[] buf = text.toCharArray();
int result = 0;
int product = 0;
int number = 0;
char prev_operand = '+';
for(char c : buf)
{
// if we have a digit add it to our number
if(c >= '0' && c <= '9')
{
number *= 10; // for every didgit we first multiply our number by 10 (no effect for the first digit sunce number = 0)
number += c - '0';
}
// we only come through here if we have either of these operators
else if(c == '+' || c == '*')
{
if(prev_operand == '*') product *= number;
if(c == '+')
{
if(prev_operand == '+') result += number;
result += product;
product = 0;
}
else if(c == '*')
{
if(prev_operand == '+') product = number;
}
prev_operand = c;
number = 0;
}
}
if(prev_operand == '*') result += product * number;
if(prev_operand == '+') result += number;
return result;
}
How about:
#include <stdio.h>
#include <stdlib.h>
#define BUILD_NUM(x,y) while(*(x) != '*' && *(x) != '+' && *(x) != '\0' && \
((*x) >= '0' && (*x) <= '9')) \
(y) = *(x)++ - '0' + (y) * 10
int comp_str(char *p1)
{
int s=0, m=1;
while(*p1 != '\0'){
if((*p1 >= '0' && *p1 <= '9') || *p1 == '+'){
int n=0;
if(*p1 == '+') ++p1;
BUILD_NUM(p1, n);
if(*p1 == '*')
m *= n;
else if(*p1 == '+' || *p1 == '\0')
s += n;
else {
fprintf(stderr,"invalid input!\n");
return(-1);
}
} else if(*p1 == '*') {
int n=0;
++p1;
BUILD_NUM(p1,n);
if(*p1 == '+' || *p1 == '\0'){ // end of multiplication block
m *= n;
s += m;
m = 1;
} else if(*p1 == '*')
m *= n;
else {
fprintf(stderr,"invalid input!\n");
return(-1);
}
} else {
fprintf(stderr,"invalid input!\n");
return(-1);
}
}
return(s);
}
int main(int argc, char *argv[])
{
if(argc != 2)
exit(1);
printf("%d\n",comp_str(argv[1]));
exit(0);
}
import java.util.ArrayList;
import java.util.List;
public class Example {
static List<String> stack = new ArrayList<String>();
static int result;
public static void main(String args[]) {
String str = "9*2+8*2";
boolean pushFlag = true;
String op1;
String ele;
for (int i = 0; i < str.length(); i++) {
ele = str.substring(i, i + 1);
if (ele.equals("+")) {
pushFlag = true;
} else if (ele.equals("*")) {
pushFlag = false;
} else if (pushFlag) {
push(ele);
} else {
op1 = pop();
push(String.valueOf(Integer.parseInt(op1) * Integer.parseInt(ele)));
}
}
System.out.println(result);
}
static void push(String str) {
stack.add(str);
result = result + Integer.parseInt(str);
}
static String pop() {
String poppedEle = stack.get(stack.size() - 1);
result = result - Integer.parseInt(poppedEle);
return poppedEle;
}
}
#include<stdio.h>
#include<string.h>
#include<conio.h>
main()
{
char a[]="9+9+1*4*7+9*9";
int sum=0;
int arr[10]={0};
int i=0,j=0;
int len=strlen(a);
int flag=0;
int k=0;
while(i>-1&& j>-1)
{
if(a[i]>='0' && a[i]<='9')
{
arr[j++]= a[i] -'0';
a[i]='%';
i++;
}
else if(a[i]=='*')
{
sum=arr[--j] * (a[i+1] -'0');
a[i-1]=a[i]=a[i+1]='%';
i+=2;
arr[j++]=sum;
if(i>=len){ flag=1;i=len-1;}
sum=0;
}
else if( a[i]=='+' && flag==1)
{
sum=arr[j-1]+arr[j-2];
arr[j-2]=sum;
j-=1;
i--;
if(j<0) break;
getch();
}
else if(a[i]=='+')
{
i++;
}
else if(i>len-1){
flag=1;
i=len-1;}
else if(flag==1)
{
i--;
}
else
i++;
}
printf("\n final value%d",arr[0]);
getch();
return 0;
}
#include<stdio.h>
#include<string.h>
#include <iostream>
using namespace std;
int integerExcute(string myStr);
int main(){
cout << "The result is: " << integerExcute("6+2*3");
return 0;
}
int integerExcute(string myStr){
int i = 0;
int preGroup = myStr.at(0) - '0';
int nextGroup = 0;
while(i != myStr.length()){
if(myStr.at(i) == '*')
preGroup *= (myStr.at(++i) - '0');
else if(myStr.at(i) == '+'){
nextGroup = myStr.at(++i) - '0';
while(i != myStr.length() && myStr.at(i) != '+'){
if(myStr.at(i) == '*')
nextGroup *= (myStr.at(++i) - '0');
else
i++;
}
preGroup += nextGroup;
}
else
i++;
}
return preGroup;
}
private static int result(String input){
int result = 0;
String[] inpArr = input.split("");
for(int i=1;i<inpArr.length;i+=2){
int f = Integer.parseInt(inpArr[i]);
if(i < inpArr.length - 1 && inpArr[i+1].equals("*")){
int s = Integer.parseInt(inpArr[i+2]);
result = f*s;
inpArr[i+2] = result+"";
inpArr[i+1] = "-";
}else if(i < inpArr.length - 3 && inpArr[i+3].equals("+")){
int s = Integer.parseInt(inpArr[i+2]);
result = f+s;
inpArr[i+2] = result+"";
inpArr[i+1] = "-";
}
if(i > 1 && !(inpArr[i-1].equals("-")) && i < inpArr.length - 2){
inpArr[i+1] = inpArr[i-1];
inpArr[i] = inpArr[i-2];
}else if(i == inpArr.length -1){
if(!(inpArr[i-1].equals("-"))){
int s = Integer.parseInt(inpArr[i-2]);
result = f+s;
}else{
result = f;
}
}
}
return result;
}
Since there are only two functions + and *, we need to take care of precedence for * first
char[] arr = {'4','*','5','+','6','*','2','+','5'};
NodeS<int> stInt = new NodeS<int>();
int result = 0;
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] >= 48 && arr[i] <= 57)
{
stInt.Push(arr[i] - '0');
}
else if(arr[i] == '*')
{
i++;
if (arr[i] >= 48 && arr[i] <= 57)
{
int f = stInt.Pop() * (arr[i] - '0');
stInt.Push(f);
}
}
}
while (!stInt.Empty())
{
result += stInt.Pop();
}
Console.WriteLine(result);
public static void main(String[] args) {
// TODO Auto-generated method stub
String exp = "3*6+*9*100";
TestAlg alg = new TestAlg();
ExpressionTree tree = alg.constructTree(exp);
if(tree != null)
{
System.out.println("paser result "+tree.result());
}
}
public static int evaluate(String expression)
{
int a = 0;
return a;
}
interface Caculation {
int result();
}
private boolean isValid(final String str){
return Pattern.compile("^[0-9\\*\\+]*$").matcher(str).matches();
}
public ExpressionTree constructTree(String str)
{
if(!isValid(str))
{
System.out.println("invalid input str");
return null;
}
ExpressionTree tree = new ExpressionTree();
String[] elemAarry = str.split("\\+");
for(String addelem : elemAarry)
{
String[] elelmArray1 = addelem.split("\\*");
Multiple multipler = new Multiple();
multipler.addElem(new BasicData(1));
for(String a : elelmArray1)
{
BasicData bdata = new BasicData(Integer.parseInt(a));
multipler.addElem(bdata);
}
tree.addElem(multipler);
}
return tree;
}
abstract class BasicCaculation implements Caculation{
List<Caculation> elemList = new LinkedList<Caculation>();
public void addElem(Caculation cal)
{
elemList.add(cal);
}
}
class ExpressionTree extends BasicCaculation{
public int result()
{
int sum = 0;
for(Caculation cal : elemList )
{
sum+=cal.result();
}
return sum;
}
}
class Multiple extends BasicCaculation{
public int result()
{
int result = 1;
for(Caculation cal : elemList )
{
result *=cal.result();
}
return result;
}
}
class BasicData implements Caculation{
int data;
public BasicData(int da)
{
data = da;
}
@Override
public int result() {
return data;
}
}
here is in c#
internal static void CalculateExpression()
{
string expression = Console.ReadLine();
int result = 0, op1 = 0, op2 = 0;
int index = 0;
bool done = false;
while (index < expression.Length)
{
switch (expression[index])
{
case '+':
result += done ? op1 * op2 : op1;
op1 = op2 = 0;
done = false;
break;
case '*':
if (done)
{
op1 *= op2;
op2 = 0;
}
done = true;
break;
case ' ':
break;
default:
if (!done)
{
op1 = op1 * 10 + int.Parse(expression[index].ToString());
}
else
{
op2 = op2 * 10 + int.Parse(expression[index].ToString());
}
break;
}
index++;
}
result += done ? op1 * op2 : op1;
Console.WriteLine("Result ->" + result);
}
Do we need a very long codes? Here is my simplest one.
public class Test
{
public String inStr;
public Test(String str)
{
inStr = str;
}
public int evaluate()
{
int sum=0;
String [] plusArray = inStr.split("\\+");
for(int i=0; i<plusArray.length; i++)
{
String [] multiArray = plusArray[i].split("\\*");
int multiple=1;
for(int j=0; j<multiArray.length; j++)
{
multiple *= Integer.parseInt(multiArray[j]);
}
sum += multiple;
}
return sum;
}
public static void main(String [] argus)
{
Test tst = new Test("3*2+5*6");
System.out.println("The result is: " + tst.evaluate());
}
}
String[] sampleData= {"5","*","2","+","6","*","2","+","5","*","3"};
String result;
Stack<String> stack = new Stack<String>();
for(String s : sampleData){
if("*".equalsIgnoreCase(s) || "+".equalsIgnoreCase(s)){
stack.push(s);
}
else{
if(!stack.isEmpty() && ("*").equalsIgnoreCase(stack.peek())){
stack.pop();
result = String.valueOf(Integer.parseInt(s)*Integer.parseInt(stack.pop()));
stack.push(result); //Evaluate the multiplication result and push back into the stack
}
else{
stack.push(s);
}
}
}
int sum= Integer.parseInt(stack.pop());
int y=0;
while(!stack.isEmpty()){ // Now stack have only numbers and +
stack.pop();
y = Integer.parseInt(stack.pop());
sum += y;
}
System.out.println(sum);
{public int calcString(String str){
int length = str.length();
int internalSum = 0;
int positionCounter = 0;
int multiplierSum = 1;
int finalSum = 0;
List<Integer> multiplier = new ArrayList<Integer>();
List<Integer> adder = new ArrayList<Integer>();
for(int i = 0 ; i<length; ++i){
char c = str.charAt(i);
if(isInt(c)){
String s;
if(positionCounter>0) {
s = internalSum + String.valueOf(c);
}
else {
s =String.valueOf(c);
}
internalSum = Integer.parseInt(s);
++positionCounter;
}
if(c == '*'){
multiplier.add(internalSum);
internalSum = 0;
positionCounter=0;
}
if(c == '+' || i == length-1){
multiplier.add(internalSum);
internalSum = 0;
for(int j : multiplier)
multiplierSum *= j;
adder.add(multiplierSum);
multiplier.clear();
if(i!=length-1)
multiplierSum = 1;
else
multiplierSum = 0;
positionCounter = 0;
}
}
if(!multiplier.isEmpty()){
for(int j : multiplier)
multiplierSum *= j;
}
adder.add(multiplierSum);
for(int i : adder)
finalSum += i;
return finalSum;
}
public static void main(String[] args){
StringCalc calc = new StringCalc();
System.out.println(calc.calcString("125+5*6"));
}
private boolean isInt(char c){
try{
int i = Integer.parseInt(String.valueOf(c));
return true;
}
catch(NumberFormatException nfe){
return false;
}
}
}
uses the algo to convert infix to postfix expression using stacks:
Scan the expression string from left to right.
Initialise empty stacks named operator & operand.
If the scanned character is an operand, add it to the operand stack. If the scanned character is an operator and if the operator stack is empty Push the character to operator stack.
If the scanned character is an Operand and the stack is not empty, compare the precedence of the character with the element on top of the operator stack (topStack). If topStack has higher precedence over the scanned character Pop the stack else Push the scanned character to stack. Repeat this step as long as stack is not empty and topStack has precedence over the character.
Repeat this step till all the characters are scanned.
(After all characters are scanned, we have to add any character that the stack may have to the operand stack.) If stack is not empty add topStack to operand stack and Pop the stack. Repeat this step as long as stack is not empty.
Return the operator stack
- Pankaj Khattar June 16, 2013