Zainspirowany przez Random ze związanymi rękami :
Cel
Celem tego wyzwania jest napisanie programu, który generuje pseudolosowy strumień bitów, który jest ciągiem 1 i 0, które wydają się być całkowicie losowe, ale w rzeczywistości są generowane w sposób deterministyczny. Twój program powinien wypisać ciąg 1 i 0 (z opcjonalnym białym znakiem) i powinien spełnić następujące wymagania:
- Biorąc pod uwagę nieograniczony czas i pamięć, twój program musi nadal wyświetlać ciąg 1 i 0 na zawsze
- Twój program musi wygenerować ponad 1000 losowych bitów w ciągu około jednej minuty na rozsądnej maszynie. Jeśli to wymaganie jest niemożliwe, zmniejszę je.
- Ciąg bitów może się powtarzać, ale długość powtarzającej się sekcji musi być większa niż 1000 bitów.
- Ciąg bitów musi przejść jak najwięcej testów losowości (opisanych poniżej), jak to możliwe.
- Program nie może pobierać żadnych danych wejściowych z zewnętrznych źródeł ani używać wbudowanej funkcji podobnej do rand ().
- Ze względu na powyższe wymagania program musi wyświetlać ten sam ciąg bitów za każdym razem, gdy jest uruchamiany.
Test losowości nr 1
Ciąg bitów pseudolosowych nie może zawierać żadnego oczywistego wzorca po oględzinach.
Test losowości nr 2 (może ulec zmianie na podstawie komentarzy)
Ciąg bitów musi zawierać równy rozkład 1 i 0. Aby to przetestować (i inne rzeczy), strumień bitów jest podzielony na segmenty o długości 3 bitów, takie jak 101|111|001
.
Spośród wszystkich tych segmentów 1/8 z nich powinna mieć trzy jedynki i żadnych zer, 3/8 z nich powinno mieć dwa jedynki, a jeden 0, 3/8 powinno mieć jeden 1 i dwa zera, a 1/8 z nich nie powinny mieć 1 i 3 0.
Test losowości # 3
„Przebieg” jest definiowany jako kolejna seria bitów, z których wszystkie mają tę samą wartość. Ciąg 1001001110
ma trzy przebiegi o rozmiarze 1 ( 1..1.....0
), dwa przebiegi o rozmiarze 2 ( .00.00....
) i jeden przebieg o rozmiarze 3 ( ......111.
). Zauważ, że przebiegi nie nakładają się.
Z ciągu 1000 losowych bitów powinno być około 250 serii o rozmiarze 1, 125 serii o rozmiarze 2, 62 serii o rozmiarze 3 itd. Ogólnie rzecz biorąc, dla serii o rozmiarze R powinno być około serii 1000/(2**(R+1))
o tej wielkości.
Test losowości # 4
Pierwsze 840 bitów podzielono na dwie połowy po 420 bitów. Każdy bit w pierwszej połowie jest porównywany z odpowiednim bitem w drugiej połowie. Dwa bity powinny pasować przez około pięćdziesiąt procent czasu.
Oto kod źródłowy programu Perl, który wykonuje testy od 2 do 4. Obecnie wymaga, aby ciąg bitów nie zawierał żadnych białych znaków.
Czas Kryterium Zwycięskiego Celu!
Zwycięzcą jest program, który spełnia wszystkie 6 wymagań i wszystkie testy losowości w stopniu, który jest nie do odróżnienia od losowości. Jeśli wiele programów to osiągnie, wygra ten, który zajmuje najwięcej czasu. Jeśli wiele programów to osiągnie, być może będę musiał znaleźć więcej testów losowości, aby działać jak remis.
źródło
Odpowiedzi:
C, 61
Tak, wiem, że to nie jest golf golfowy. Jest to oczywiście raczej rozwiązanie anty -... ale z pewnością spełnia twoje kryteria.
Długość okresu wynosi 2²⁹.
źródło
Mathematica
7853 znakiCyfry binarnej reprezentacji Pi wydają się zachowywać tak, jakby były wytwarzane chaotycznie, chociaż nie jest to udowodnione.
Poniższa prosta procedura deterministycznie zwraca jako ciąg binarne cyfry pi, odpowiadające
d
cyfrom dziesiętnym:Stosowanie
Jeśli poprosimy o odpowiednik 301 cyfr dziesiętnych Pi, otrzymamy 1000 cyfr binarnych.
Ponieważ Pi jest liczbą nieracjonalną, nie ma kropki. Istnieją jednak praktyczne ograniczenia związane z uruchomionym sprzętem.
Test 1 Wygląda mi dobrze.
Test 2
Bardziej szczegółowa kontrola:
Test 3: Działa
Prowadziłem wiele spraw, aby systematycznie sprawdzać rozkład przebiegów. W około 3 milionach cyfr binarnych było 830 tys. Serii 1, 416 tys. Serii 2, 208 tys. Serii 3, 104 tys. Serii 4 itd.
Test 4: Dopasowywanie pierwszej i drugiej połowy danych
Dopasowaniami są 212 przypadków 0 i 2; niedopasowania to 208 przypadków, w których suma odpowiednich cyfr wynosi 1.
wyczucie czasu
Obliczenie 3321928 cyfr binarnych zajmuje mniej niż dwie sekundy (co odpowiada 10 ^ 6 cyfr dziesiętnych).
źródło
e
zamiastpi
zapisać jeden bajt?e
rozprowadzany chaotycznie?Python, 90
g
jest wartością początkową. Losowe pobieranie próbek wykazuje niezwykle normalny rozkład. Powtarzane losowe pobieranie próbek średnich próbek dało średnią0.506
i standardowe odchylenie.0473
(wielkość próbki 1000). Niestety losowość jest bardzo wrażliwa na początkowe nasiona. Ziarno w powyższym kodzie dało mi najlepszą losowość: strAKTUALIZACJA
Zobaczmy, jak ten kod wytrzymuje testy OP:
Test nr 1
Ten jest nieco subiektywny ... ale dla mnie wygląda dość nieregularnie.
Test nr 2
Test nr 3
Działa według rozmiaru:
Test nr 4
źródło
Haskell
7458Dzięki shiona za uproszczenie. Wyniki:
Jest to także straszny pseudolosowy generator (podobny do tego, z którego korzystał von-Neuman). Dla tych, którzy nie byli świadomi
concatMap == (=<<) == flip . (>>=)
(dla list)źródło
\x->if odd x then"1"else"0"
zshow.(`mod`2)
.Pytanie jest zasadniczo równoważne z „implementacją szyfru strumieniowego”. Wdrażam więc RC4, ponieważ jest to stosunkowo proste.
Nie używam żadnego klucza i upuszczam pierwsze 100000 bitów, ponieważ początek RC4 jest nieco stronniczy, zwłaszcza, że pominąłem harmonogram kluczy. Ale spodziewam się, że przejdzie test nawet bez tego (oszczędzając 20 znaków kodu).
Zwykle wypisuje się pełny bajt na cykl, ale konwersja na binarną jest raczej brzydka w C #, więc po prostu odrzucam wszystko oprócz najmniej znaczącego bitu.
Lub bez spacji:
C #, 156 znaków, działa w trybie instrukcji LinqPada. Aby uzyskać pełny program w języku C #, dodaj zwykły szablon.
Możemy również użyć wbudowanych prymitywów kryptograficznych (rozwiązanie Cheater):
(C #, 99 znaków, działa w trybie instrukcji LinqPada. W przypadku normalnego kompilatora C # musisz dodać trochę kafelka)
Wyjście funkcji kryptograficznych funkcji skrótu zostało zaprojektowane tak, aby było nierozróżnialne od losowych danych, więc spodziewam się, że przejdzie wszystkie testy losowości (trudniejsze, ...) rzucisz na to, ale jestem zbyt leniwy, aby to przetestować.
źródło
C, 52 znaki
To jest 10-bitowy LFSR, wyniki testu:
źródło
a
powinien zaczynać się od 1 (zakładając, że jest wywoływany bez argumentów). Możesz też trzymać sięa=
środka, coś w rodzajua=a/2^-!putchar(49-a%2)%576
(trochę wolności z algorytmem)a
, zmieniłem ją z powodu „The program must not take any input from any external sources
”Sage / Python
Ten program drukuje skrajnie prawe cyfry binarne, które są wspólne dla każdej wystarczająco wysokiej wieży wykładniczej w postaci 3 3 3 3 . . . Dla wszystkich, jakie kiedykolwiek można było wygenerować, są to najbardziej binarne cyfry liczby Grahama . Sekwencja cyfr jest nieskończona i nie jest okresowa.
W przypadku 1000 cyfr zajęło to mniej niż 2 sekundy; czas będzie jednak zwiększał się znacznie szybciej niż liniowo w liczbie cyfr.
Te wyniki badań z użyciem programu PO za to
(Zobacz Czy skrajnie prawe cyfry G są losowe ?, aby uzyskać więcej niż 32000 cyfr i dodatkowe testy statystyczne.)
źródło
Java,
371317Oparty na 128-bitowym LFSR ( dotknięcia bitów pochodzą z noty 52 aplikacji xilinx )
EDYCJA: Nie byłem zadowolony z używania BigInteger, więc ta wersja nie. Zapisałem niektóre postacie. Wynik może być nieco mniej przypadkowy, ponieważ nie mogłem wymyślić dobrej metody „seedowania”.
Nowy kod: Argumenty: BITS_TO_PRINT
Stara wersja: Argumenty: SEED, BITS_TO_PRINT
Nowa wersja: Przykładowy wynik, bity = 100:
źródło
JavaScript - 1ms do 2ms dla 1000 pseudolosowych bitów (139ms do 153ms dla 100000 bitów)
To rozwiązanie wykorzystuje fakt, że pierwiastki kwadratowe są nieracjonalne, a zatem prawie losowe. Zasadniczo, rozpoczyna się pierwiastek kwadratowy z 2, konwertuje go na binarny, wyrzuca wiodącą część, która pasowała do poprzedniego pierwiastka, dołącza ją do losowego ciągu, powtarza z kolejną wyższą liczbą (lub wraca do 2, jeśli liczba się powtarza i miał co najmniej 30 bitów) i zwraca losowy ciąg, gdy jest wystarczająco długi.
Nie przeprowadziłem jeszcze testów, ale wyobrażam sobie, że poradzi sobie z nimi dobrze. Oto skrzypce, dzięki czemu można zobaczyć w akcji. W moich czasach właśnie uruchomiłem program kilka razy i wziąłem najszybsze i najwolniejsze wartości jako zakresy.
źródło
Pyton
Powinien mieć okres około 2 ^ 512.
źródło
perl, 44 bajty
Wiem, że to nie jest golf golfowy, ale zawsze byłem fanem korzystania z bitów niskiego rzędu prostej funkcji kwadratowej, np .:
Okres jest dłuższy niż 3 miliardy, ale zabrakło mi miejsca na dysku, aby obliczyć więcej.
źródło
$x=1/7;print substr($x*=4-4*$x,9,1)%2while 1