package main import ( "fmt" "sort" "strings" ) type Hand struct { Cards []Card } // NewHand parses an input string and returns a new Hand. func NewHand(input string) (*Hand, error) { parts := strings.Fields(input) if len(parts) != 5 { return nil, fmt.Errorf("invalid number of cards: %d", len(parts)) } var cards []Card valueMap := map[byte]int{ '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, 'T': 10, 'J': 11, 'Q': 12, 'K': 13, 'A': 14, } for _, p := range parts { if len(p) != 2 { return nil, fmt.Errorf("invalid card format: %s", p) } suitChar := string(p[0]) valChar := p[1] val, ok := valueMap[valChar] if !ok { return nil, fmt.Errorf("invalid value: %c", valChar) } cards = append(cards, Card{Suit: suitChar, Value: val}) } return &Hand{Cards: cards}, nil } type HandCategory int const ( HighCard HandCategory = iota Pair TwoPair ThreeOfAKind Straight Flush FullHouse FourOfAKind StraightFlush RoyalFlush ) var handNames = []string{ "High Card", "Pair", "Two Pair", "Three of a Kind", "Straight", "Flush", "Full House", "Four of a Kind", "Straight Flush", "Royal Flush", } type HandResult struct { Category HandCategory TieBreakers []int } // Evaluate evaluates the hand and returns its category and tiebreakers. func (h *Hand) Evaluate() HandResult { sort.Slice(h.Cards, func(i, j int) bool { return h.Cards[i].Value > h.Cards[j].Value }) counts := make(map[int]int) suits := make(map[string]int) for _, c := range h.Cards { counts[c.Value]++ suits[c.Suit]++ } isFlush := len(suits) == 1 isStraight, straightHigh := h.checkStraight() if isFlush && isStraight { if straightHigh == 14 { return HandResult{Category: RoyalFlush, TieBreakers: []int{}} } return HandResult{Category: StraightFlush, TieBreakers: []int{straightHigh}} } type group struct { val int count int } var groups []group for v, c := range counts { groups = append(groups, group{v, c}) } sort.Slice(groups, func(i, j int) bool { if groups[i].count != groups[j].count { return groups[i].count > groups[j].count } return groups[i].val > groups[j].val }) var tieBreakers []int for _, g := range groups { tieBreakers = append(tieBreakers, g.val) } if len(groups) > 1 && groups[0].count == 1 { // Fallback for Straight/Flush Sortierung: sicherstellen, dass es rein nach Wert geht tieBreakers = nil for _, c := range h.Cards { tieBreakers = append(tieBreakers, c.Value) } } if groups[0].count == 4 { return HandResult{Category: FourOfAKind, TieBreakers: []int{groups[0].val, groups[1].val}} } if groups[0].count == 3 && groups[1].count == 2 { return HandResult{Category: FullHouse, TieBreakers: []int{groups[0].val, groups[1].val}} } if isFlush { return HandResult{Category: Flush, TieBreakers: tieBreakers} } if isStraight { return HandResult{Category: Straight, TieBreakers: []int{straightHigh}} } if groups[0].count == 3 { return HandResult{Category: ThreeOfAKind, TieBreakers: []int{groups[0].val, groups[1].val, groups[2].val}} } if groups[0].count == 2 && groups[1].count == 2 { return HandResult{Category: TwoPair, TieBreakers: []int{groups[0].val, groups[1].val, groups[2].val}} } if groups[0].count == 2 { return HandResult{Category: Pair, TieBreakers: []int{groups[0].val, groups[1].val, groups[2].val, groups[3].val}} } return HandResult{Category: HighCard, TieBreakers: tieBreakers} } func (h *Hand) checkStraight() (bool, int) { isStd := true for i := 0; i < 4; i++ { if h.Cards[i].Value != h.Cards[i+1].Value+1 { isStd = false break } } if isStd { return true, h.Cards[0].Value } if h.Cards[0].Value == 14 && h.Cards[1].Value == 5 && h.Cards[2].Value == 4 && h.Cards[3].Value == 3 && h.Cards[4].Value == 2 { return true, 5 } return false, 0 } // Compare compares the current hand with another hand. // Returns 1 if the current hand wins, 2 if the other hand wins, and 0 for a tie. func (h *Hand) Compare(other *Hand) int { h1Result := h.Evaluate() h2Result := other.Evaluate() if h1Result.Category > h2Result.Category { return 1 } if h2Result.Category > h1Result.Category { return 2 } for i := 0; i < len(h1Result.TieBreakers); i++ { if h1Result.TieBreakers[i] > h2Result.TieBreakers[i] { return 1 } if h2Result.TieBreakers[i] > h1Result.TieBreakers[i] { return 2 } } return 0 } // FindBestHand finds the best 5-card hand from 7 given cards. func FindBestHand(sevenCards []Card) (*Hand, error) { if len(sevenCards) != 7 { return nil, fmt.Errorf("expected 7 cards, got %d", len(sevenCards)) } var bestHand *Hand // Generate all combinations of 5 cards from 7 for i := 0; i < 7; i++ { for j := i + 1; j < 7; j++ { for k := j + 1; k < 7; k++ { for l := k + 1; l < 7; l++ { for m := l + 1; m < 7; m++ { currentCards := []Card{ sevenCards[i], sevenCards[j], sevenCards[k], sevenCards[l], sevenCards[m], } currentHand := &Hand{Cards: currentCards} if bestHand == nil { bestHand = currentHand } else { // Compare currentHand with bestHand // h.Compare(other) returns 1 if h wins, 2 if other wins, 0 for tie if currentHand.Compare(bestHand) == 1 { bestHand = currentHand } } } } } } } return bestHand, nil }