Just for fun I created an algorithm that computes every possible combination from a given rugby score (3, 5 or 7 points). I found two methods : The first one is brute force, 3 imbricated for loops. The other one is recursion.
Problem is some combinations appear multiple times. How can I avoid that ?
My code :
#include <iostream>
using namespace std;
void computeScore( int score, int nbTryC, int nbTryNC, int nbPenalties );
int main()
{
int score = 0;
while (true)
{
cout << "Enter score : ";
cin >> score;
cout << "---------------" << endl << "SCORE = " << score << endl
<< "---------------" << endl;
// Recursive call
computeScore(score, 0, 0, 0);
}
return 0;
}
void computeScore( int score, int nbTryC, int nbTryNC, int nbPenalties )
{
const int tryC = 7;
const int tryNC = 5;
const int penalty = 3;
if (score == 0)
{
cout << "* Tries: " << nbTryC << " | Tries NT: " << nbTryNC
<< " | Penal/Drops: " << nbPenalties << endl;
cout << "---------------" << endl;
}
else if (score < penalty)
{
// Invalid combination
}
else
{
computeScore(score - tryC, nbTryC+1, nbTryNC, nbPenalties);
computeScore(score - tryNC, nbTryC, nbTryNC+1, nbPenalties);
computeScore(score - penalty, nbTryC, nbTryNC, nbPenalties+1);
}
}
One way to think about this is to realize that any time you have a sum, you can put it into some “canonical” form by sorting all the values. For example, given
You could also write this as
This gives a few different options for how to solve your problem. First, you could always sort and record all of the sums that you make, never outputting the same sum twice. This has the problem that you’re going to end up repeatedly generating the same sums multiple different times, which is extremely inefficient.
The other (and much better) way to do this is to update the recursion to work in a slightly different way. Right now, your recursion works by always adding 3, 5, and 7 at each step. This is what gets everything out of order in the first place. An alternative approach would be to think about adding in all the 7s you’re going to add, then all the 5’s, then all the 3’s. In other words, your recursion would work something like this:
The idea here is to add in all of the 7’s you’re going to use before you add in any 5’s, and to add in any 5’s before you add in any 3’s. If you look at the shape of the recursion tree that’s made this way, you will find that no two paths end up trying out the same sum, because when the path branches either a different number was added in or the recursion chose to start using the next number in the series. Consequently, each sum is generated exactly once, and no duplicates will be used.
Moreover, this above approach scales to work with any number of possible values to add, so if rugby introduces a new SUPER GOAL that’s worth 15 points, you could just update the
kValuesarray and everything would work out just fine.Hope this helps!