Twoim zadaniem jest napisanie programu lub funkcji tego wyjścia n
liczb losowych z przedziału [0,1] z ustaloną sumę s
.
Wkład
n, n≥1
, liczba liczb losowych do wygenerowania
s, s>=0, s<=n
, suma liczb do wygenerowania
Wydajność
Losowa n
liczba liczb zmiennoprzecinkowych ze wszystkimi elementami z przedziału [0,1] i sumą wszystkich elementów równych s
, jest generowana w dowolny dogodny, jednoznaczny sposób. Wszystkie ważne n
pary muszą być jednakowo prawdopodobne w granicach liczb zmiennoprzecinkowych.
Jest to równoznaczne z równomiernym próbkowaniem z przecięcia punktów wewnątrz n
sześcianu -wymiarowej jednostki i n-1
-wymiarowej hiperpłaszczyzny, która przechodzi (s/n, s/n, …, s/n)
i jest prostopadła do wektora (1, 1, …, 1)
(trzy przykłady patrz czerwony obszar na rycinie 1).
Rysunek 1: Płaszczyzna prawidłowych wyników przy n = 3 i suma 0,75, 1,75 i 2,75
Przykłady
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]
Zasady
- Twój program powinien zakończyć się na sekundę na twoim komputerze co najmniej za pomocą
n≤10
i prawidłowych s. - Jeśli chcesz, twój program może być wyłączny na górnym końcu, tj.
s<n
I liczbach wyjściowych z półotwartego przedziału [0,1) (przełamując drugi przykład) - Jeśli twój język nie obsługuje liczb zmiennoprzecinkowych, możesz sfałszować wynik co najmniej dziesięcioma cyframi dziesiętnymi po przecinku.
- Standardowe luki są niedozwolone i dozwolone są standardowe metody wejścia / wyjścia.
- To jest golf golfowy , więc wygrywa najkrótszy wpis, mierzony w bajtach.
This is equal to uniformly sampling from the intersection
- widzę, że program wybiera losowo tylko z rogów tego skrzyżowania. Czy to byłoby ważne?s==0 or s==3
. Dla wszystkich innych wartościs
płaszczyzna ma niezerowe pole i musisz jednorodnie losowo wybrać punkt na tej płaszczyźnie.s=2.99999999999, n=3
? Czy możemy generować losowe liczby rzeczywiste w wielokrotnościach, powiedzmy1e-9
,?Odpowiedzi:
Wolfram Language (Mathematica) ,
9290 bajtówWypróbuj online!
Kod bez golfa:
Oto rozwiązanie, które działa w 55 bajtach, ale na razie (Mathematica wersja 12) jest ograniczone,
n=1,2,3
ponieważRandomPoint
odmawia rysowania punktów z hiperpłaszczyzn o wyższych wymiarach (w wersji 11.3 TIO również się nie udajen=1
). Może jednakn
w przyszłości działać lepiej :Wypróbuj online!
Kod bez golfa:
źródło
JavaScript (Node.js) ,
122115 bajtówWypróbuj online!
źródło
Python 2 ,
144128119 bajtówWypróbuj online!
źródło
g(4, 2.0)
1000 razy, aby uzyskać 4000 punktów, a wyniki wyglądają tak, jak się wydaje, dość jednolite.Java 8,
194188196237236 bajtów+49 bajtów (188 → 196 i 196 → 237), aby naprawić szybkość przypadków testowych zbliżonych do 1, a także ogólnie naprawić algorytm.
Wypróbuj online
Wyjaśnienie:
Wykorzystuje podejście z tej odpowiedzi StackoverFlow , w pętli, dopóki jeden z elementów jest nadal większy niż 1.
Ponadto, jeśli
2*s>n
,s
zostanie zmieniony nan-s
, a ustawiona jest flaga wskazująca, że powinniśmy użyć1-diff
zamiastdiff
w tablicy wyników (dzięki za wskazówkę @soktinpk i @ l4m2 ).źródło
test(10, 9.99);
10, 9.0
zaraz po tym, jak edytowałem, aby naprawićn=10, s=9.999999999999
przypadek testowy. Nie jestem pewien, czy jest poprawka w Javie, wciąż zachowując jej równomierną losowość. Będę musiał się nad tym zastanowić. Na razie dokonam edycji, aby określić limit czasu.n-s<1
możesz zadzwonićf(n,n-s)
i przerzucić każdy numer1/2
(tj. Zastąpićx
go1-x
), tak jak zrobił to L4m2. To może rozwiązać problem dla liczb, któres
są bliskon
.s+s>n
zamiastn-s<1
, ale kiedy spojrzałem na inne odpowiedzi JavaScript, rzeczywiście miało to sens. Wszystko jest teraz naprawione, w tym kolejny błąd, który był nadal obecny. Bajty trochę wzrosły, ale teraz każdy działa. Będzie działać odliczanie bajtów stąd. :)JavaScript (Node.js) , 153 bajty
Wypróbuj online!
źródło
C ++ 11,
284267 bajtów-17 bajtów dzięki
losowej bibliotece Zacharý Uses C ++, wyjście na standardowe wyjście
Aby zadzwonić, musisz po prostu to zrobić:
Gdzie parametrem szablonu (tutaj 2) jest N, a rzeczywistym parametrem (tutaj 0,0) jest S
źródło
<z>
iu
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]<<' ';}
. Nowa linia nie musi być separatorem między przedmiotamid
całkowicie, zmieniającd=s/N
nas/=N
Sugeruj przerobienie drugiej pętlifor(z c;i<N;a[++i%N]-=c)a[i]+=c=u(e);
zamiastfor(;i<N;){z c=u(e);a[i]+=c;a[++i]-=c;}
(zwróć uwagę na dodane%N
, aby program poprawnie obliczył pierwszą liczbę)Czysty ,
221201 bajtówCzyste, golfowe lub losowe liczby. Wybierz dwa.
Wypróbuj online!
Literał funkcji częściowej
:: (Int Real -> [Real])
. Będzie generować nowe wyniki tylko raz na sekundę.Dokładność do co najmniej 10 miejsc po przecinku.
źródło
R , 99 bajtów (z
gtools
pakietem)Wypróbuj online!
Jeślis = 1 , to proste: odpowiada próbkowaniu z D i r i c h l e t ( 1 , 1 , … , 1 ) dystrybucja (która jest jednolita w stosunku do simpleksu). W ogólnym przypadkus ≠ 1 , używamy próbkowania odrzucenia: próbka z rozkładu Dirichleta, dopóki wszystkie wpisy nie będą < 1 / s , a następnie pomnóż przez s .
Sposób na wykonanie kopii lustrzanej kiedys > n / 2 (co myślę, że L4m2 jako pierwszy wymyślił ) jest niezbędne. Zanim to zobaczyłem, liczba iteracji w próbniku odrzucenia eksplodowała w ostatnim przypadku testowym, więc spędziłem dużo czasu próbując efektywnie próbkować z dobrze wybranych skróconych dystrybucji Beta, ale w końcu nie jest to konieczne.
źródło
C,
132127125118110107 bajtów-2 bajty dzięki @ceilingcat
Wypróbuj online!
źródło
[0,1]
, a ich łączny rozkład nie jest jednolity.n=4
wartościs=3.23
oraz wartościs=0.89
wyjściowych poza zakresem. Co więcej, dystrybucjaX-s/n
powinna zależećs
, ale tak nie jest.Haskell ,
122217208 bajtówWypróbuj online!
Czasami odpowiedzi są nieco nieaktualne z powodu, jak sądzę, błędu zmiennoprzecinkowego. Jeśli to problem, mogę to naprawić kosztem 1 bajtu. Nie jestem też pewien, czy jest to jednolite (całkiem pewne, że jest w porządku, ale nie jestem aż tak dobry w tego typu sprawach), więc opiszę mój algorytm.
Podstawową ideą jest wygenerowanie liczby,
x
a następnie odjęcie jejs
i powtarzanie do momentu, aż będziemy mielin
elementy, a następnie przetasujemy je. Generujęx
z górną granicą 1 lubs
(w zależności od tego, która wartość jest mniejsza) i dolną granicąs-n+1
lub 0 (w zależności od tego, która wartość jest większa). Ta dolna granica istnieje, więc przy następnej iteracjis
nadal będzie mniejsza lub równan
(wyprowadzenie:s-x<=n-1
->s<=n-1+x
->s-(n-1)<=x
->s-n+1<=x
).EDYCJA: Dzięki @ michi7x7 za wskazanie wady w mojej jednolitości. Myślę, że naprawiłem to przez tasowanie, ale daj mi znać, jeśli jest inny problem
EDYCJA 2: Poprawiona liczba bajtów plus ustalone ograniczenie typu
źródło
Haskell , 188 bajtów
Nie golfowany:
Wypróbuj online!
źródło