PHP – losowanie liczb bez powtórzeń

Data dodania: jakiś czas temu
reklama

php-generator-liczb

Od czasu do czasu na forach internetowych widzę pytania dotyczące losowania liczb bez powtórzeń. Zamiast udzielać porad indywidualnie postanowiłem napisać ten krótki poradnik, który mam nadzieję pomoże w łatwym zrozumienia całego mechanizmu.

Jak zwykle jak to ja, tego typu poradniki staram się pisać kodem „łopatologicznym”, który mam nadzieje, jest łatwy do zrozumienia przez początkujących. Nie traćmy zatem czasu i bierzmy się do roboty.

Dlaczego rand() to zły pomnysł

Załóżmy, że chcemy wylosować sobie ze zbioru 50 liczb 4 takie, które na pewno będą unikalne. Na początku przychodzi Wam pewnie na myśl prosta funkcja rand:

<?php
$liczba1 = rand(1,50);
$liczba2 = rand(1,50);
$liczba3 = rand(1,50);
$liczba4 = rand(1,50);

Wydaje się, że zadziała? A no może zadziałać, ale nie musi. Każda z tych zmiennych może otrzymać inną liczbę, ale może też otrzymać taką samą. Z każdym razem funkcja rand() jest wywoływana od początku i wybiera liczby z zakresu od 1 do 50. Nie jest to poprawne rozwiązanie tego problemu.

Piszemy własne funkcje

W ramach tego ćwiczenia stworzymy sobie 2 funkcje. Jedna będzie generować nam zbiór liczb, a druga losować z niego liczby bez powtórzeń. Na początek napiszmy sobie funkcję, która stworzy nam tablicę wypełnioną danymi, w tym przypadku będą to liczby od 1 do 50:

<?php

function generuj_zbior($ilosc){

	$ile=0; //deklarujemy na początku zero
	$zbior_liczb=array(); //deklarujemy pustą tablice
	
	//teraz pętla, która szybko wypełni nam tablicę danymi
	while($ile<$ilosc){
		$ile++;
		$zbior_liczb[]=$ile;
	}
	return $zbior_liczb; //zwraca nam nasz zbiór
}

Ok, sprawdźmy czy działa, wywołajmy ją:

$zbior = generuj_zbior(50);
echo '<pre>';
print_r($zbior);
echo '</pre>';

Powinniście osiągnąć taki efekt:

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    [4] => 5
    [5] => 6
    [6] => 7
    [7] => 8
    [8] => 9
    [9] => 10
    [10] => 11
    [11] => 12
    [12] => 13
    [13] => 14
    [14] => 15
    [15] => 16
    [16] => 17
    [17] => 18
    [18] => 19
    [19] => 20
    [20] => 21
    [21] => 22
    [22] => 23
    [23] => 24
    [24] => 25
    [25] => 26
    [26] => 27
    [27] => 28
    [28] => 29
    [29] => 30
    [30] => 31
    [31] => 32
    [32] => 33
    [33] => 34
    [34] => 35
    [35] => 36
    [36] => 37
    [37] => 38
    [38] => 39
    [39] => 40
    [40] => 41
    [41] => 42
    [42] => 43
    [43] => 44
    [44] => 45
    [45] => 46
    [46] => 47
    [47] => 48
    [48] => 49
    [49] => 50
)

Pamiętajcie, że indeksy tablicy liczone są od zera. Dlatego finalne ostatni indeks ma nr 49 o wartości 50.

Ok, wiemy już, że nasza funkcja generująca zbiór danych działa. Teraz napiszemy funkcję, która z tych 50 liczb wylosuje nam te 4 unikalne:

function losuj_unikalne($zbior,$ile_wylosowac){
	
	$wylosowane_liczby=array(); //jeszcze nic nie wylosowano, deklarujemy pustą tablice
	
	//pętla załatwi sprawę z ilością losowanych liczb
	for($i=0;$i<$ile_wylosowac;$i++){
		$wylosowany_index = array_rand($zbior,1); //losujemy jakiś element tablicy z całego zbioru
		$wylosowane_liczby[]=$zbior[$wylosowany_index]; //przypisuje wylosowany element tablicy do nowej tablicy
		unset($zbior[$wylosowany_index]); //po wylosowaniu usuwamy ten element z tablicy by nie dopuścić do jego ponownego wylosowania
	}
	return $wylosowane_liczby; //zwraca unikalne wylosowane liczby
}

