github.com/agrigoryan/aoc_2023_go@v0.0.0-20231216221323-4ace361ec685/day7/d7p2.go (about)

     1  package day7
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"slices"
     7  	"strconv"
     8  	"strings"
     9  )
    10  
    11  func d7p2(input string) int {
    12  	lines := strings.Split(input, "\n")
    13  	hands := []*hand{}
    14  
    15  	for _, line := range lines {
    16  		var h = parseHand2(line)
    17  		hands = append(hands, h)
    18  	}
    19  
    20  	slices.SortFunc(hands, func(a, b *hand) int {
    21  		if a.rank != b.rank {
    22  			return b.rank - a.rank
    23  		}
    24  		for i := 0; i < len(a.cards); i++ {
    25  			if a.cards[i] != b.cards[i] {
    26  				return b.cards[i] - a.cards[i]
    27  			}
    28  		}
    29  		return 0
    30  	})
    31  
    32  	sum := 0
    33  	for i, h := range hands {
    34  		sum += h.bid * (i + 1)
    35  	}
    36  
    37  	fmt.Println(sum)
    38  	return sum
    39  }
    40  
    41  func parseHand2(str string) *hand {
    42  	h := &hand{}
    43  	numJokers := 0
    44  	for i, r := range str[:5] {
    45  		card := ctoi[r]
    46  		h.cards[i] = card
    47  		h.counts[card] += 1
    48  		if card == cJ {
    49  			numJokers += 1
    50  		}
    51  		if bid, err := strconv.Atoi(str[6:]); err != nil {
    52  			log.Fatal("error parsing bid", err)
    53  		} else {
    54  			h.bid = bid
    55  		}
    56  	}
    57  
    58  	h.resolveRank2()
    59  	return h
    60  }
    61  
    62  func (h *hand) resolveRank2() {
    63  	sortedCounts := make([]int, len(h.counts))
    64  	copy(sortedCounts, h.counts[:])
    65  	numJoker := sortedCounts[cJ]
    66  	if numJoker > 0 {
    67  		maxCard := 0
    68  		maxCount := 0
    69  		for i, c := range sortedCounts {
    70  			if c > maxCount && i != cJ {
    71  				maxCard = i
    72  				maxCount = c
    73  			}
    74  		}
    75  		sortedCounts[maxCard] += numJoker
    76  		sortedCounts[cJ] = 0
    77  	}
    78  	slices.SortFunc(sortedCounts, func(a, b int) int { return b - a })
    79  	switch sortedCounts[0] {
    80  	case 5:
    81  		h.rank = rFiveOfAKind
    82  	case 4:
    83  		h.rank = rFourOfAKind
    84  	case 3:
    85  		if sortedCounts[1] >= 2 {
    86  			h.rank = rFullHouse
    87  		} else {
    88  			h.rank = rTheeOfAKind
    89  		}
    90  	case 2:
    91  		if sortedCounts[1] >= 2 {
    92  			h.rank = rTwoPairs
    93  		} else {
    94  			h.rank = rPair
    95  		}
    96  	default:
    97  		h.rank = rHighCard
    98  	}
    99  }