Zaimplementuj funkcję rand5() używając rand7() Daily Coding Problem: Problem #71 [Easy]

Wpis z 01.05.2023, autor Andrzej Mazur  ·  Code in sandbox   ·  Subskrybuj LekcjePHP na Youtube


Używając funkcji rand7(), która zwraca liczbę całkowitą od 1 do 7, zaimplementuj funkcję rand5(), która zwraca liczbę całkowitą od 1 do 5.


Treść zadania:

Używając funkcji rand7(), która zwraca liczbę całkowitą od 1 do 7 (włącznie) z jednakowym prawdopodobieństwem, zaimplementuj funkcję, rand5(), która zwraca liczbę całkowitą od 1 do 5 (włącznie).

(orginał ang.) Using a function rand7() that returns an integer from 1 to 7 (inclusive) with uniform probability, implement a function rand5() that returns an integer from 1 to 5 (inclusive).

Wstępne przemyślenia

Oczywistym nasuwa się trywialne rozwiązanie aby zrobić modulo z funkcji rand7():

$result = ((rand7() - 1) % 5) + 1

Ale to podchwytliwe zadanie i nieprawidłowa implentacja, bo nie uzyskamy jednakowego prawdopodobieństwa.

Latwo zauważać że liczby 1 i 2 będą pojawiać się 2 razy częściej, bo także dla wartości 6 i 7 zwracanych przez rand7().

Rozwiązanie

Pewnym pomysłem jest nałożenie funkcji liniowej na wynik losowania:

$result round(($num 1) * (4.0 6.0)) + 1;

Natomiast i to nie jest dobrym rozwiązaniem. W wyniku zaokrągleń nadliczne będą liczby 2 i 4.

Nie pomoże tez zastąpienie round() przez floor() lub ceil().

Wciąż pewne wartości będą dwukrotnie bardziej liczne niż inne. Dla ceil() będą to 3 i 5 a dla floor() liczby 1 i 3.

Najprostsze rozwiązanie

Najprostszym i najskuteczniejszym rozwiązaniem jest po prostu odrzucenie wartości z poza oczekiwanego zakresu, i nakazanie funkcji rand7 ponowne wylosowanie liczb.wartości

Prostą implementację z wykorzystaniem żadko stosowanej pętli do-while znajdziecie poniżej:

Kod źródłowy

function rand5() {
    do {
        
$num rand7();
    } while (
$num 5);
    return 
$num;
}

Praktyczny kod do testów

Jeżeli sam chcesz, sprawdzic powyższe informacje, poniżej przedstawiam cały kod do testu, także do przeprowadzenia jakości wyników, czyli rozkładu ilościowego wartości zwracanych przez testowana funkcję rand5()

<?php
// Pomocnicza funkcja rand7
function rand7() {
  return 
rand(17);
}

// Poszukiwana funkcja rand5
function rand5() {
    do {
        
$num rand7();
    } while (
$num 5);
    return 
$num;
}

// Testy prawdopodobieństwa
$stat = [];
for(
$i 1$i 110000$i++) {
    
$rr rand5();
    @
$stat[$rr]++;
}
ksort($stat);
print_r($stat);

Materiał przygotował dla Was:
Andrzej EZNAWCA Mazur
Zapraszam na moje strony:
LekcjePHP.pl
Eznawca.pl