I to w zasadzie koniec. Teraz sprawdźmy naszą „losowarkę” na praktycznych danych. Poniżej całość kodu:

<?php
//autor: Marcin Romanowicz

function generuj_zbior($ilosc){

	$ile=0; //deklarujemy na początku zero
	$zbior_liczb=array(); //deklarujemy pustą tablice
	
	//teraz pętla, która szybko wypełni nam tablicę danymi, w typ przypadku danymi
	while($ile<$ilosc){
		$ile++;
		$zbior_liczb[]=$ile;
	}
	return $zbior_liczb; //zwraca nam nasz zbiór
}

function losuj_unikalne($zbior,$ile_wylosowac){
	
	$wylosowane_liczby=array(); //jeszcze nic nie wylosowano, deklarujemy pustą tablice
	
	//pętla załatwi sprawę z ilością losowanych liczb
	for($i=0;$i<$ile_wylosowac;$i++){
		$wylosowany_index = array_rand($zbior,1); //losujemy jakiś element tablicy z całego zbioru
		$wylosowane_liczby[]=$zbior[$wylosowany_index]; //przypisuje wylosowany element tablicy do nowej tablicy
		unset($zbior[$wylosowany_index]); //po wylosowaniu usuwamy ten element z tablicy by nie dopuścić do jego ponownego wylosowania
	}
	return $wylosowane_liczby; //zwraca unikalne wylosowane liczby
}


//no to generujemy
$zbior = generuj_zbior(50); //tworzy nam 50 elementów z których bęziemy losować
$losowanie = losuj_unikalne($zbior,4); //losuje nam 4 unikalne elementy

//wyświetlamy
echo '<pre>';
	print_r($losowanie);
echo '</pre>';

?>

Ja osiągnąłem taki efekt. Na 99,9% u Was liczby będą inne niż u mnie. Grunt, by były ich dokładnie 4:

Array
(
    [0] => 30
    [1] => 31
    [2] => 43
    [3] => 16
)

Proste? Mam nadzieję. Podsumowując, by wylosować sobie dowolne liczby ze zbioru liczb wystarczy zmienić liczby podane w:

$zbior = generuj_zbior(50);
$losowanie = losuj_unikalne($zbior,4);

Udanego kodowania!


PS. jeśli masz konto na Facebooku, polub fanpage Konkretnego. Dzięki!




Tagi: , , , ,

Bądź miły! Uwielbiam wchodzić z Wami w dyskusję, proszę jednak, by krytyka była konstruktywna. Komentarz, który ma na celu obrażać mnie lub moich Czytelników może zostać usunięty. Tutaj każdy ma czuć się dobrze :)

Jestem także tutaj


YouTube - ostatni film z Filek.TV

YouTube - ostatni film z Konkretny.pl

Discord

Chcesz ze mną pograć?
Wbijaj na mój Discord

Partnerzy











O blogu

Konkretny.pl to blog technologiczny, którego tematyka porusza kilka specjalistycznych dziedzin. Jednymi z najważniejszych są zagadnienia dotyczące technologii i Internetu, ale nie brakuje tutaj również typowych tekstów dotyczących finansów, marketingu, programowania, a nawet gier komputerowych. Życzę przyjemnej lektury :)


Social Media

 



© 2011-2018 Marcin Romanowicz. Wszelkie prawa zastrzeżone.

Wszystkie posty piszę w dobrej wierze. Nie odpowiadam jednak za wszelkie szkody, treść komentarzy oraz autentyczność informacji na stronie. Informuję, że publikowane pliki zostały sprawdzone programem antywirusowym w aktualnej wersji. Nie biorę jednak odpowiedzialności, jeśli coś się stanie.

| O mnie |   | Polityka Prywatności |   | Kontakt |