If we produce all the partitions of 10 (of which there are 42) then we can pick p
from that collection randomly (uniformly, if you want). There will be np
elements in the chosen partition. We can choose np
of the naturals 1..24, and use those as the positions of the Vector V
to which to assign the entries of p
.
The following acts inplace on Vector V
. Initialization to precompute the set of all partitions of 10, and to construct V and the random generating function (1..42), takes almost no time at all.
Subsequent generation of a solution, populating V, takes about 0.00125 sec on an Intel i7.
restart: randomize(): # different results for each Maple session interface(rtablesize=24): G:=proc(v::Vector,y,all) local i,p,np,pos; ArrayTools:-Fill(0,v); p:=all[y()]; np:=nops(p); pos:=[combinat[randcomb](24,np)[]]; for i from 1 to np do v[pos[i]]:=p[i]; end do; NULL; # acts in-place on V end proc: st:=time(): All:=combinat[partition](10): Y:=rand(1..nops(All)): V:=Vector[row](24): time()-st; 0. G(V,Y,All); V; [0, 0, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2] G(V,Y,All); V; [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 4, 0, 0, 4, 0, 0, 0, 0, 0] G(V,Y,All); V; [0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4] st:=time(): for j from 1 to 10^3 do G(V,Y,All); end do: time()-st; # time for 1000 regenerations 0.125
The above picks from the complete set of partitions of 10 (ie. "ways to split up 10 as a sum of positive integers") with each having an equal weight, hence a uniform discrete distribution. That might not be what you want. Another way to generate each p
is to randomly select values from {1..10} while computing a running total, stopping whenever the running total is exactly 10, and rejecting/reselecting each chosen value if it pushes the running total over 10.