Ten program generuje 6 liczb losowych od 0 do 45, a liczby nie mogą się powtarzać. Czy można ulepszyć ten kod?
$numbers = []; $i = 1; while($i <= 6) { $number = mt_rand(0, 45); if(!in_array($number, $numbers)) { array_push($numbers, $number); $i++; } } sort($numbers); echo implode(" - ", $numbers);
Odpowiedź
Twój algorytm działa, ale niekoniecznie jest bardzo wydajna i będzie się zderzać częściej, i częściej, jeśli liczba liczb wzrośnie.
Ogólnie rzecz biorąc, lepiej jest zacząć od unikalnego zestawu liczb i wyodrębnić losowy wybór tych liczb, zamiast wybierania liczb losowych i testowania ich unikalności.
PHP sprawia, że jest to stosunkowo fajne, ponieważ ma wbudowaną funkcję losową (to zasadniczo robi tasowanie Fisher-Yatesa przy użyciu tego samego systemu losowego co Ty).
A więc pobierz tablicę unikalnych wartości, potasuj ją, wybierz ją i posortuj wynik:
$count = 6; $highball = 45; $numbers = range(0, $highball); shuffle($numbers); $drawn = array_slice($numbers, - $count); sort($drawn);
Uwaga, użycie nazwanych zmiennych zamiast stałych powoduje jaśniej widać, co robisz.
Zobacz ten działający w ideone: https://ideone.com/1Hh0y8
Komentarze
- Wygenerowanie 6 różnych liczb z 45 prawdopodobnie nie będzie wymagało więcej liczb losowych niż tasowanie 45-elementowej tablicy, nawet w przypadku kolizji. I wątpię, żeby 6 i 45 zmieniły się znacznie, jak na typową loterię.
- @ 200_success – zgodził się, i chociaż moje pierwsze zdanie wspomina o wydajności, czyli o algorytmie, tak naprawdę chodzi o schludność, i funkcja kodu. 2 poziomy zagnieżdżenia są również usuwane wraz z powyższym i wyłączając deklaracje liczb magicznych, ' to tylko 4 linie kodu.
Odpowiedź
Zmienna $i
może zostać wyeliminowana, jeśli count($numbers)
, co wymagałoby zmiany operatora z <=
na <
.
while
można przepisać jako pętlę for
– np.
for ($numbers = []; count($numbers) < 6; /* intentionally empty */ )