Facebook Interview Question


Country: India
Interview Type: In-Person




Comment hidden because of low score. Click to expand.
7
of 7 vote

My solution recursively tries out all operators on the target number and each number in the array. The base case is when the target number equals the last number of the array.

bool validEq(vector<int> arr, float target_num, int i)
{
    if(arr[i]==fabs(target_num) && i==arr.size()-1)
        return true;
    if(i>=arr.size())
        return false;
        
    return (validEq(arr, target_num+arr[i], i+1) || validEq(arr, target_num-arr[i], i+1) ||
        validEq(arr, target_num*arr[i], i+1) || validEq(arr, (float)target_num/arr[i], i+1));
}

- anshilbhansali February 27, 2017 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

In gist:
1. Create a combination of operators that is array of numbers length long.
2. Interleave it with the elements of the array of numbers to create an expression.
3. Create postfix expression.
4. Evaluate the expression and report back if it matches;

The idea here is to generate combinations of the operators as long as the length of the array ( identified by k here).

Once you generate a combination, prune the invalid operator combinations defined as the combination that either start with '*' or '/' .

If the combination of the operator starts with either + or - , simply prefix 0 to it and it will be a valid expression.

Next is a trivial case of converting it into postfix and evaluating the postfix ( code not shown here). After evaluating the postfix expression, compare if the result is the same as desired. If so, print it after removing the 0 that we had added prior.

void createExpressions(char expr[],int expr_n,int k,int numElements,int start,char branches[],int a[],int a_n,int sum) {
	if(numElements==k) {
		if(branches[0]=='*' || branches[0]=='/') return;
		string op;
		if(branches[0]=='-' || branches[0]=='+') {
			op=op+'0'+branches[0];
		}
		int i=1;
		while(i<numElements) {
			op=op+(char)(a[i-1]+'0')+branches[i];
			i++;
		}
		op=op+(char)(a[i-1]+'0');
		string postfixed=postfix(op);
		int result=evaluatePostfix(postfixed);
		if(result==sum) {
			printf("%s\n",op.substr(2,op.length()-2).c_str());
		}
		fflush(stdout);
		return;
	}
	for(int i=0;i<expr_n;i++) {
		branches[numElements++]=expr[i];
		createExpressions(expr,expr_n,k,numElements,++start,branches,a,a_n,sum);
		numElements--;
	}
}

void createValidExpressionsToSum(char expr[],int expr_n,int a[],int a_n,int sum) {
	char branches[a_n];
	memset(branches,0x00,sizeof(branches));
	createExpressions(expr,expr_n,a_n,0,0,branches,a,a_n,sum);
}

call as :
char expr[]={'+','-','/','*'};
int a[]={5,5,1};
createValidExpressionsToSum(expr,4,a,3,9);

- capt_caveman March 17, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

For the first element in the list, solve the problem recursively for each symbol. For +, recursively look for a way to combine all the remaining elements to equal the target minus the current element. For *, recursively look for a way to comine all the elements to equal the target divided by the current element. For -, look for target+x as well x - target.

If pulling out the first element doesn't yield a solution, move on the second, and so on.

- showell30@yahoo.com February 18, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

I believe order of operation matters here. and since you don't have () to use, taking the first element and do * with the rest won't work

- youSuck February 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Nice name!

- Anonymous February 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

surely you need to compute * and / first

- zyfo2 February 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

Yup, if parens aren't allowed, then you're better off just generating all the possible answers and evaluating them. To generate the sequence of numbers, use a permutation algorithm. To generate the symbols, use an odometer algorithm. To evaluate the expression, first scan for * and /, then scan for + and -.

- showell30@yahoo.com February 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Here is my recursive solution in javascript. Complexity is 4^(n-1) because in the worst case we simply generate all possible combinations of – + * /

function eveluate(numbers, N) {
    var remainingNumbers, firstNumber, secondNumber;

    if (numbers.length === 0) {
        return false;
    } else if (numbers.length === 1) {
        return Math.abs(numbers[0] - N) < 0.00001;
    } else {
        remainingNumbers = numbers.slice(1);

        firstNumber = numbers[0];
        secondNumber = remainingNumbers[0];

        if (eveluate(remainingNumbers, N - firstNumber))  {
            return true;
        } else {
            remainingNumbers[0] = - secondNumber;

            if (eveluate(remainingNumbers, N - firstNumber)) {
                return true;
            } else {
                remainingNumbers[0] = firstNumber * secondNumber;

                if (eveluate(remainingNumbers, N)) {
                    return true;
                } else {
                    remainingNumbers[0] = firstNumber / secondNumber;

                    if (eveluate(remainingNumbers, N)) {
                        return true;
                    }
                }
            }
        }
    }
}

- gmetrofun September 14, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

I think we need to consider the last number as well for * and / operations. And do the needful to get the right total. Here is how i would solve it

