namespace Day7; public class Hand : IComparable { private static readonly Dictionary, int> Types = new Dictionary, int> { [counts => counts[0] == 5] = 7, [counts => counts[0] == 4] = 6, [counts => counts[0] == 3 && counts[1] == 2] = 5, [counts => counts[0] == 3] = 4, [counts => counts[0] == 2 && counts[1] == 2] = 3, [counts => counts[0] == 2] = 2, [_ => true] = 1, }; private static readonly string CardOrder = "23456789TJQKA"; private static readonly string CardOrderWild = "J23456789TQKA"; private readonly bool _jacksAreWild; public string Cards { get; } public int Type { get; set; } public int Bid { get; } public Hand(string cards, int bid) : this(cards, bid, false) { } private Hand(string cards, int bid, bool jacksAreWild) { _jacksAreWild = jacksAreWild; Cards = cards; Bid = bid; Type = GetHandType(); } public Hand Recalculate(bool jacksAreWild) { return new Hand(Cards, Bid, jacksAreWild); } private int GetHandType() { int[] counts; if (_jacksAreWild) { var set = new Dictionary(); var wild = 0; foreach (var c in Cards) { if (c == 'J') { wild++; } else { set.TryAdd(c, 0); set[c]++; } } counts = set.Values.OrderDescending().ToArray(); if (counts.Length > 0) { counts[0] += wild; } else { counts = new int[] { wild }; } } else { var set = new Dictionary(); foreach (var c in Cards) { set.TryAdd(c, 0); set[c]++; } counts = set.Values.OrderDescending().ToArray(); } return Types.First(kvp => kvp.Key(counts)).Value; } public int CompareTo(Hand? other) { // this < other => negative var typeCmp = Type.CompareTo(other?.Type); if (typeCmp != 0) return typeCmp; for (var i = 0; i < Cards.Length; i++) { var cardCmp = CompareCard(Cards[i], other!.Cards[i]); if (cardCmp != 0) { return cardCmp; } } return 0; } private int CompareCard(char left, char right) { var vLeft = (_jacksAreWild ? CardOrderWild : CardOrder).IndexOf(left); var vRight = (_jacksAreWild ? CardOrderWild : CardOrder).IndexOf(right); return vLeft.CompareTo(vRight); } }