Smallest expression to represent a number using single digit

Given a number N and a digit D, we have to form an expression or equation that contains only D and that expression evaluates to N. Allowed operators in an expression are +, -, *, and / . Find the minimum length expression that satisfies the condition above and D can only appear in the expression at most 10(limit) times. Hence limit the values of N (Although the value of limit depends upon how far you want to go. But a large value of limit can take a longer time for the below approach).

Remember, there can be more than one minimum expression of D that evaluates to N but the length of that expression will be minimum.

Examples:

Input :  N = 7, D = 3
Output : 3/3+ 3 + 3
Explanation : 3/3 = 1, and 1+3+3 = 7 
This is the minimum expression.

Input :  N = 7, D = 4
Output : (4+4+4)/4 + 4
Explanation : (4+4+4) = 12, and 12/4 = 3 and 3+4 = 7
Also this is the minimum expression. Although 
you may find another expression but that 
expression can have only five 4's

Input :  N = 200, D = 9
Output : Expression not found!
Explanation : Not possible within 10 digits. 

The approach we use is Backtracking. We start with the given Digit D and start multiplying, adding, subtracting, and dividing if possible. This process is done until we find the total as N or we reach the end and we backtrack to start another path. To find the minimum expression, we find the minimum level of the recursive tree. And then apply our backtracking algorithm.



Let’s say N = 7, D = 3

The above approach is exponential. At every level, we recurse 4 more ways (at-most). So, we can say the time complexity of the method is 4^n where n is the number of levels in the recursive tree (or we can say the number of times we want D to appear at-most in the expression which in our case is 10).

Note: We use the above approach two times. First to find the minimum level and then to find the expression that is possible at that level. So, we have two passes in this approach. We can get the expression in one go, but you’ll need to scratch your head for that.

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// CPP Program to generate minimum expression containing
// only given digit D that evaluates to number N.
#include <climits>
#include <iostream>
#include <map>
#include <sstream>
#include <stack>
  
// limit of Digits in the expression
#define LIMIT 10
  
using namespace std;
  
// map that store if a number is seen or not
map<int, int> seen;
  
// stack for storing operators
stack<char> operators;
int minimum = LIMIT;
  
// function to find minimum levels in the recursive tree
void minLevel(int total, int N, int D, int level) {
  
  // if total is equal to given N
  if (total == N) {
  
    // store if level is minimum
    minimum = min(minimum, level);
    return;
  }
  
  // if the last level is reached
  if (level == minimum)
    return;
  
  // if total can be divided by D.
  // recurse by dividing the total by D
  if (total % D == 0)
    minLevel(total / D, N, D, level + 1);
  
  // recurse for total + D
  minLevel(total + D, N, D, level + 1);
  
  // if total - D is greater than 0
  if (total - D > 0)
  
    // recurse for total - D
    minLevel(total - D, N, D, level + 1);
  
  // recurse for total multiply D
  minLevel(total * D, N, D, level + 1);
}
  
// function to generate the minimum expression
bool generate(int total, int N, int D, int level) {
  // if total is equal to N
  if (total == N)
    return true;
  
  // if the last level is reached
  if (level == minimum)
    return false;
  
  // if total is seen at level greater than current level
  // or if we haven't seen total before. Mark the total 
  // as seen at current level
  if (seen.find(total) == seen.end() ||
      seen.find(total)->second >= level) {
      
    seen[total] = level;
  
    int divide = INT_MAX;
  
    // if total is divisible by D
    if (total % D == 0) {
      divide = total / D;
  
      // if divide isn't seen before
      // mark it as seen
      if (seen.find(divide) == seen.end())
        seen[divide] = level + 1;
    }
  
    int addition = total + D;
  
    // if addition isn't seen before
    // mark it as seen
    if (seen.find(addition) == seen.end())
      seen[addition] = level + 1;
  
    int subtraction = INT_MAX;
    // if D can be subtracted from total
    if (total - D > 0) {
      subtraction = total - D;
  
      // if subtraction isn't seen before
      // mark it as seen
      if (seen.find(subtraction) == seen.end())
        seen[subtraction] = level + 1;
    }
  
    int multiply = total * D;
  
    // if multiply isn't seen before
    // mark it as seen
    if (seen.find(multiply) == seen.end())
      seen[multiply] = level + 1;
  
    // recurse by dividing the total if possible
    if (divide != INT_MAX)
      if (generate(divide, N, D, level + 1)) {
  
        // store the operator.
        operators.push('/');
        return true;
      }
  
    // recurse by adding D to total
    if (generate(addition, N, D, level + 1)) {
  
      // store the operator.
      operators.push('+');
      return true;
    }
  
    // recurse by subtracting D from total
    if (subtraction != INT_MAX)
      if (generate(subtraction, N, D, level + 1)) {
  
        // store the operator.
        operators.push('-');
        return true;
      }
  
    // recurse by multiplying D by total
    if (generate(multiply, N, D, level + 1)) {
  
      // store the operator.
      operators.push('*');
      return true;
    }
  }
  
  // expression is not found yet
  return false;
}
  
