Utwórz funkcję, która wygeneruje zestaw różnych liczb losowych losowanych z zakresu. Kolejność elementów w zestawie jest nieistotna (można je nawet posortować), ale musi być możliwe, aby zawartość zestawu była inna przy każdym wywołaniu funkcji.
Funkcja otrzyma 3 parametry w dowolnej kolejności:
- Liczba liczb w zestawie wyjściowym
- Dolny limit (włącznie)
- Górny limit (włącznie)
Załóżmy, że wszystkie liczby są liczbami całkowitymi z zakresu od 0 (włącznie) do 2 31 (wyłącznie). Dane wyjściowe można przekazać w dowolny sposób (zapis do konsoli, jako tablica itp.)
Osądzać
Kryteria obejmują 3 R.
- Czas działania - testowany na czterordzeniowym komputerze z systemem Windows 7 z dowolnym kompilatorem, który jest łatwo lub łatwo dostępny (w razie potrzeby podaj link)
- Wytrzymałość - czy funkcja obsługuje przypadki narożne, czy wpadnie w nieskończoną pętlę lub wygeneruje nieprawidłowe wyniki - wyjątek lub błąd dotyczący nieprawidłowego wejścia
- Losowość - powinna generować losowe wyniki, których nie da się łatwo przewidzieć przy losowym rozkładzie. Korzystanie z wbudowanego generatora liczb losowych jest w porządku. Ale nie powinno być żadnych oczywistych uprzedzeń ani oczywistych przewidywalnych wzorców. Musi być lepszy niż generator liczb losowych używany przez Dział Księgowości w Dilbert
Jeśli jest solidny i losowy, sprowadza się do czasu działania. Brak solidności lub losowości znacznie szkodzi jego sytuacji.
code-challenge
fastest-code
number
random
Jim McKeeth
źródło
źródło
Odpowiedzi:
Pyton
Prawdopodobnie właśnie wymyśliłem pewien dobrze znany algorytm, ale pomysł polega na (koncepcyjnym) wykonaniu częściowego tasowania Fisher-Yatesa zakresu,
lower..upper
aby uzyskaćn
prefiks długości równomiernie tasowanego zakresu.Oczywiście przechowywanie całego zakresu byłoby raczej drogie, więc przechowuję tylko lokalizacje, w których elementy zostały zamienione.
W ten sposób algorytm powinien działać dobrze zarówno w przypadku próbkowania liczb z wąskiego zakresu (np. 1000 liczb w zakresie 1..1000), jak również w przypadku próbkowania liczb z dużego zakresu .
Nie jestem pewien jakości losowości z wbudowanego generatora w Pythonie, ale stosunkowo łatwo jest zamienić dowolny generator, który może generować liczby całkowite jednolicie z pewnego zakresu.
źródło
python 2.7
Nie jestem pewien, na czym się opierasz, używając wbudowanych losowych metod, ale i tak już i tak. miły i krótki
edit: właśnie zauważyłem, że range () nie lubi tworzyć dużych list. powoduje błąd pamięci. zobaczę, czy jest jakiś inny sposób to zrobić ...
edit2: zakres był niewłaściwą funkcją, xrange działa. Maksymalna liczba całkowita jest w rzeczywistości
2**31-1
dla Pythonatest:
źródło
do
Zwraca tablicę zawierającą x unikatowych losowych liczb całkowitych od min do max. (dzwoniący musi zwolnić)
Działa, generując x losowych liczb całkowitych w zakresie, a następnie tasując je. Dodaj
seed(time)
gdzieś w dzwoniącym, jeśli nie chcesz uzyskać takich samych wyników przy każdym uruchomieniu.źródło
Rubin> = 1,8
źródło
R
źródło
Pytanie jest nieprawidłowe. Potrzebujesz jednolitego próbkowania, czy nie? W przypadku, gdy potrzebne jest jednolite próbkowanie, mam następujący kod w R, który ma średnią złożoność O ( s log s ), gdzie s jest rozmiarem próbki.
Oczywiście można przepisać go w C dla lepszej wydajności. Złożoność tego algorytmu omówiono w: Rouzankin, PS; Voytishek, AV W sprawie kosztów algorytmów losowego wyboru. Metody Monte Carlo. 5 (1999), no. 1, 39–54. http://dx.doi.org/10.1515/mcma.1999.5.1.39
Możesz przejrzeć ten dokument w poszukiwaniu innego algorytmu o tej samej średniej złożoności.
Ale jeśli nie potrzebujesz jednolitego próbkowania, wymagając tylko, aby wszystkie próbkowane liczby były różne, sytuacja zmienia się drastycznie. Nie jest trudno napisać algorytm o średniej złożoności O ( s ).
Zobacz także jednolite pobieranie próbek: P. Gupta, GP Bhattacharjee. (1984) Wydajny algorytm losowego próbkowania bez zamiany. International Journal of Computer Mathematics 16: 4, strony 201-209. DOI: 10.1080 / 00207168408803438
Teuhola, J. and Nevalainen, O. 1982. Dwa wydajne algorytmy losowego próbkowania bez zamiany. / IJCM /, 11 (2): 127–140. DOI: 10.1080 / 00207168208803304
W ostatnim artykule autorzy używają tabel skrótów i twierdzą, że ich algorytmy mają złożoność O ( s ). Jest jeszcze jeden algorytm szybkiej tabeli skrótów, który wkrótce zostanie zaimplementowany w pqR (dość szybki R): https://stat.ethz.ch/pipermail/r-devel/2017-October/075012.html
źródło
APL,
1822 bajtówDeklaruje anonimową funkcję, która przyjmuje dwa argumenty
⍺
i⍵
.⍺
to liczba liczb losowych, którą chcesz,⍵
to wektor zawierający dolną i górną granicę, w tej kolejności.a?b
wybieraa
losowe liczby od 0 -b
bez zamiany. Biorąc⍵[1]-⍵[0]
, otrzymujemy rozmiar zakresu. Następnie wybieramy⍺
liczby (patrz poniżej) z tego zakresu i dodajemy dolną granicę. W C to byłoby⍺
razy bez wymiany. Nawiasy nie są potrzebne, ponieważ APL działa od prawej do lewej.Zakładając, że poprawnie zrozumiałem warunki, nie spełnia to kryteriów „odporności”, ponieważ funkcja zawiedzie, jeśli otrzyma niewłaściwe argumenty (np. Przekazanie wektora zamiast skalara as⍺
).W przypadku, gdy
⍺
jest to wektor, a nie skalar,1↑⍺
bierze pierwszy element⍺
. W przypadku skalara jest to sam skalar. W przypadku wektora jest to pierwszy element. To powinno sprawić, że funkcja spełni kryteria „niezawodności”.Przykład:
źródło
{⍵+⍺?⎕-⍵}
powinno wystarczyć, gdy monit dotyczy górnej granicy, a prawy arg jest dolnej granicyScala
skompiluj i uruchom:
W drugim wierszu uruchomionych zostanie 200 testów z 15 wartościami od 0 do 100, ponieważ Scala tworzy szybki kod bajtowy, ale potrzebuje trochę czasu uruchamiania. Tak więc 200 zaczyna się od 15 wartości od 0 do 100 zużyłoby więcej czasu.
Próbka na jednordzeniowym 2 GHz:
Logika:
Używając wbudowanych losowych i rekurencyjnie wybierających liczb z zakresu (maks. Min), dodając min i sprawdzając, czy rozmiar zestawu jest oczekiwanym rozmiarem.
Krytyka:
źródło
Schemat
Nie jestem pewien, dlaczego potrzebujesz 3 parametrów, ani dlaczego muszę zakładać dowolny zakres ...
źródło
R
źródło
C ++
Ten kod jest najlepszy przy pobieraniu wielu próbek z zakresu.
źródło
max-min
jest znacznie większe niżn
. Ponadto sekwencja wyjściowa rośnie monotonicznie, więc masz bardzo niską jakość losowości, ale wciąż ponosisz koszty połączeńrand()
wielokrotnych za wynik. Losowe przetasowanie tablicy prawdopodobnie byłoby warte dodatkowego czasu działania.Q (19 znaków)
Następnie użyj f [x; y; z] jako [liczba liczb w zestawie wyjściowym; punkt początkowy; rozmiar zakresu]
np. f [5; 10; 10] wygeneruje 5 różnych liczb losowych od 10 do 19 włącznie.
Powyższe wyniki pokazują skuteczność przy 100 000 iteracjach po wybraniu 100 liczb losowych od 1 do 10 000.
źródło
R, 31 lub 40 bajtów (w zależności od znaczenia słowa „zakres”)
Jeśli wejście ma 3 liczby,
a[1], a[2], a[3]
a przez „zakres” rozumiesz „ciąg liczb całkowitych od [2] do [3]”, to masz to:Jeśli masz tablicę,
n
z której zamierzasz ponownie próbkować, ale pod ograniczeniem dolnej i górnej granicy, na przykład „ponownie próbkuj wartości danej tablicyn
z zakresua[1]...a[2]
”, użyj tego:Jestem dość zaskoczony, dlaczego poprzedni wynik nie został zagrany w golfa, biorąc pod uwagę wbudowaną próbkę z urządzeniami zastępczymi! Tworzymy wektor, który spełnia warunek zakresu, i ponownie próbkujemy go.
źródło
0:(2^31)
powodujeError: cannot allocate a vector of size 16.0 Gb
JavaScript (przy użyciu zewnętrznej biblioteki) (64 bajty / 104 bajty ??)
Link do lib: https://github.com/mvegh1/Enumerable/
Objaśnienie kodu: Wyrażenie lambda akceptuje min, max, liczenie jako argumenty. Utwórz kolekcję o rozmiarze n i przypisz każdy element do losowej liczby spełniającej kryteria min / maks. Konwertuj na natywną tablicę JS i zwróć ją. Uruchomiłem to również na wejściu o wielkości 5.000.000, a po zastosowaniu wyraźnej transformacji nadal pokazałem 5.000.000 elementów. Jeśli zostanie uzgodnione, że nie jest to wystarczająco bezpieczna gwarancja odrębności, zaktualizuję odpowiedź
Na obrazku poniżej umieściłem pewne statystyki ...
EDYCJA: Poniższy obraz pokazuje kod / wydajność, która gwarantuje, że każdy element będzie odrębny. Jest znacznie wolniejszy (6,65 sekundy dla 50 000 elementów) w porównaniu z powyższym oryginalnym kodem dla tych samych argumentów (0,012 sekundy)
źródło
K (oK) , 14 bajtów
Rozwiązanie:
Wypróbuj online!
Przykład:
Wyjaśnienie:
Przyjmuje 3 dane niejawne na specyfikację:
x
, liczba liczb w zestawie wyjściowym,y
, dolny limit (włącznie)z
, górny limit (włącznie)Uwagi:
Również poliglot
q/kdb+
z dodatkowym zestawem nawiasów:{y+((-)x)?1+z-y}
(16 bajtów).źródło
Axiom + jego biblioteka
Powyższa funkcja f () zwraca jako błąd pustą listę, w przypadku f (n, a, b) z a> b. W innych przypadkach niepoprawnego wprowadzania nie uruchamia się z jednym komunikatem o błędzie w oknie Axiom, ponieważ argument nie będzie odpowiedniego typu. Przykłady
źródło