3

Okay, so here is what I'm trying to do. The user inputs a number. I'm trying to write a recursive function that counts the number of sequences that sum up to that number (user input).

For example:

Then the number of sequences that sum up to 6 is 11 (including 6 itself).

6
5+1
4+1+1
3+1+1+1
2+1+1+1+1
1+1+1+1+1+1
2+2+1+1
3+2+1
4+2
2+2+2
3+3

I'm also trying not to have sequences that repeat, for example 2+2+1+1 and 1+1+2+2.

The reason i have no code included is i cannot figure out a recursive way to make this work so i'm seeking some guidance. Thanks in advance!

ADDITION:

Okay so here is what my thought process is. 6 can be split as...

6
5+1
4+2
3+3

but it is still not over,if you take 5+1 and consider the +1 part to be completed; you use the same trick to proceed.

4+1+1
3+2+1

but then they start to repeat..... and i don't get further than this second step in my plan.

Okay so code wise this is what I've come up with on my own. Looking for suggestions to fix this.

int sum(int number, int min, int counter)
{
    int temp=0, n;
    n=number+temp;
    if (number>=(n/2)& number!=min)
    {
        while (number>=(n/2))
        {
            cout << number << "+"<< temp <<"\n";
            number --;
            temp ++;
            counter ++;
        }
    }
    sum(temp, 1,counter);
    return counter;
}

int main()
{
    int number;

    cout << "Please enter the number: ";
    cin >> number ;
    cout << "\n";

    sum(number, 1, 0);

    return 0;
}

I do realize this is all sorts of messed up.

