Random numbers with fixed sum
JavaScript (Node.js), 122 115 bytes
N=>W=S=>2*S>N?W(N-S).map(t=>1-t):(t=(Q=s=>n?[r=s-s*Math.random()**(1/--n),...r>1?[++Q]:Q(s-r)]:[])(S,n=N),Q?t:W(S))
Try it online!
Python 2, 144 128 119 bytes
from random import*
def f(n,s):
r=min(s,1);x=uniform(max(0,r-(r-s/n)*2),r);return n<2and[s]or sample([x]+f(n-1,s-x),n)
Try it online!
- -20 bytes, thanks to Kevin Cruijssen
Java 8, 194 188 196 237 236 bytes
n->s->{double r[]=new double[n+1],d[]=new double[n],t;int f=0,i=n,x=2*s>n?1:0;for(r[n]=s=x>0?n-s:s;f<1;){for(f=1;i-->1;)r[i]=Math.random()*s;for(java.util.Arrays.sort(r);i<n;d[i++]=x>0?1-t:t)f=(t=Math.abs(r[i]-r[i+1]))>1?0:f;}return d;}
+49 bytes (188 → 196 and 196 → 237) to fix the speed of test cases nearing 1, as well as fix the algorithm in general.
Try it online
Explanation:
Uses the approach in this StackoverFlow answer, inside a loop as long as one of the items is still larger than 1.
Also, if 2*s>n
, s
will be changed into n-s
, and a flag is set to indicate we should use 1-diff
instead of diff
in the result-array (thanks for the tip @soktinpk and @l4m2).
n->s->{ // Method with integer & double parameters and Object return-type
double r[]=new double[n+1]
// Double-array of random values of size `n+1`
d[]=new double[n],
// Resulting double-array of size `n`
t; // Temp double
int f=0, // Integer-flag (every item below 1), starting at 0
i=n, // Index-integer, starting at `n`
x= // Integer-flag (average below 0.5), starting at:
2*s>n? // If two times `s` is larger than `n`:
1 // Set this flag to 1
: // Else:
0; // Set this flag to 0
for(r[n]=s= // Set both the last item of `r` and `s` to:
x>0? // If the flag `x` is 1:
n-s // Set both to `n-s`
: // Else:
s; // Set both to `s`
f<1;){ // Loop as long as flag `f` is still 0
for(f=1; // Reset the flag `f` to 1
i-->1;) // Inner loop `i` in range (n,1] (skipping the first item)
r[i]=Math.random()*s;
// Set the i'th item in `r` to a random value in the range [0,s)
for(java.util.Arrays.sort(r);
// Sort the array `r` from lowest to highest
i<n; // Inner loop `i` in the range [1,n)
;d[i++]= // After every iteration: Set the i'th item in `d` to:
x>0? // If the flag `x` is 1:
1-t // Set it to `1-t`
: // Else:
t) // Set it to `t`
f=(t=Math.abs( // Set `t` to the absolute difference of:
r[i]-r[i+1]))
// The i'th & (i+1)'th items in `r`
>1? // And if `t` is larger than 1 (out of the [0,1] boundary)
0 // Set the flag `f` to 0
: // Else:
f;} // Leave the flag `f` unchanged
return d;} // Return the array `d` as result