public String findExpression ( int N, int sum, String current, int [ ] numbers, int lastNumber ) {
	
	if ((current.length()+1)/2 == number.length) {	
			if (sum == N)	
				return current;
			return null;
		}

	
	for (int i=0; i<number.length; i++) {
		
		if (current.length() == 0) {
			current += number[i];
			sum = number[i];
			exp = findExpression (N, sum, current, number, number[i]);
		} else {
			String exp = null;
			// addition
			current += "+"+number[i];
			sum += number[i];
			exp = findExpression (N, sum, current, number, number[i]));
			if (exp != null) return exp;

			//subtraction
			current += "-"+number[i];
			sum -= number[i];
			exp = findExpression (N, sum, current, number, number[i]));
			if (exp != null) return exp;

			//multiplication 
			current += "*"+number[i];
			sum +=lastNumber * number[i] - lastNumber;
			exp = findExpression (N, sum, current, number, lastNumber*number[i]));
			if (exp != null) return exp;

			//division
			current += "/"+number[i];
			sum +=lastNumber / number[i] - lastNumber;
			exp = findExpression (N, sum, current, number, lastNumber/number[i]));
		}
		
		if (exp != null) return exp;
	}
	return null;
}

- Zero2 October 06, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Here I am passing the last number and subtracting it from the sum because I added it to the sum in last recursion and found out the next operator is "*" or "/"

- Zero2 October 06, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

static char symbols[] = {'+', '-', '*', '/'};
static float getSum(float test[], float ans, int operators[], int count)
{
        float prev, result = 0.0;
        int i;
        for (i = 0; i < count; ++i)
        {
            if (0 == operators[i])
            {
                prev = test[i];
                result += prev;
            }
            else if (1 == operators[i])
            {
                prev = -test[i];
                result += prev;
            }
            else if (2 == operators[i]) // multiplication
            {
                result -= prev;
                prev = prev*test[i];
                result += prev;
            }
            else // division
            {
                result -= prev;
                prev = prev/test[i];
                result += prev;
            }
        }
        return result;
}

static void findAnswerRecur(float test[], float ans, int len, int operators[], int count)
{
    float result = 0.0;
    int i;
    if (count == len)
    {
        float result = getSum(test, ans, operators, count);
        if (ans == result)
        {
            for (i = 0; i < len; ++i)
                printf("%c %.0f ", symbols[operators[i]], test[i]);
            printf(" = %.2f\n", ans);
        }
        return;
    }

    for  (i = 0; i < 4; ++i)
    {
        operators[count] = i;
        findAnswerRecur(test, ans, len, operators, count+1);
    }
 }


static void findAnswer(float test[], float ans, int len)
{
    int operators[4];
    int count = 0;
    int i;
    // only apply +/- at the very first
    for (i = 0; i < 2; ++i)
    {
        operators[count] = i;
        findAnswerRecur(test, ans, len, operators, count+1);
    }
}

- Andrew September 25, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

C solution using combinatorial method:

static char symbols[] = {'+', '-', '*', '/'};
static float getSum(float test[], float ans, int operators[], int count)
{
        float prev, result = 0.0;
        int i;
        for (i = 0; i < count; ++i)
        {
            if (0 == operators[i])
            {
                prev = test[i];
                result += prev;
            }
            else if (1 == operators[i])
            {
                prev = -test[i];
                result += prev;
            }
            else if (2 == operators[i]) // multiplication
            {
                result -= prev;
                prev = prev*test[i];
                result += prev;
            }
            else // division
            {
                result -= prev;
                prev = prev/test[i];
                result += prev;
            }
        }
        return result;
}

static void findAnswerRecur(float test[], float ans, int len, int operators[], int count)
{
    float result = 0.0;
    int i;
    if (count == len)
    {
        float result = getSum(test, ans, operators, count);
        if (ans == result)
        {
            for (i = 0; i < len; ++i)
                printf("%c %.0f ", symbols[operators[i]], test[i]);
            printf(" = %.2f\n", ans);
        }
        return;
    }

    for  (i = 0; i < 4; ++i)
    {
        operators[count] = i;
        findAnswerRecur(test, ans, len, operators, count+1);
    }
 }


static void findAnswer(float test[], float ans, int len)
{
    int operators[4];
    int count = 0;
    int i;
    // only apply +/- at the very first
    for (i = 0; i < 2; ++i)
    {
        operators[count] = i;
        findAnswerRecur(test, ans, len, operators, count+1);
    }
}

- Andrew September 25, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

char op[]={'+','-','*','/'};
bool eval(int a[],int target,int n,int pos,int prev)
{
	if(pos == n) {
		if(prev == target)	{
            return true;
		}
		return false;
	}
	for(int i=0;i<4;i++) {
		int res = 0;
		char ch = op[i];
		if(ch == '+') {
			res = prev + a[pos];
		} else if(ch == '-') {
			res = prev - a[pos];
		} else if(ch == '*') {
			res = prev * a[pos];
		} else {
			res = prev / a[pos];
		}
		if(	eval(a,target,n,pos+1,res ) )
			return true;
	}
	return false;
}

- amit March 30, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

