public HandStrength GetStrength() { if (Cards.Count == 5) { var strength = new HandStrength(); strength.Kickers = new List <int>(); Cards = Cards.OrderBy(card => card.PrimeRank * 100 + card.PrimeSuit).ToList(); int rankProduct = Cards.Select(card => card.PrimeRank).Aggregate((acc, r) => acc * r); int suitProduct = Cards.Select(card => card.PrimeSuit).Aggregate((acc, r) => acc * r); bool straight = rankProduct == 8610 || // 5-high straight rankProduct == 2310 || // 6-high straight rankProduct == 15015 || // 7-high straight rankProduct == 85085 || // 8-high straight rankProduct == 323323 || // 9-high straight rankProduct == 1062347 || // T-high straight rankProduct == 2800733 || // J-high straight rankProduct == 6678671 || // Q-high straight rankProduct == 14535931 || // K-high straight rankProduct == 31367009; // A-high straight bool flush = suitProduct == 147008443 || // Spades suitProduct == 229345007 || // Hearts suitProduct == 418195493 || // Diamonds suitProduct == 714924299; // Clubs var cardCounts = Cards.GroupBy(card => (int)card.Rank).Select(group => group).ToList(); var fourOfAKind = -1; var threeOfAKind = -1; var onePair = -1; var twoPair = -1; foreach (var group in cardCounts) { var rank = group.Key; var count = group.Count(); if (count == 4) { fourOfAKind = rank; } else if (count == 3) { threeOfAKind = rank; } else if (count == 2) { twoPair = onePair; onePair = rank; } } if (straight && flush) { strength.HandRanking = HandRanking.StraightFlush; strength.Kickers = Cards.Select(card => (int)card.Rank).Reverse().ToList(); } else if (fourOfAKind >= 0) { strength.HandRanking = HandRanking.FourOfAKind; strength.Kickers.Add(fourOfAKind); strength.Kickers.AddRange(Cards .Where(card => (int)card.Rank != fourOfAKind) .Select(card => (int)card.Rank)); } else if (threeOfAKind >= 0 && onePair >= 0) { strength.HandRanking = HandRanking.FullHouse; strength.Kickers.Add(threeOfAKind); strength.Kickers.Add(onePair); } else if (flush) { strength.HandRanking = HandRanking.Flush; strength.Kickers.AddRange(Cards .Select(card => (int)card.Rank) .Reverse()); } else if (straight) { strength.HandRanking = HandRanking.Straight; strength.Kickers.AddRange(Cards .Select(card => (int)card.Rank) .Reverse()); } else if (threeOfAKind >= 0) { strength.HandRanking = HandRanking.ThreeOfAKind; strength.Kickers.Add(threeOfAKind); strength.Kickers.AddRange(Cards .Where(card => (int)card.Rank != threeOfAKind) .Select(card => (int)card.Rank)); } else if (twoPair >= 0) { strength.HandRanking = HandRanking.TwoPair; strength.Kickers.Add(Math.Max(twoPair, onePair)); strength.Kickers.Add(Math.Min(twoPair, onePair)); strength.Kickers.AddRange(Cards .Where(card => (int)card.Rank != twoPair && (int)card.Rank != onePair) .Select(card => (int)card.Rank)); } else if (onePair >= 0) { strength.HandRanking = HandRanking.Pair; strength.Kickers.Add(onePair); strength.Kickers.AddRange(Cards .Where(card => (int)card.Rank != onePair) .Select(card => (int)card.Rank)); } else { strength.HandRanking = HandRanking.HighCard; strength.Kickers.AddRange(Cards .Select(card => (int)card.Rank) .Reverse()); } return(strength); } else { return(null); } }
private void GenerateFiveCardTable() { var sourceSet = Enumerable.Range(0, 52).ToList(); var combinations = new Combinatorics.Collections.Combinations <int>(sourceSet, 5); // Generate all possible 5 card hand bitmaps Console.WriteLine("Generating bitmaps"); var handBitmaps = new List <ulong>(); int count = 0; foreach (List <int> values in combinations) { if (debug && count++ % 1000 == 0) { Console.Write("{0} / {1}\r", count, combinations.Count); } handBitmaps.Add(values.Aggregate(0ul, (acc, el) => acc | (1ul << el))); } // Calculate hand strength of each hand Console.WriteLine("Calculating hand strength"); var handStrengths = new Dictionary <ulong, HandStrength>(); count = 0; foreach (ulong bitmap in handBitmaps) { if (debug && count++ % 1000 == 0) { Console.Write("{0} / {1}\r", count, handBitmaps.Count); } var hand = new Hand(bitmap); handStrengths.Add(bitmap, hand.GetStrength()); } // Generate a list of all unique hand strengths Console.WriteLine("Generating equivalence classes"); var uniqueHandStrengths = new List <HandStrength>(); count = 0; foreach (KeyValuePair <ulong, HandStrength> strength in handStrengths) { if (debug && count++ % 1000 == 0) { Console.Write("{0} / {1}\r", count, handStrengths.Count); } Utilities.BinaryInsert <HandStrength>(uniqueHandStrengths, strength.Value); } Console.WriteLine("{0} unique hand strengths", uniqueHandStrengths.Count); // Create a map of hand bitmaps to hand strength indices Console.WriteLine("Creating lookup table"); count = 0; foreach (ulong bitmap in handBitmaps) { if (debug && count++ % 1000 == 0) { Console.Write("{0} / {1}\r", count, handBitmaps.Count); } var hand = new Hand(bitmap); HandStrength strength = hand.GetStrength(); var equivalence = Utilities.BinarySearch <HandStrength>(uniqueHandStrengths, strength); if (equivalence == null) { throw new Exception(string.Format("{0} hand not found", hand)); } else { handRankMap[bitmap] = (ulong)equivalence; } } }
private void GenerateFiveCardTable() { var sourceSet = Enumerable.Range(0, 52).ToList(); var combinations = new Combinatorics.Collections.Combinations <int>(sourceSet, 5); // Generate all possible 5 card hand bitmaps var handBitmaps = new List <ulong>(); using (var progress = new ProgressBar()) { long sharedLoopCounter = 0; foreach (List <int> values in combinations) { handBitmaps.Add(values.Aggregate(0ul, (acc, el) => acc | (1ul << el))); sharedLoopCounter++; progress.Report((double)sharedLoopCounter / combinations.Count, sharedLoopCounter); } } // Calculate hand strength of each hand var handStrengths = new Dictionary <ulong, HandStrength>(); Console.WriteLine("Calculating hand strength (" + handBitmaps.Count + ")"); using (var progress = new ProgressBar()) { long sharedLoopCounter = 0; foreach (ulong bitmap in handBitmaps) { var hand = new Hand(bitmap); handStrengths.Add(bitmap, hand.GetStrength()); sharedLoopCounter++; progress.Report((double)sharedLoopCounter / handBitmaps.Count, sharedLoopCounter); } } // Generate a list of all unique hand strengths var uniqueHandStrengths = new List <HandStrength>(); Console.WriteLine("Generating equivalence classes"); using (var progress = new ProgressBar()) { long sharedLoopCounter = 0; foreach (KeyValuePair <ulong, HandStrength> strength in handStrengths) { Utilities.BinaryInsert(uniqueHandStrengths, strength.Value); sharedLoopCounter++; progress.Report((double)sharedLoopCounter / handStrengths.Count, sharedLoopCounter); } } Console.WriteLine("{0} unique hand strengths", uniqueHandStrengths.Count); // Create a map of hand bitmaps to hand strength indices Console.WriteLine("Generating new five card lookup table (2'598'960)"); using (var progress = new ProgressBar()) { long sharedLoopCounter = 0; foreach (ulong bitmap in handBitmaps) { var hand = new Hand(bitmap); HandStrength strength = hand.GetStrength(); var equivalence = Utilities.BinarySearch(uniqueHandStrengths, strength); if (equivalence == null) { throw new Exception(string.Format("{0} hand not found", hand)); } else { handRankMap[bitmap] = (ulong)equivalence; } sharedLoopCounter++; progress.Report((double)sharedLoopCounter / handBitmaps.Count, sharedLoopCounter); } } }