tags:

views:

399

answers:

4

I'm looking for a formula that can spread out numbers in a linear format based on a minimum number, max number and amount of numbers (or dots) between. The catch is, the closer you get to the max, the more numbers should be there.

An example (number will vary and will be about 100 times larger)

Min = 0
Max = 16
AmountOfNumbersToSpread = 6

0 1 2 3 4 5 6 7 8 9 A B C D E F

1           2       3   4   5 6

Thanks for the help in advance.

+1  A: 

Basically, you should have something that looks like:

  1. Generate a random number between 0 and 1.
  2. Implement your desired distribution function (a 1:1 function from [0,1]->[0,1]).
  3. Scale the result of the distribution function to match your desired range.

The exact function used for the second point is determined according to how exactly you want the numbers to be distributed, but according to your requirement, you'll want a function that has more values close to 1 than 0. For example, a sin or cos function.

Tal Pressman
A: 

Tried this on paper and it worked:

given MIN, MAX, AMOUNT:

Length = MAX - MIN
"mark" MIN and MAX
Length--, AMOUNT--
Current = MIN
While AMOUNT > 1
  Space = Ceil(Length * Amount / (MAX - MIN))
  Current += Space
  "mark" Current

By "mark" I mean select that number, or whatever you need to do with it.

nairdaen
close, but doesn't work with larger numbers. List<int> lstMin = new List<int>(); int Min = 1; int Max = 1500; int Length = Max - Min; int Current = Min; int ConnectedClient = 7; double Space; while(ConnectedClient > 0) { Space = Math.Ceiling((double)(Length * ConnectedClient / (Max - Min))); Current += (int)Space; ConnectedClient--; Length--; lstMin.Add(Current); }
that didn't post well, put in a answer below.
A: 

Close answer, not quite though, needs to work for larger numbers.

List<int> lstMin = new List<int>();

int Min = 1;
int Max = 1500;

int Length = Max - Min;
int Current = Min;
int ConnectedClient = 7;
double Space;

while(ConnectedClient > 0)
{
    Space = Math.Ceiling((double)(Length * ConnectedClient / (Max - Min)));
    Current += (int)Space;

    ConnectedClient--;
    Length--;

    lstMin.Add(Current);
}
+1  A: 

Based on the answer of Tal Pressman, you can write a distribution function like this:

IEnumerable<double> Spread(int min, int max, int count, Func<double, double> distribution)
    {
    double start = min;
    double scale = max - min;
    foreach (double offset in Redistribute(count, distribution))
        yield return start + offset * scale;
    }

IEnumerable<double> Redistribute(int count, Func<double, double> distribution)
    {
    double step = 1.0 / (count - 1);
    for (int i = 0; i < count; i++)
        yield return distribution(i * step);
    }

You can use any kind of distribution function which maps [0;1] to [0;1] this way. Examples:

quadratic

Spread(0, 16, 6, x => 1-(1-x)*(1-x))

Output: 0 5.76 10.24 13.44 15.36 16

sine

Spread(0, 16, 6, x => Math.Sin(x * Math.PI / 2))

Output: 0 4.94427190999916 9.40456403667957 12.9442719099992 15.2169042607225 16
Juozas Kontvainis
This worked perfect, and at the same time taught me something cool. Thanks A TON for this.