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

     1  package day7
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"slices"
     7  	"strconv"
     8  	"strings"
     9  )
    10  
    11  const (
    12  	cA = iota
    13  	cK
    14  	cQ
    15  	cJ
    16  	cT
    17  	c9
    18  	c8
    19  	c7
    20  	c6
    21  	c5
    22  	c4
    23  	c3
    24  	c2
    25  )
    26  
    27  const (
    28  	rFiveOfAKind = iota
    29  	rFourOfAKind
    30  	rFullHouse
    31  	rTheeOfAKind
    32  	rTwoPairs
    33  	rPair
    34  	rHighCard
    35  )
    36  
    37  var ctoi = map[rune]int{
    38  	'A': cA,
    39  	'K': cK,
    40  	'Q': cQ,
    41  	'J': cJ,
    42  	'T': cT,
    43  	'9': c9,
    44  	'8': c8,
    45  	'7': c7,
    46  	'6': c6,
    47  	'5': c5,
    48  	'4': c4,
    49  	'3': c3,
    50  	'2': c2,
    51  }
    52  
    53  type hand struct {
    54  	cards  [5]int
    55  	bid    int
    56  	counts [13]int
    57  	rank   int
    58  }
    59  
    60  func d7p1(input string) int {
    61  	lines := strings.Split(input, "\n")
    62  	hands := []*hand{}
    63  
    64  	for _, line := range lines {
    65  		var h = parseHand(line)
    66  		hands = append(hands, h)
    67  	}
    68  
    69  	slices.SortFunc(hands, func(a, b *hand) int {
    70  		if a.rank != b.rank {
    71  			return b.rank - a.rank
    72  		}
    73  		for i := 0; i < len(a.cards); i++ {
    74  			if a.cards[i] != b.cards[i] {
    75  				return b.cards[i] - a.cards[i]
    76  			}
    77  		}
    78  		return 0
    79  	})
    80  
    81  	sum := 0
    82  	for i, h := range hands {
    83  		sum += h.bid * (i + 1)
    84  	}
    85  
    86  	fmt.Println(sum)
    87  
    88  	return sum
    89  }
    90  
    91  func parseHand(str string) *hand {
    92  	h := &hand{}
    93  	for i, r := range str[:5] {
    94  		h.cards[i] = ctoi[r]
    95  		h.counts[ctoi[r]] += 1
    96  		if bid, err := strconv.Atoi(str[6:]); err != nil {
    97  			log.Fatal("error parsing bid", err)
    98  		} else {
    99  			h.bid = bid
   100  		}
   101  	}
   102  	h.resolveRank()
   103  	return h
   104  }
   105  
   106  func (h *hand) resolveRank() {
   107  	sortedCounts := make([]int, len(h.counts))
   108  	copy(sortedCounts, h.counts[:])
   109  	slices.SortFunc(sortedCounts, func(a, b int) int { return b - a })
   110  	switch sortedCounts[0] {
   111  	case 5:
   112  		h.rank = rFiveOfAKind
   113  	case 4:
   114  		h.rank = rFourOfAKind
   115  	case 3:
   116  		if sortedCounts[1] == 2 {
   117  			h.rank = rFullHouse
   118  		} else {
   119  			h.rank = rTheeOfAKind
   120  		}
   121  	case 2:
   122  		if sortedCounts[1] == 2 {
   123  			h.rank = rTwoPairs
   124  		} else {
   125  			h.rank = rPair
   126  		}
   127  	default:
   128  		h.rank = rHighCard
   129  	}
   130  }