Skip to content

Instantly share code, notes, and snippets.

@JesseKPhillips
Created October 23, 2011 19:12
Show Gist options
  • Save JesseKPhillips/1307739 to your computer and use it in GitHub Desktop.
Save JesseKPhillips/1307739 to your computer and use it in GitHub Desktop.
Implimentation of randomCover that uses Random as a reference
import std.random;
import std.range;
auto randomCover2(Range,Rnd)(Range arr, ref Rnd random) {
return RandomCover2!(Range,Rnd)(arr,&random);
}
struct RandomCover2(Range, Random)
{
private Range _input;
private Random* _rnd;
private bool[] _chosen;
private uint _current;
private uint _alreadyChosen;
this(Range input, Random* rnd)
{
_input = input;
_rnd = rnd;
_chosen.length = _input.length;
popFront;
}
static if (hasLength!Range)
@property size_t length()
{
return (1 + _input.length) - _alreadyChosen;
}
@property auto ref front()
{
return _input[_current];
}
void popFront()
{
if (_alreadyChosen >= _input.length)
{
// No more elements
++_alreadyChosen; // means we're done
return;
}
size_t k = _input.length - _alreadyChosen;
uint i;
foreach (e; _input)
{
if (_chosen[i]) { ++i; continue; }
// Roll a dice with k faces
auto chooseMe = uniform(0, k, _rnd) == 0;
assert(k > 1 || chooseMe);
if (chooseMe)
{
_chosen[i] = true;
_current = i;
++_alreadyChosen;
return;
}
--k;
++i;
}
assert(false);
}
@property bool empty() { return _alreadyChosen > _input.length; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment