std::sample în C++

Alege aleatoriu n elemente distincte dintr-un interval și le copiază la destinație.

Sintaxă
OutputIt sample(PopulationIt first, PopulationIt last, OutputIt out, Distance n, URBG&& generator);

Ce face std::sample

std::sample extrage n elemente fără repetare: fiecare element din sursă apare cel mult o dată în rezultat. Dacă sursa are mai puțin de n elemente, le copiază pe toate.

Când sursa are iteratori de tip forward (de exemplu un vector), elementele alese păstrează ordinea din sursă. Ca la std::shuffle, rezultatul pentru un seed fix depinde de implementarea bibliotecii.

Parametri

Parametru Descriere
first, last Populația din care se alege.
out Destinația.
n Câte elemente se aleg.
generator Generatorul de numere aleatorii.

Ce returnează

Iterator după ultimul element copiat.

Exemple

Exemplul 1: Trei câștigători dintr-o tombolă

#include <algorithm>
#include <iterator>
#include <print>
#include <random>
#include <string>
#include <vector>

int main() {
    std::vector<std::string> participanti{"Ana", "Bogdan", "Cristina", "Dan", "Ioana", "Mihai", "Vlad"};
    std::vector<std::string> castigatori;

    std::mt19937 gen(std::random_device{}());
    std::sample(participanti.begin(), participanti.end(), std::back_inserter(castigatori), 3, gen);

    std::print("Câștigători:");
    for (const auto& c : castigatori) {
        std::print(" {}", c);
    }
    std::println("");
}

Rezultat posibil (diferă la fiecare rulare)

Câștigători: Bogdan Ioana Vlad

Exemplul 2: Eșantion reproductibil

Cu seed fix, rezultatul se repetă la fiecare rulare (pe aceeași bibliotecă standard). Ordinea din sursă este păstrată.

#include <algorithm>
#include <iterator>
#include <numeric>
#include <print>
#include <random>
#include <vector>

int main() {
    std::vector<int> bilete(50);
    std::iota(bilete.begin(), bilete.end(), 1);

    std::vector<int> extrase;
    std::mt19937 gen(7);
    std::ranges::sample(bilete, std::back_inserter(extrase), 6, gen);
    std::println("{}", extrase);
}

Rezultat

[2, 4, 17, 30, 43, 45]

Greșeli frecvente

  • Vrei extrageri cu repetare (de exemplu 5 aruncări de zar) și folosești sample. Pentru asta folosește o distribuție, precum std::uniform_int_distribution.

Comenzi înrudite

  • std::shuffle: Amestecă aleatoriu elementele unui interval folosind un generator de numere aleatorii.
  • std::mt19937: Generatorul Mersenne Twister: numere pseudo-aleatorii rapide și de calitate, reproductibile cu un seed fix.
  • std::uniform_int_distribution: Transformă numerele unui generator în întregi aleatorii dintr-un interval [a, b], toate cu aceeași probabilitate.