char op[]={'+','-','*','/'};
bool eval(int a[],int target,int n,int pos,int prev)
{
	if(pos == n) {
		if(prev == target)	{
            return true;
		}
		return false;
	}
	for(int i=0;i<4;i++) {
		int res = 0;
		char ch = op[i];
		if(ch == '+') {
			res = prev + a[pos];
		} else if(ch == '-') {
			res = prev - a[pos];
		} else if(ch == '*') {
			res = prev * a[pos];
		} else {
			res = prev / a[pos];
		}
		if(	eval(a,target,n,pos+1,res ) )
			return true;
	}
	return false;
}

- amit March 30, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

I constructed an expression tree recursively. It works well. If there is n numbers and 4 operators, then the time should be O(4^n*n!), and the space is O(n^2) (mainly used in stack when doing recursion).

#include <vector>
#include <iostream>
#include <iterator>

using namespace std;

enum Op {ADD, MUL, SUB, DIV};

class Node {
public:
  Node *left, *right;
  int value;
  Op op;
  Node (int value) : value(value) { left = right = NULL; }
  bool setChild (Node *left, Node *right, Op op) {
    this->left = left;
    this->right = right;
    this->op = op;
    switch (op) {
    case ADD:
      this->value = left->value + right->value;
      break;
    case SUB:
      this->value = left->value - right->value;
      break;
    case MUL:
      this->value = left->value * right->value;
      break;
    case DIV:
      if (right->value == 0 || (left-value % right->value != 0))
	return false;
      this->value = left->value / right->value;
      break;
    }
    return true;
  }
  void print() {
    cout << left->value;
    switch(op) {
    case ADD:
      cout << " + ";
      break;
    case SUB:
      cout << " - ";
      break;
    case MUL:
      cout << " * ";
      break;
    case DIV:
      cout << " / ";
      break;
    }
    cout << right->value << endl;
  }
};

Node *constructExpressionTree(vector<Node*> &nodes, int target) {
  if (nodes.size() == 1 && nodes[0]->value == target) {
    return nodes[0];
  }
  int size = nodes.size();
  Node *new_node = new Node(0), *result = NULL;
  bool valid;
  vector<Node*> next_nodes;
  for (int i = 0; i < size && !result; ++i) {
    for (int j = i + 1; j < size && !result; ++j) {
      next_nodes.clear();
      next_nodes.insert(next_nodes.end(), nodes.begin(), nodes.begin() + i);
      next_nodes.insert(next_nodes.end(), nodes.begin() + i + 1, nodes.begin() + j);
      next_nodes.insert(next_nodes.end(), nodes.begin() + j + 1, nodes.end());
      next_nodes.push_back(new_node);

      for (int op = ADD; op <= DIV; ++op) {
	valid = new_node->setChild(nodes[i], nodes[j], static_cast<Op>(op));
	if (valid && (result = constructExpressionTree(next_nodes, target))) {
	  new_node->print();
	  break;
	}
	if (op >= SUB) {
	  valid = new_node->setChild(nodes[j], nodes[i], static_cast<Op>(op));
	  if (valid && (result = constructExpressionTree(next_nodes, target))) {
	    new_node->print();
	    break;
	  }
	}
      }
    }
  }
  if (!result)
    delete new_node;
  return result;
}

Node *construct(vector<int> numbers, int target) {
  vector<Node*> expression;
  for (vector<int>::iterator it = numbers.begin();
       it != numbers.end(); ++it) {
    Node *node = new Node(*it);
    expression.push_back(node);
  }
  return constructExpressionTree(expression, target);
}

void print(Node *root, bool par = false) {
  if (!root) {
    cout << "no valid expression. " << endl;
    return;
  }
  if (root->left && root->right) {
    if (par)
      cout << "(";
    bool left_par = (root->op == MUL || root->op == DIV) &&
      (root->left->op == ADD || root->left->op == SUB);
    bool right_par = root->op == DIV || 
      ((root->op == MUL || root->op == SUB) && 
       (root->right->op == ADD || root->right->op == SUB));
    print(root->left, left_par);
    switch(root->op) {
    case ADD:
      cout << " + ";
      break;
    case SUB:
      cout << " - ";
      break;
    case MUL:
      cout << " * ";
      break;
    case DIV:
      cout << " / ";
      break;
    }
    print(root->right, right_par);
    if (par)
      cout << ")";
  } else {
    cout << root->value;
  }
}

void deleteNodes(Node *root) {
  if (!root)
    return;
  deleteNodes(root->left);
  deleteNodes(root->right);
  delete root;
}

int main() {
  vector<int> numbers;
  int target = 24;
  srand((unsigned)time(NULL));
  numbers.push_back(rand() % 13 + 1);
  numbers.push_back(rand() % 13 + 1);
  numbers.push_back(rand() % 13 + 1);
  numbers.push_back(rand() % 13 + 1);
  copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " "));
  cout << endl;
  Node *root = construct(numbers, target);
  print(root);
  cout << endl;
  deleteNodes(root);
}

- DarkPassenger March 11, 2013 | Flag Reply


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More