Skip to content

Instantly share code, notes, and snippets.

@resilience-me
Last active November 8, 2018 19:12
Show Gist options
  • Save resilience-me/d2b17f6ebdd641edad33f34f9e3166d2 to your computer and use it in GitHub Desktop.
Save resilience-me/d2b17f6ebdd641edad33f34f9e3166d2 to your computer and use it in GitHub Desktop.
// The shuffle algorithm is similar to Algorithm P (Shuffle) from Knuth, 1969, in turn similar to the Fisher–Yates shuffle
// from 1938. It gets the position of an object from shufflingIndex, using a random number generator, and then updates the
// index so that the same position cannot be given to another object, and does so by switching places between the object
// that was picked, and the first object in the list, exchange shufflingIndex[randomNumber] and shufflingIndex[counter].
struct ShuffleAlgorithm {
mapping(uint => uint) shufflingIndex;
uint counter;
}
ShuffleAlgorithm shuffleUtility[3];
mapping(address => uint) pseudonymID;
mapping(uint => address) pseudonymIndex;
mapping(address => uint) immigrantID;
mapping(uint => address) immigrantIndex;
function sortMe() atTime(State.interlude, State.pseudonymEvent) {
require(pseudonymID[msg.sender] == 0);
uint8 idx;
// Map even and uneven numbers in separate indices, each integer representing a pair with two people
// this lets people who opt-in "hitch-hike" on the shuffling of the entire population, so that optIn()
// can be invoked continuously
if(totalSorted % 2 == 1) {
shuffleUtility[0].counter++;
idx = 0;
}
else {
shuffleUtility[1].counter++;
idx = 1;
}
uint totalSorted = shuffleUtility[0].counter + shuffleUtility[1].counter;
pseudonymID[msg.sender] = totalSorted;
pseudonymIndex[totalSorted] = msg.sender;
entropy = generateRandomNumber(entropy);
uint pos = shuffleUtility[idx].counter;
uint randomNumber = 1 + (entropy % pos);
shuffleUtility[idx].shufflingIndex[pos] = randomNumber;
shuffleUtility[idx].shufflingIndex[randomNumber] = pos;
}
function getPair(address _nym) view atTime(State.pseudonymEvent, State.endOfPeriod) returns (uint) {
uint ID = pseudonymID[_nym];
uint8 idx;
uint nominator;
if(ID % 2 == 1) {
nominator += 1;
idx = 0;
}
else idx = 1;
uint pos = nominator / 2;
uint pairID = shuffleUtility[idx].shufflingIndex[pos];
return pairID;
}
function optIn() atTime(State.interlude, State.pseudonymEvent) {
uint totalPairs = shuffleUtility[1].counter;
shuffleUtility[2].counter++;
uint totalImmigrants = shuffleUtility[2].counter;
require(totalPairs >= 1);
require(totalPairs > (totalImmigrants - 1));
require(immigrantID[msg.sender] == 0);
require(borderToken.balanceOf[msg.sender] >= 1);
borderToken.balanceOf[msg.sender]--;
immigrantID[msg.sender] = totalImmigrants;
immigrantIndex[totalImmigrants] = msg.sender;
entropy = generateRandomNumber(entropy);
uint randomNumber = 1 + (entropy % (totalPairs - totalImmigrants));
uint randomPerson = totalImmigrants + randomNumber; // Mapped to evenNumbers, hitch-hikes on a registered person, and the shuffling on their end
// Prune the list with randomPerson, adding the person from the beginning to its position
if(shuffleUtility[2].shufflingIndex[randomPerson] == 0) shuffleUtility[2].shufflingIndex[randomPerson] = randomPerson;
if(shuffleUtility[2].shufflingIndex[totalImmigrants] == 0) shuffleUtility[2].shufflingIndex[totalImmigrants] = totalImmigrants;
shuffleUtility[2].shufflingIndex[randomPerson] = shuffleUtility[2].shufflingIndex[totalImmigrants];
// Assign the person to randomPerson
shuffleUtility[2].shufflingIndex[totalImmigrants] = shuffleUtility[2].shufflingIndex[randomPerson];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment