Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate all combinations of mathematical expressions that add to target (Java homework/interview)

I've tried to solve the problem below for a coding challenge but could not finish it in 1 hour. I have an idea on how the algorithm works but I'm not quite sure how to best implement it. I have my code and problem below.

The first 12 digits of pi are 314159265358. We can make these digits into an expression evaluating to 27182 (first 5 digits of e) as follows:

3141 * 5 / 9 * 26 / 5 * 3 - 5 * 8 = 27182

or

3 + 1 - 415 * 92 + 65358 = 27182

Notice that the order of the input digits is not changed. Operators (+,-,/, or *) are simply inserted to create the expression.

Write a function to take a list of numbers and a target, and return all the ways that those numbers can be formed into expressions evaluating to the target

For example:
f("314159265358", 27182) should print:

3 + 1 - 415 * 92 + 65358 = 27182
3 * 1 + 4 * 159 + 26535 + 8 = 27182
3 / 1 + 4 * 159 + 26535 + 8 = 27182
3 * 14 * 15 + 9 + 26535 + 8 = 27182
3141 * 5 / 9 * 26 / 5 * 3 - 5 * 8 = 27182

This problem is difficult since you can have any combination of numbers and you don't consider one number at a time. I wasn't sure how to do the combinations and recursion for that step. Notice that parentheses are not provided in the solution, however order of operations is preserved.

My goal is to start off with say

{"3"}
then
{"31", "3+1", "3-1", "3*1" "3/1"}
then
{"314", "31+4", "3+1+4", "3-1-4", "31/4", "31*4", "31-4"} etc.

then look at the every value in the list each time and see if it is target value. If it is, add that string to result list.

Here is my code

public static List<String> combinations(String nums, int target)
    {

        List<String> tempResultList = new ArrayList<String>();
        List<String> realResultList = new ArrayList<String>();
        String originalNum = Character.toString(nums.charAt(0));


        for (int i = 0; i < nums.length(); i++)
        {
            if (i > 0)
            {
                originalNum += nums.charAt(i); //start off with a new number to decompose
            }
            tempResultList.add(originalNum);
            char[] originalNumCharArray = originalNum.toCharArray();
            for (int j = 0; j < originalNumCharArray.length; j++)
            {
                //go through every character to find the combinations?
                // maybe recursion here instead of iterative would be easier...
            }
            for (String s : tempResultList)
            {
                //try to evaluate
                int temp = 0;
               if (s.contains("*") || s.contains("/") || s.contains("+") || s.contains("-"))
               {
                  //evaluate expression
               } else {
                   //just a number
               }
                if (temp == target)
                {
                    realResultList.add(s);
                }

            }
         tempResultList.clear();
        }
        return realResultList;
    }

Could someone help with this problem? Looking for an answer with coding in it, since I need help with the generation of possibilities

like image 500
John61590 Avatar asked Sep 15 '15 20:09

John61590


1 Answers

I don't think it's necessary to build a tree, you should be able to calculate as you go -- you just need to delay additions and subtractions slightly in order to be able take the precedence into account correctly:

static void check(double sum, double previous, String digits, double target, String expr) {
   if (digits.length() == 0) {
     if (sum + previous == target) {
       System.out.println(expr + " = " + target);
     }
   } else {
     for (int i = 1; i <= digits.length(); i++) {
       double current = Double.parseDouble(digits.substring(0, i));
       String remaining = digits.substring(i);
       check(sum + previous, current, remaining, target, expr + " + " + current);
       check(sum, previous * current, remaining, target, expr + " * " + current);
       check(sum, previous / current, remaining, target, expr + " / " + current);
       check(sum + previous, -current, remaining, target, expr + " - " + current);
     }
   }
 }

 static void f(String digits, double target) {
   for (int i = 1; i <= digits.length(); i++) {
     String current = digits.substring(0, i);
     check(0, Double.parseDouble(current), digits.substring(i), target, current);
   }
 } 
like image 60
Stefan Haustein Avatar answered Sep 18 '22 17:09

Stefan Haustein