# RandomSequence

The `RandomSequence` component provides object-oriented random number sequences behind a common `SequenceInterface`. This is useful when you need to inject a random source as a dependency, swap implementations for testing, or produce reproducible sequences from a known seed.

## The Interface

Every sequence implements `SequenceInterface` with a single method:

```php
use Psl\IO;
use Psl\RandomSequence\SecureSequence;
use Psl\RandomSequence\SequenceInterface;

/** @var SequenceInterface $sequence */
$sequence = new SecureSequence();
$a = $sequence->next(); // next random int
$b = $sequence->next(); // another random int

IO\write_line('First: %d', $a);
IO\write_line('Second: %d', $b);
```

## Implementations

### MersenneTwisterSequence

A seedable Mersenne Twister (MT19937) PRNG. Given the same seed, it always produces the same sequence, making it ideal for reproducible simulations, procedural generation, and deterministic tests:

```php
use Psl\IO;
use Psl\RandomSequence\MersenneTwisterSequence;

$seq = new MersenneTwisterSequence(seed: 42);

$first = $seq->next(); // always the same for seed 42
$second = $seq->next(); // deterministic

IO\write_line('First (seed 42): %d', $first);
IO\write_line('Second (seed 42): %d', $second);
```

### MersenneTwisterPHPVariantSequence

A variant that matches PHP's internal `mt_rand` twist behavior. Use this when you need compatibility with sequences generated by PHP's built-in Mersenne Twister:

```php
use Psl\IO;
use Psl\RandomSequence\MersenneTwisterPHPVariantSequence;

$seq = new MersenneTwisterPHPVariantSequence(seed: 42);

$first = $seq->next();
$second = $seq->next();

IO\write_line('PHP variant first (seed 42): %d', $first);
IO\write_line('PHP variant second (seed 42): %d', $second);
```

### SecureSequence

A cryptographically secure sequence backed by `SecureRandom\int()`. Use this in production when security matters:

```php
use Psl\IO;
use Psl\RandomSequence\SecureSequence;

$seq = new SecureSequence();
$value = $seq->next(); // cryptographically secure random int

IO\write_line('Secure random: %d', $value);
```

## Dependency Injection

The shared interface makes it easy to swap implementations. Use `MersenneTwisterSequence` in tests for reproducibility and `SecureSequence` in production:

```php
use Psl\IO;
use Psl\Iter;
use Psl\RandomSequence\MersenneTwisterSequence;
use Psl\RandomSequence\SecureSequence;
use Psl\RandomSequence\SequenceInterface;

/**
 * Picks a random winner from the list of participants using the provided RNG.
 *
 * @param non-empty-list<non-empty-string> $participants
 *
 * @return non-empty-string The name of the winner.
 */
function pick_winner(array $participants, SequenceInterface $rng): string
{
    /** @var int<0, max> $index */
    $index = $rng->next() % Iter\count($participants);

    return $participants[$index];
}

// Deterministic for tests
$testRng = new MersenneTwisterSequence(seed: 42);
$winner = pick_winner(['Alice', 'Bob', 'Charlie'], $testRng);
IO\write_line('Test winner: %s', $winner);

// Secure for production
$prodRng = new SecureSequence();
$winner = pick_winner(['Alice', 'Bob', 'Charlie'], $prodRng);
IO\write_line('Production winner: %s', $winner);
```

See [src/Psl/RandomSequence/](https://github.com/php-standard-library/php-standard-library/tree/6.2.1/packages/random-sequence/src/Psl/RandomSequence/) for the full API.
