0

Problem Statement:

We are given

  1. A set of T numbers S1, S2,....ST

  2. An integer called Range

This means S1 can take on (2*Range+1) values (S1-Range,S1-Range+1,...S1, S1+1,....S1+Range) Similarly S2, ...ST can take on 2*Range+1 values

Problem 1: How do I enumerate all the possible sequences? I.e all the (2*Range-1)^T sequences (S1-Range,S2,...ST), S1-Range+1,S2,...ST), ....., (S1, S2-Range,S3,....ST) etc

Problem 2: How do I only list the sequences whose sum is S1+S2+...+ST?

For problem 1: The approach I am considering is to do a

for (i=0; i<pow(Range,T);i++)
{
   Sequences that can be derived from i are
   1. {Si + i mod pow(Range,i)}
   2. {Si - i mod pow(Range,i)}
}

Any other more elegant solution?

Also, any ideas for problem 2?

Smart Home
  • 801
  • 7
  • 26

1 Answers1

2

For #1, one way is to think of it like how you increment a number. You increment the last digit, and when it overflows you set it back to initial value (0) and increment the next digit.

So, create an array of size T, then initialize elements to (S1-Range, S2-Range, ..., ST-Range). Print it.

Now increment last value to ST-Range+1. Print it. Keep incrementing and printing until you reach ST+Range. When trying to increment, reset back to ST-Range, then move one position left and increment that. Repeat if that overflows too. If moving all the way left, you're done, otherwise print it.

// Input: T, S[T], Range
create V[T]
for (i in 1..T):
    V[i] = S[i] - Range
loop forever {
    print V
    i = T
    V[i]++
    while V[i] > S[i] + Range {
        V[i] = S[i] - Range
        i--
        if i < 1:
            return // we're done
        V[i]++
    }
}

For #2, it's a bit different. For the description, I'm going to ignore the values of S, and focus of the delta (-Range, ..., 0, ..., +Range) for each position, calling it D.

Since sum(D)=0, the initial set of values are (-Range, -Range, ..., +Range, +Range). If T is even, first half are -Range, and second half are +Range. If T is odd, then middle value is 0.

Now look at how you want the iterations to go:

-2 -2  0  2  2
-2 -2  1  1  2
-2 -2  1  2  1
-2 -2  2  0  2  (A)
-2 -2  2  1  1
-2 -2  2  2  0
-2 -1 -1  2  2
-2 -1  0  1  2
-2 -1  0  2  1
-2 -1  1  0  2

The logic here is that you skip the last digit, since it's always a function of the other digits. You increment the right-most digit that can be incremented, and reset the digits to the right of it to the lower possible values that will give sum(D)=0.

Logic is a bit more complicated, so I'll let you have some fun writing it. ;-)

A good helper method thought, would be a method to reset digits after a certain position to their lowest possible value, given a start delta. You can then use it to initialize the array to begin with by calling reset(1, 0), i.e. reset positions 1..T using a starting delta of 0.

Then, when you increment D[3] to 2 in the step marked A above, you call reset(4, -2), i.e. reset positions 4..5 using a starting delta of -2. With max value of 2 (Range) for last digit, then means D[4] cannot be lower than 0.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • Thanks @Andreas. Solution to problem #1 is super clear. But I dont get all the steps in your solution to #2. Is there any well known algorithm in combinatorics that is related to this problem that I can look up online? – Smart Home Jun 13 '16 at 03:40
  • Not that I'm aware of, sorry. I just made that up, as a suggestion of one way it might be done. – Andreas Jun 13 '16 at 13:53