package main import ( "fmt" "sort" h "git.bullercodeworks.com/brian/adventofcode/helpers" ) var p2 bool // 251515138 is too high func main() { inp := h.StdinToStringSlice() part1(inp) fmt.Println() part2(inp) } func part1(input []string) { var hands []*Hand for i := range input { hands = append(hands, NewHand(input[i])) } sort.Sort(sort.Reverse(ByRank(hands))) var total int for i := range hands { total += hands[i].bid * (i + 1) } fmt.Println() fmt.Println("# Part 1") fmt.Println(total) } func part2(input []string) { p2 = true var hands []*Hand for i := range input { hands = append(hands, NewHand(input[i])) } sort.Sort(sort.Reverse(ByRank(hands))) var total int for i := range hands { total += hands[i].bid * (i + 1) } fmt.Println() fmt.Println("# Part 2") fmt.Println(total) } type Hand struct { raw string cards []byte bid int handType int cardMap map[byte]int } const ( TypeFiveOfKind = 6 TypeFourOfKind = 5 TypeFullHouse = 4 TypeThreeOfKind = 3 TypeTwoPair = 2 TypeOnePair = 1 TypeHighCard = 0 ) var typeToString = map[int]string{ TypeFiveOfKind: "Five of a Kind", TypeFourOfKind: "Four of a Kind", TypeFullHouse: "Full House", TypeThreeOfKind: "Three of a Kind", TypeTwoPair: "Two Pair", TypeOnePair: "One Pair", TypeHighCard: "High Card", } func cardToValue(b byte) int { switch b { case 'T': return 10 case 'J': if p2 { return 1 } return 11 case 'Q': return 12 case 'K': return 13 case 'A': return 14 } return int(b - '0') } func NewHand(input string) *Hand { hand := Hand{raw: input} i := 0 for i = range input { if input[i] == ' ' { break } hand.cards = append(hand.cards, input[i]) } hand.bid = h.Atoi(input[i:]) hand.handType = hand.findType() return &hand } func (hand *Hand) findType() int { hand.cardMap = make(map[byte]int) for i := range hand.cards { hand.cardMap[hand.cards[i]]++ } if p2 { if jCnt, ok := hand.cardMap['J']; ok { var c byte cCnt := h.MIN_INT for k, v := range hand.cardMap { if k != 'J' { if v > cCnt { cCnt = v c = k } } } hand.cardMap[c] = hand.cardMap[c] + jCnt delete(hand.cardMap, 'J') } } max := h.MIN_INT for _, v := range hand.cardMap { if v > max { max = v } } switch len(hand.cardMap) { case 5: return TypeHighCard case 4: return TypeOnePair case 3: if max == 3 { return TypeThreeOfKind } return TypeTwoPair case 2: if max == 3 { return TypeFullHouse } return TypeFourOfKind default: return TypeFiveOfKind } } func (hand Hand) String() string { return fmt.Sprintf("%s %d", string(hand.cards), hand.bid) } type ByRank []*Hand func (rank ByRank) Len() int { return len(rank) } func (rank ByRank) Swap(i, j int) { rank[i], rank[j] = rank[j], rank[i] } func (rank ByRank) Less(i, j int) bool { if rank[i].handType > rank[j].handType { return true } else if rank[j].handType > rank[i].handType { return false } for k := range rank[i].cards { cmp := cmpCards(rank[i].cards[k], rank[j].cards[k]) if cmp != 0 { return cmp == 1 } } return false } func cmpCards(c1, c2 byte) int { if cardToValue(c1) > cardToValue(c2) { return 1 } else if cardToValue(c1) < cardToValue(c2) { return -1 } return 0 }