Created
October 23, 2011 19:12
-
-
Save JesseKPhillips/1307739 to your computer and use it in GitHub Desktop.
Implimentation of randomCover that uses Random as a reference
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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