Ваша задача - написать программу или функцию, которая выводит n
случайные числа из интервала [0,1] с фиксированной суммой s
.
вход
n, n≥1
, количество случайных чисел для генерации
s, s>=0, s<=n
, сумма чисел, которые будут сгенерированы
Выход
Случайный n
набор чисел с плавающей запятой со всеми элементами из интервала [0,1] и суммой всех элементов, равных s
, выводится любым удобным однозначным способом. Все допустимые n
кортежи должны быть одинаково вероятными в пределах ограничений чисел с плавающей запятой.
Это равносильно равномерной выборке из пересечения точек внутри n
-мерного единичного куба и n-1
-мерной гиперплоскости, которая проходит (s/n, s/n, …, s/n)
и перпендикулярна вектору (1, 1, …, 1)
(см. Красную область на рисунке 1 для трех примеров).
Рисунок 1: Плоскость действительных выходов с n = 3 и суммами 0,75, 1,75 и 2,75
Примеры
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]
правила
- Ваша программа должна завершиться менее чем за секунду на вашем компьютере, по крайней мере, с
n≤10
любым допустимым s - Если вы хотите, ваша программа может быть эксклюзивной на верхнем конце, то есть
s<n
и выходных чисел из полуоткрытого интервала [0,1) (ломая второй пример) - Если ваш язык не поддерживает числа с плавающей запятой, вы можете подделать вывод не менее десяти десятичных цифр после запятой.
- Стандартные лазейки запрещены, и стандартные методы ввода / вывода разрешены.
- Это код-гольф , поэтому выигрывает самая короткая запись в байтах.
This is equal to uniformly sampling from the intersection
- я вижу программу, выбирающую случайным образом только из углов этого пересечения. Это будет действительным?s==0 or s==3
. Для всех других значенийs
плоскость имеет ненулевую площадь, и вы должны случайным образом выбрать точку на этой плоскости.s=2.99999999999, n=3
? Можем ли мы генерировать случайные реальные числа, например, кратные1e-9
?Ответы:
Wolfram Language (Mathematica) ,
9290 байтПопробуйте онлайн!
Негольфированный код:
Вот решение, которое работает в 55 байтах, но на данный момент (версия 12 Mathematica) ограничено,
n=1,2,3
потому чтоRandomPoint
отказывается рисовать точки из гиперплоскостей с большей размерностью (в версии 11.3 TIO это также не удаетсяn=1
) Это может работать для более высокого уровняn
в будущем, хотя:Попробуйте онлайн!
Негольфированный код:
источник
JavaScript (Node.js) ,
122115 байтПопробуйте онлайн!
источник
Python 2 ,
144128119 байтовПопробуйте онлайн!
источник
g(4, 2.0)
1000 раз, чтобы получить 4000 очков, и результаты выглядят примерно так, что выглядит довольно равномерно.Ява 8,
194188196237236 байт+49 байтов (188 → 196 и 196 → 237), чтобы зафиксировать скорость тестовых случаев, близких к 1, а также исправить алгоритм в целом.
Попробуйте онлайн
Объяснение:
Использует подход в этом ответе StackoverFlow , внутри цикла, пока один из элементов все еще больше 1.
Также, если
2*s>n
,s
будет изменен наn-s
, и установлен флаг, чтобы указать, что мы должны использовать1-diff
вместоdiff
в массиве результатов (спасибо за отзыв @soktinpk и @ l4m2 ).источник
test(10, 9.99);
10, 9.0
сразу после того, как я отредактировал исправлениеn=10, s=9.999999999999
тестового примера. Не уверен, есть ли исправление в Java, все еще сохраняя его равномерную случайность. Придется подумать об этом некоторое время. Сейчас я отредактирую это, чтобы заявить, что это истекло.n-s<1
вы можете позвонитьf(n,n-s)
и перевернуть каждый номер1/2
(т.е. заменитьx
на1-x
), как это сделал l4m2. Это может решить проблему с номерами,s
рядом с которымиn
.s+s>n
вместоn-s<1
, но когда я посмотрел на другие ответы JavaScript, это действительно имело смысл. Теперь все исправлено, включая еще одну ошибку, которая все еще присутствовала. Количество байтов возросло, но теперь все работает. Будет работать отсчет байтов отсюда. :)JavaScript (Node.js) , 153 байта
Попробуйте онлайн!
источник
C ++ 11,
284267 байт-17 байт благодаря
случайной библиотеке Zacharý Uses C ++, вывод на стандартный вывод
Чтобы позвонить, нужно просто сделать это:
Где параметр шаблона (здесь, 2) равен N, а фактический параметр (здесь 0,0) равен S
источник
<z>
иu
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]<<' ';}
. Новая строка не должна быть разделителем между элементамиd
полностью избавиться , переключившисьd=s/N
наs/=N
Предлагать переработку второго циклаfor(z c;i<N;a[++i%N]-=c)a[i]+=c=u(e);
вместоfor(;i<N;){z c=u(e);a[i]+=c;a[++i]-=c;}
(обратите внимание на добавленное%N
, чтобы программа правильно вычислила первое число)Чисто ,
221201 байтЧисто, код-гольф или случайные числа. Выбери два.
Попробуйте онлайн!
Частичная функция буквальная
:: (Int Real -> [Real])
. Новые результаты будут появляться только раз в секунду.Точность не менее 10 знаков после запятой.
источник
R , 99 байт (с
gtools
пакетом)Попробуйте онлайн!
Мы хотим сделать выборку равномерно из множестваA~= { ш1, … , ШN: ∀ i , 0 < wя< 1 ; ∑ шя= s } веся s A= { ш1, … , ШN: ∀ i , 0 < wя< 1s; ∑ шя= 1 }
Еслиs = 1 Д я г I с х в л е т ( 1 , 1 , ... , 1 ) с ≠ 1 < 1 / с s
источник
C
132127125118110107 байт-2 байта благодаря @ceilingcat
Попробуйте онлайн!
источник
[0,1]
, и их совместное распределение не является равномерным.n=4
значенийs=3.23
иs=0.89
выводов за пределы диапазона. Более того, распределениеX-s/n
должно зависеть отs
, но это не так.Haskell ,
122217208 байтПопробуйте онлайн!
Иногда ответы слегка отклоняются из-за ошибки с плавающей запятой. Если это проблема, я могу исправить ее стоимостью 1 байт. Я также не уверен, насколько это равномерно (уверен, что это нормально, но я не настолько хорош в подобных вещах), поэтому я опишу свой алгоритм.
Основная идея состоит в том, чтобы сгенерировать число,
x
затем вычесть егоs
и повторять до тех пор, пока мы не получимn
элементы, а затем не перемешать их. Я генерируюx
с верхней границей 1 илиs
(в зависимости от того, что меньше) и нижней границейs-n+1
или 0 (в зависимости от того, что больше). Эта нижняя граница существует для того, чтобы на следующей итерацииs
она была меньше или равнаn
(производная:s-x<=n-1
->s<=n-1+x
->s-(n-1)<=x
->s-n+1<=x
).РЕДАКТИРОВАТЬ: Спасибо @ michi7x7 за указание на недостаток в моей однородности. Я думаю, что я исправил это с тасованием, но дайте мне знать, если есть другая проблема
EDIT2: улучшено количество байтов плюс фиксированное ограничение типа
источник
Haskell , 188 байт
Ungolfed:
Попробуйте онлайн!
источник