// function to print the expression
void printExpression(int N, int D) {
  // find minimum level
  minLevel(D, N, D, 1);
  
  // generate expression if possible
  if (generate(D, N, D, 1)) {
    // stringstream for converting to D to string
    ostringstream num;
    num << D;
  
    string expression;
  
    // if stack is not empty
    if (!operators.empty()) {
  
      // concatenate D and operator at top of stack
      expression = num.str() + operators.top();
      operators.pop();
    }
  
    // until stack is empty
    // concatenate the operator with parenthesis for precedence
    while (!operators.empty()) {
      if (operators.top() == '/' || operators.top() == '*')
        expression = "(" + expression + num.str() + ")" + operators.top();
      else
        expression = expression + num.str() + operators.top();
      operators.pop();
    }
  
    expression = expression + num.str();
  
    // print the expression
    cout << "Expression: " << expression << endl;
  }
  
  // not possible within 10 digits.
  else
    cout << "Expression not found!" << endl;
}
  
// Driver's Code
int main() {
  int N = 7, D = 4;
  
  // print the Expression if possible
  printExpression(N, D);
  
  // print expression for N =100, D =7
  minimum = LIMIT;
  printExpression(100, 7);
  
  // print expression for N =200, D =9
  minimum = LIMIT;
  printExpression(200, 9);
  
  return 0;
}

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program to generate minimum expression containing
# only the given digit D that evaluates to number N.
LIMIT = 10
  
# to restrict the maximum number of times 
# the number D can be used to obtain N
minimum = LIMIT
  
# to store the value of intermediate D
# and the D of operands used to get that intermediate D, ie
# seen[intermediateNumber] = numberOfOperandsUsed
seen = {}
  
# stack to store the operators used to print the expression
operators = []
  
# function to obtain minimum D of operands in recursive tree
def minLevel(total, N, D, level):
    global minimum
  
    # if total is equal to given N
    if total == N:
        # store if D of operands is minimum
        minimum = min(minimum, level)
        return
  
    # if the last level (limit) is reached
    if level == minimum:
        return
  
    # if total can be divided by D, recurse
    # by dividing the total by D
    if total % D == 0:
        minLevel(total / D, N, D, level + 1)
  
    # recurse for total + D
    minLevel(total + D, N, D, level + 1)
  
    # if total - D is greater than 0, recurse for total - D
    if total - D > 0:
        minLevel(total - D, N, D, level + 1)
  
    # recurse for total * D
    minLevel(total * D, N, D, level + 1)
  
# function to generate the minimum expression
def generate(total, N, D, level):
      
    # if total is equal to N
    if total == N:
        return True
  
    # if the last level is reached
    if level == minimum:
        return False
  
    # if the total is not already seen or if 
    # the total is seen with more level
    # then mark total as seen with current level
    if seen.get(total) is None or seen.get(total) >= level:
        seen[total] = level
  
        divide = -1
          
        # if total is divisible by D
        if total % D == 0:
            divide = total / D
              
            # if the number (divide) is not seen, mark as seen
            if seen.get(divide) is None:
                seen[divide] = level + 1
  
        addition = total + D
          
        # if the number (addition) is not seen, mark as seen
        if seen.get(addition) is None:
            seen[addition] = level + 1
  
        subtraction = -1
        # if D can be subtracted from total
        if total - D > 0:
            subtraction = total - D
              
            # if the number (subtraction) is not seen, mark as seen
            if seen.get(subtraction) is None:
                seen[subtraction] = level + 1
  
        multiplication = total * D
          
        # if the number (multiplication) is not seen, mark as seen
        if seen.get(multiplication) is None:
            seen[multiplication] = level + 1
  
        # recurse by dividing the total if possible and store the operator
        if divide != -1 and generate(divide, N, D, level + 1):
            operators.append('/')
            return True
  
        # recurse by adding D to total and store the operator
        if generate(addition, N, D, level + 1):
            operators.append('+')
            return True
  
        # recurse by subtracting D from total
        # if possible and store the operator
        if subtraction != -1 and generate(subtraction, N, D, level + 1):
            operators.append('-')
            return True
  
        # recurse by multiplying D by total and store the operator
        if generate(multiplication, N, D, level + 1):
            operators.append('*')
            return True
  
    # expression is not found yet
    return False
  
# function to print the expression
def printExpression(N, D):
      
    # find the minimum number of operands
    minLevel(D, N, D, 1)
  
    # generate expression if possible
    if generate(D, N, D, 1):
        expression = ''
          
        # if stack is not empty, concatenate D and
        # operator popped from stack
        if len(operators) > 0:
            expression = str(D) + operators.pop()
  
        # until stack is empty, concatenate the 
        # operator popped with parenthesis for precedence
        while len(operators) > 0:
            popped = operators.pop()
            if popped == '/' or popped == '*':
                expression = '(' + expression + str(D) + ')' + popped
            else:
                expression = expression + str(D) + popped
  
        expression = expression + str(D)
        print("Expression: " + expression)
  
    # not possible within 10 digits.
    else:
        print("Expression not found!")
  
# Driver's code
if __name__ == '__main__':
    # N = 7, D = 4
    minimum = LIMIT
    printExpression(7, 4)
  
    minimum = LIMIT
    printExpression(100, 7)
  
    minimum = LIMIT
    printExpression(200, 9)
  
# This code is contributed by thecodingpanda

chevron_right


Output:

Expression: (4+4+4)/4+4
Expression: (((7+7)*7)*7+7+7)/7
Expression not found!

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : thecodingpanda

Article Tags :
Practice Tags :


Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.