-
-
Save CodesInChaos/9226bad330dd1b80db24 to your computer and use it in GitHub Desktop.
This file contains 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
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