-2

I'm working on an assignment that gives an integer N and tasks us to find all possible combinations of X, Y such that X + Y = N and Y = X with one digit removed. For example, 302 would have the following solutions:

251 + 51 = 302

275 + 27 = 302

276 + 26 = 302

281 + 21 = 302

301 + 01 = 302

My code to accomplish this can find all of the correct answers, but it runs too slowly for very large numbers (it takes roughly 8 seconds for the largest possible number, 10^9, when I would like for the entire algorithm of up to 100 of these cases to complete in under 3 seconds).

Here's some code describing my current solution:

//Only need to consider cases where x > y.
for(int x = n * 0.5; x <= n; x++)
{
     //Only considers cases where y's rightmost digit could align with x.
     int y = n - x,
         y_rightmost = y % 10;
     if(y_rightmost == x % 10 || y_rightmost == (x % 100) / 10)
     {
         //Determines the number of digits in x and y without division. places[] = {1, 10, 100, 1000, ... 1000000000}
         int x_numDigits = 0,
             y_numDigits = 0;
         while(x >= places[x_numDigits])
         {
             if(y >= places[x_numDigits])
                 y_numDigits++;

             x_numDigits++;
         }

         //y must have less digits than x to be a possible solution.      
         if(y_numDigits < x_numDigits)
         {
             if(func(x, y))
             {
                 //x and y are a solution.
             }
         }
}

Where func is a function to determine if x and y only have a one digit difference. Here's my current method for calculating that:

bool func(int x, int y)
{
    int diff = 0;
    while(y > 0)
    {
        if(x % 10 != y % 10)
        {
            //If the rightmost digits do not match, move x to the left once and check again.
            x /= 10;
            diff++;
            if(diff > 1)
                return false;
        }
        else
        {
            //If they matched, both move to the next digit.
            x /= 10;
            y /= 10;
        }
    }

    //If the last digit in x is the only difference or x is composed of 0's led by 1 number, then x, y is a solution.
    if((x < 10 && diff == 0) || (x % 10 == 0))
        return true;
    else
        return false;
}

This is the fastest solution that I've been able to find so far (other methods I tried included converting X and Y into strings and using a custom subsequence function, along with dividing X into a prefix and suffix without each digit from the right to the left and seeing if any of these summed to Y, but neither worked as quickly). However, it still doesn't scale as well as I need it to with larger numbers, and I'm struggling to think of any other ways to optimize the code or underlying mathematical reasoning. Any advice would be greatly appreciated.

  • @SamVarshavchik So you're saying algorithmic questions have no purpose in learning programming? – XCS Oct 27 '19 at 20:58
  • Unfortunately, it's an assignment for one of my classes. I know that this problem itself is not practically useful, but I still need to figure out a more efficient way to perform these calculations. It feels like I'm missing something more generally useful that can simplify things here. – AstroMW Oct 27 '19 at 20:59
  • I would start with the number of digits X and Y have. If X has D digits, then Y has (D-1) digits. And their sum has to be N (which again, you know the number of digits). Probably based on this you can reduce your search pool by a lot. – XCS Oct 27 '19 at 21:00
  • If this is a homework assignment, can you explain what particular subject matter is this a homework assignment for? Is it for learning inheritance, operator overloading, templates, or some other key, fundamental aspect of C++? What specific C++ topic are you studying for which this is an appropriate homework assignment? – Sam Varshavchik Oct 27 '19 at 21:01
  • @Cristy It's difficult to narrow it down more than just throwing out cases where X and Y have the same number of digits. Y could have leading zeroes, so if N = 100 then X = 100 and Y = 00 is a valid solution. – AstroMW Oct 27 '19 at 21:02
  • @AstroMW Yes, but X will always either have same number of digits as N or `NdigitCount - 1`. – XCS Oct 27 '19 at 21:04
  • @Sam Varshavchik It's a general problem-solving course, with a focus on contest problems. The course is essentially just assigning us a problem such as this each week and tasking us to figure out an efficient solution. We could technically use a different language, so the class isn't centered around C++ specifically but rather on the problem-solving process. – AstroMW Oct 27 '19 at 21:06
  • I'm a little confused by the statement that X will always have the same number or one less than the digits in N. I would expect that to be fulfilled already by starting the loop at N / 2. Unfortunately, this still results in 500 million possible solutions on its own, which I've cut down a bit by checking if Y's digits < X's digits and the two modulus checks to see if one of the last two in X match the last one in Y. – AstroMW Oct 27 '19 at 21:20

1 Answers1

0

Consider solving a simpler solution first:

  • Finding X and Y such that X + Y = N

In pseudo-code you steps should look like this:

  • loop through the array and with every given item do the next:

    • add this number to Set and check whether there is N - item

This will work as O(n) complexity for unique array.

So improve it to work with duplicated numbers by looping through an array first and adding counter of duplicates for every number. Use some kind of Dictionary for c++ or extend Set. And every time you find the necessary number check for counter.

After doing that you will just have to write this "digit check" function and apply it when finding the value in Set.

fox112358
  • 79
  • 9
  • I don't think that I fully understand what you're suggesting here. I'm currently just storing correct solutions in a string for later output, so outside of repeated numbers, I don't see the benefit of keeping a set here. The input is just a single number N, with the task to find all possible X + Y combos as outlined above. Because even the same X will have a different Y depending on N, I don't see an easy way to use past calculations here outside of when a duplicate N is given. – AstroMW Oct 27 '19 at 21:31