Zud
  • 4,247
  • 4
  • 24
  • 25
  • I can build this a function that does this but i have problems with getting doubles of the sequences and sequences that don't even belong. So i'm starting the function over from scratch. Therefor im just looking for some direction. – Zud Dec 08 '10 at 03:58
  • What function? Where? We can't see anything in your question. – casablanca Dec 08 '10 at 04:01
  • It is possible to enumerate all partitions of a positive integer without recursion, too? Are you interested in non-recursive function, too? – George Robinson Jul 06 '19 at 19:04
  • Does this answer your question? [How to to determine the number of ways a number can be broken down into sums of smaller numbers](https://stackoverflow.com/questions/20311254/how-to-to-determine-the-number-of-ways-a-number-can-be-broken-down-into-sums-of) – Karl Knechtel Mar 07 '23 at 00:13

6 Answers6

4

Hint: try to find a function that gives the number of sequences with sum n and terms not larger than k.

EDIT:
Forgive me if this sounds harsh, but... your updated code is all wrong. It's hard to see what you intended. I can guess, but that would be pointless.

Here's what I had in mind: a sequence should be in nonincreasing order, like "2 2 1 1 1 1". So how many such sequences add up to 6? Well, find the number of such sequences starting with 1, then the number of sequences starting with 2, and so on up to 6, and add them up. And how many sequences start with 2 and add up to six? (This is where the recursion comes in.) In each such sequence, the first term is 2 and the rest add up to 4 with no term exceeding 2, so we must find the number of sequences adding up to 4 with no term greater than 2. So write the signature first, then the iteration loop, then the recursive call and you're done.

EDIT:
All right, here's everything but the loop:

int partition(int n, int max)
{
  if(n==0)
    return(0);
  int ret = 0;
  if(n<=max)
    ret=1;
  for(...)
  {
    ...
  }
  return(ret);
}

Can you fill in the blanks?

Beta
  • 96,650
  • 16
  • 149
  • 150
  • Okay so here is what my thought process is. 6 can be split as... 6 5+1 4+2 3+3 but it is still not over,if you take 5+1 and consider the +1 part to be completed; you use the same trick to proceed. 4+1+1 3+2+1 but then they start to repeat..... – Zud Dec 08 '10 at 04:09
  • Co-hint: This will help you find sequences where the terms always appear in non-increasing order. Because of this order, you won't get problems like 2+2+1+1 and 1+1+2+2 both appearing, because you'll never generate the second one. – j_random_hacker Dec 08 '10 at 04:12
  • @Alec: Think about ways to guarantee distinctness. For example: If 2 sequences begin with different numbers, and each has all numbers in non-increasing order, then they must be distinct -- right? That suggests that when looking for the partitions of a given number (that's what these sums are called), you should arrange things so that you never *modify* the 1st term in the sequence. E.g. given some number n, you can generate all partitions that start with 1 and afterward contain no number > 1, then all partitions that start with 2 and afterward contain no number > 2, etc. – j_random_hacker Dec 08 '10 at 07:01
  • @ Beta: I am still having problems with this is there any way you can help? – Zud Dec 10 '10 at 04:53
0

i think it is close to the probability theory
amount of combinations of set {1,2,3,4,5,6} giving summary 6

Vasserman
  • 71
  • 3
0

These are called Integer Partitions, and there is a simple way to calculate the number of partitions of any number using an intermediate function. Take a look here: Integer Partition.

Khaled Alshaya
  • 94,250
  • 39
  • 176
  • 234
0

Let f(n) be the function we want, that generates sequences of integers that add to n, without permutations

Define

f(n) = g(n,n)

g(n,p) = { i \in 1..min(n, p): [i g(n-i,i)] }

Community
  • 1
  • 1
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
0

Define P(n) as the number of ways to partition n, restricting n to be an integer, n >= 1.

Define p(n, k) as the number of ways to partition n using numbers no larger than k, restricting k to be an integer, k >= 1, k <= n.

It follows that P(n) = sum (i: 1..n) p(n, i).

To find p(n, k), first note that we neatly avoid double-counting by simply keeping the partition sorted: take the largest chunk first. So the first chunk may have any size from 1 up to k, and then the rest of the chunks must account for the rest of the total n, and be no larger than the first chunk.

Thus p(n, k) = sum (i: 1..k) p(n - i, i).

As a base case, p(1, 1) = 1.


A sample implementation, very much not guaranteed to be at all efficient, or even to compile (but it should give you the basic idea) - spoilers!

// A utility function to represent the result of appending to a vector,
// as a new vector (without affecting the previous one).
template <typename T>
vector<T> operator<<(vector<T> copy, T to_append) {
    // We passed by value to get a copy implicitly.
    copy.push_back(to_append);
    return copy;
}

// A utility function to append one vector to another.
template <typename T>
vector<T>& operator+=(vector<T>& original, const vector<T>& to_append) {
    // 'copy' is in namespace std:: and defined in <algorithm>.
    // 'back_inserter' is in namespace std:: and defined in <iterator>.
    copy(to_append.begin(), to_append.end(), back_inserter(original));
    return original;
}

vector<vector<int> > partitions(int remaining, int limit, vector<int> prefix) {
    // Finds the partitions of some larger number which start with the
    // numbers in 'prefix', such that the rest of the "chunks" sum to
    // 'remaining' and are all no larger than 'limit'.

    // 'max' is in namespace std:: and defined in <algorithm>. We restrict
    // the 'limit' to be no more than 'remaining'.
    limit = max(remaining, limit);

    vector<vector<int> > result;

    // Base case. 
    if (remaining == 1) {
        return result << (prefix << 1); // note the parentheses are required!
    }

    for (int i = limit; i > 0; --i) {
        result += partitions(remaining - i, i, prefix << i);
    }

    return result;
}
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
  • Would you mind taking a look at my code and seeing if you can tell whats wrong. – Zud Dec 08 '10 at 06:24
  • The most obvious problem: you are expecting `counter` to be passed by reference and thus to accumulate values across all the recursive calls. You could just change the parameter to be passed by reference, but you'd miss a valuable lesson about how recursion works. What you really want to do is have `counter` as a local variable, and then **add in** the values that are returned by the recursive calls. In general, ignoring the return value of a function that returns a value is a sign that you might be doing something wrong; you might be able to turn up compiler warnings high enough to flag this. – Karl Knechtel Dec 08 '10 at 07:06
  • The next most obvious problem: trying to print the partitions as you go is much harder than you expect. Your output line only allows for outputting two numbers, and a partition may consist of more than that. In general, you would have to "carry forward" the "chunks" of the partition found so far into the next recursive step. I'm working on a solution that I'll edit with, which assembles the partitions in a vector of vectors of ints, which you can then cycle through to print. No guarantees about efficiency :) – Karl Knechtel Dec 08 '10 at 07:29
0

The algorithm is well covered in this question.

Community
  • 1
  • 1
Tristan
  • 916
  • 5
  • 10