Generating $n$ random samples every time

Is it possible to generate $n$ random samples, and always ensure that $n$ samples are generated?

eg For $n=5$:

n=5; {n1, n2, n3, n4, n5} = (While[Total[set = Reverse@Sort@Round
[(tmp = RandomInteger[100, n])/Total@tmp 100]] != 100]; set);
s = Reverse[Sort[{n1, n2, n3, n4, n5}]];
a = rs[]; b = s[]; c = s[]; d = s[]; e = s[];
PieChart[{a, b, c, d, e}, ImageSize -> 200,
ChartLabels -> {Style[StringForm["A:%", a], 10],
Style[StringForm["B:%", b], 10],
Style[StringForm["C:%", c], 10],
Style[StringForm["D:%", d], 10],
Style[StringForm["E:%", e], 10]}]


is ok, but for large enough $n$ the numbers are often "used up" before the last few get a chance to sample (so, in the example of the above pie chart, "E" often doesn't feature).

Is it possible to avoid the samples reaching $0$ before last $n$ is reached? (Obviously, by the time $n=100$, each sample should have value of $1$.)

• This is very unclear. There is no $n$ in your code. – Simon Woods May 26 '14 at 12:09
• Question edited accordingly. – martin May 26 '14 at 12:15
• If your summed value (100 in your example) and n are not too large you could use RandomSample[IntegerPartitions[100, 5], 1]. However, do take care as IntegerPartitions can blow up extremely fast and fill up all of your memory (potentially crashing your kernel) if you're not cautious. – Sjoerd C. de Vries May 26 '14 at 12:24
• Great - thank you - will give it a go :) – martin May 26 '14 at 12:25
• So you are trying to create a list of n random integers such that Total[list]==100 and Min[list]==1 ? – Simon Woods May 26 '14 at 12:25

Partitioning n into k elements

Here's a way to efficiently use the logic of partitioning from my first attempt (which can be found in the edit history).

Imagine slicing the ordered set of integers at k-1 distinct places between integers 1 and n-1. Then we simply evaluate the size of each slice (in terms of the number of integers contained in the respective interval).

A suggestion by Simon Woods helped streamline the code.

g[n_,k_]:=Differences@Join[{0},Sort@RandomSample[Range[n-1],k-1],{n}]


Examples

g[100, 5] // AbsoluteTiming


{0.000068, {16, 26, 13, 16, 29}}

g[100, 15] // AbsoluteTiming
Total@%[]


{0.000052, {5, 28, 7, 1, 3, 3, 5, 5, 12, 3, 1, 11, 9, 4, 3}}
100

g[100, 35] // AbsoluteTiming
Total@%[]


{0.000063, {1, 1, 6, 2, 5, 1, 2, 1, 1, 8, 4, 1, 3, 1, 1, 2, 6, 4, 5, 1, 5, 1, 4, 1, 2, 12, 4, 2, 4, 1, 1, 1, 2, 1, 3}}
100

g[997, 55] // AbsoluteTiming
Total@%[]


{0.000065, {20, 29, 72, 10, 4, 13, 43, 42, 9, 12, 1, 19, 10, 1, 9, 22, 63, 8, 9, 42, 8, 11, 27, 3, 8, 16, 18, 33, 23, 1, 33, 30, 1, 4, 49, 24, 1, 1, 6, 31, 2, 4, 23, 8, 32, 12, 9, 6, 39, 2, 13, 1, 39, 4, 37}}
997

• +1 This must be the most efficient approach I think. You could write the output more succinctly as Differences@Join[{0}, slices, {n}] – Simon Woods May 26 '14 at 14:53
• Thanks for the suggested shortening of code, which I will incorporate. – DavidC May 26 '14 at 15:40

If the problem is to create a list of $n$ random integers such that Total[list]==100 and Min[list]>=1, how about starting with a list of $n$ ones (taking care of the Min[list] >= 1 criterion) and then incrementing a random element of the list $100-n$ times.

n = 50;
list = ConstantArray[1, n];
Scan[list[[#]]++ &, RandomInteger[{1, n}, 100 - n]];

Reverse @ Sort @ list
(* {4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} *)

Total @ list
(* 100 *)

• Thanks for your help - very much appreciated :) – martin May 26 '14 at 16:41