Skip to content

Instantly share code, notes, and snippets.

@CodesInChaos
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CodesInChaos/9226bad330dd1b80db24 to your computer and use it in GitHub Desktop.
Save CodesInChaos/9226bad330dd1b80db24 to your computer and use it in GitHub Desktop.
void Main()
{
// setup deck
var interestingCounts = new []{4,4,4,4};
//var interestingCounts = new []{4,4,4,4,18}; // with lands
var interestingCards = interestingCounts.SelectMany((count, i)=>Enumerable.Repeat(i+1,count)).ToList();
var cards = interestingCards.Concat(Enumerable.Repeat(0, 60 - interestingCards.Count)).ToList();
//cards.Dump();
// simulation
int n = 100000000;
int success = 0;
for(int i = 0; i < n; i++)
{
var startingHand = RandomHelper.Random.Shuffle(cards).Take(7);
if(startingHand.Where(c => c != 0).Distinct().Count() == interestingCounts.Length)
success++;
}
(100.0 * success / n).Dump();
}
public static class RandomHelper
{
[ThreadStatic]
private static Random _random;
private static int _seed = Environment.TickCount;
// each thread gets its own instance, so Random not being threadsafe isn't a big issue. Just don't pass it to other threads.
public static Random Random
{
get
{
if (_random == null)
_random = new Random(Interlocked.Increment(ref _seed));
return _random;
}
}
public static IEnumerable<T> Shuffle<T>(this Random random, IList<T> inputs)
{
return ShuffleInternal(inputs.Count, random.Next).Select(i => inputs[i]);
}
// Fisher-Yates shuffle. Uses a dictionary to save time and memory when less than totalCount elements are needed
private static IEnumerable<int> ShuffleInternal(int totalCount, Func<int, int> random)
{
var overrides = new Dictionary<int, int>();
for (int outputIndex = 0; outputIndex < totalCount; outputIndex++)
{
var chosenIndex = random(totalCount - outputIndex) + outputIndex;
int chosenValue, currentValue;
if (!overrides.TryGetValue(outputIndex, out currentValue))
currentValue = outputIndex;
if (!overrides.TryGetValue(chosenIndex, out chosenValue))
chosenValue = chosenIndex;
overrides[chosenIndex] = currentValue;
overrides.Remove(outputIndex);
yield return chosenValue;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment