Sua tarefa é escrever um programa ou uma função que produza n
números aleatórios do intervalo [0,1] com soma fixa s
.
Entrada
n, n≥1
, número de números aleatórios a serem gerados
s, s>=0, s<=n
, soma dos números a serem gerados
Saída
Um número aleatório n
de números de ponto flutuante com todos os elementos do intervalo [0,1] e a soma de todos os elementos iguais a s
, são emitidos de qualquer maneira conveniente e inequívoca. Todos os n
-tuplos válidos devem ter a mesma probabilidade dentro das limitações dos números de ponto flutuante.
Isso é igual à amostragem uniforme da interseção dos pontos dentro do n
cubo da unidade tridimensional e do n-1
hiperplano tridimensional que passa (s/n, s/n, …, s/n)
e é perpendicular ao vetor (1, 1, …, 1)
(veja a área vermelha na Figura 1 para três exemplos).
Figura 1: O plano de saídas válidas com n = 3 e soma 0,75, 1,75 e 2,75
Exemplos
n=1, s=0.8 → [0.8]
n=3, s=3.0 → [1.0, 1.0, 1.0]
n=2, s=0.0 → [0.0, 0.0]
n=4, s=2.0 → [0.2509075946818119, 0.14887693388076845, 0.9449661625992032, 0.6552493088382167]
n=10, s=9.999999999999 → [0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999]
Regras
- Seu programa deve terminar em menos de um segundo em sua máquina pelo menos com
n≤10
e quaisquer s válidos. - Se desejar, seu programa pode ser exclusivo na extremidade superior, ou seja,
s<n
os números de saída do intervalo semiaberto [0,1) (quebrando o segundo exemplo) - Se o seu idioma não suportar números de ponto flutuante, você poderá falsificar a saída com pelo menos dez dígitos decimais após o ponto decimal.
- As brechas padrão não são permitidas e os métodos padrão de entrada / saída são permitidos.
- Isso é código-golfe , então a entrada mais curta, medida em bytes, vence.
This is equal to uniformly sampling from the intersection
- eu posso ver um programa escolhendo aleatoriamente apenas nos cantos do cruzamento. Isso seria válido?s==0 or s==3
. Para todos os outros valores des
, o plano tem área diferente de zero e você precisa escolher aleatoriamente um ponto nesse plano.s=2.99999999999, n=3
? Podemos gerar reais aleatórios em múltiplos de, digamos1e-9
,?Respostas:
Wolfram Language (Mathematica) ,
9290 bytesExperimente online!
Código não golfe:
Aqui está uma solução que funciona em 55 bytes, mas por enquanto (Mathematica versão 12) é restrita
n=1,2,3
porqueRandomPoint
se recusa a extrair pontos de hiperplanos de dimensões mais altas (na versão 11.3 do TIO também falhan=1
). Pode funcionar para mais alton
no futuro:Experimente online!
Código não golfe:
fonte
JavaScript (Node.js) ,
122115 bytesExperimente online!
fonte
Python 2 ,
144128119 bytesExperimente online!
fonte
g(4, 2.0)
1.000 vezes para obter 4.000 pontos e os resultados são assim, o que parece bastante uniforme.Java 8,
194188196237236 bytes+49 bytes (188 → 196 e 196 → 237) para corrigir a velocidade dos casos de teste próximos a 1, bem como para corrigir o algoritmo em geral.
Experimente online
Explicação:
Usa a abordagem de esta resposta stackoverflow , dentro de um loop, enquanto um dos itens é ainda maior do que 1.
Além disso, se
2*s>n
,s
será alterado emn-s
, e um sinalizador está definido para indicar que devemos usar1-diff
em vez dediff
no resultado-array (obrigado pela dica @soktinpk e @ l4m2 ).fonte
test(10, 9.99);
10, 9.0
logo após a edição para corrigir on=10, s=9.999999999999
caso de teste .. Não tenho certeza se existe uma correção em Java enquanto ainda mantém sua aleatoriedade uniforme .. Terá que pensar nisso por um tempo. Por enquanto, vou editá-lo para declarar o tempo limite.n-s<1
você pode ligarf(n,n-s)
e virar todos os números1/2
(ou seja, substituirx
por1-x
), como l4m2 fez. Isso pode resolver o problema de númeross
próximos an
.s+s>n
vez den-s<1
, mas quando olhei para as outras respostas do JavaScript, de fato fazia sentido. Tudo está consertado agora, incluindo outro bug que ainda estava presente. Os bytes subiram um pouco, mas agora todos funcionam. Trabalhará a contagem de bytes a partir daqui. :)JavaScript (Node.js) , 153 bytes
Experimente online!
fonte
C ++ 11,
284267 bytes-17 bytes graças ao Zacharý
Usa biblioteca aleatória C ++, saída na saída padrão
Para ligar, você só precisa fazer isso:
Onde o parâmetro do modelo (aqui, 2) é N e o parâmetro real (aqui, 0,0) é S
fonte
<z>
eu
typedef float z;template<int N>void g(z s){z a[N],d=s/N;int i=N;for(;i;)a[--i]=d;std::uniform_real_distribution<z>u(.0,d<.5?d:1-d);std::default_random_engine e;for(;i<N;){z c=u(e);a[i]+=c;a[++i]-=c;}for(;i;)std::cout<<a[--i]<<' ';}
. A nova linha não tem que ser o separador entre os itensd
completamente, alterandod=s/N
as/=N
Sugerir reformulação da segunda voltafor(z c;i<N;a[++i%N]-=c)a[i]+=c=u(e);
, em vez defor(;i<N;){z c=u(e);a[i]+=c;a[++i]-=c;}
(note o agregado%N
, a fim de tornar a calcular programa o primeiro número corretamente)Limpo ,
221201 bytesNúmeros limpos, de código de golfe ou aleatórios. Escolhe dois.
Experimente online!
Função parcial literal
:: (Int Real -> [Real])
. Só produzirá novos resultados uma vez por segundo.Precisas até pelo menos 10 casas decimais.
fonte
R , 99 bytes (com
gtools
pacote)Experimente online!
fonte
C,
132127125118110107 bytes-2 bytes graças a @ceilingcat
Experimente online!
fonte
[0,1]
e sua distribuição conjunta não é uniforme.n=4
, os valoress=3.23
e ass=0.89
saídas fora do intervalo. Mais precisamente, a distribuição deX-s/n
deve dependers
, mas não.Haskell ,
122217208 bytesExperimente online!
Às vezes, as respostas estão um pouco erradas devido, presumo, a um erro de ponto flutuante. Se for um problema, posso corrigi-lo a um custo de 1 byte. Também não tenho certeza de quão uniforme isso é (tenho certeza de que está bem, mas não sou tão bom nesse tipo de coisa), então vou descrever meu algoritmo.
A idéia básica é gerar um número
x
, subtraí-los
e repetir até que tenhamosn
elementos e os embaralhe. Gerox
com um limite superior de 1 ous
(o que for menor) e um limite inferior des-n+1
ou 0 (o que for maior). Esse limite inferior existe para que na próxima iteraçãos
ainda seja menor ou igual an
(derivação:s-x<=n-1
->s<=n-1+x
->s-(n-1)<=x
->s-n+1<=x
).EDIT: Obrigado a @ michi7x7 por apontar uma falha na minha uniformidade. Acho que o corrigi com a reprodução aleatória, mas deixe-me saber se há outro problema
EDIT2: contagem de bytes aprimorada mais restrição de tipo fixo
fonte
Haskell , 188 bytes
Ungolfed:
Experimente online!
fonte