package day07 import ( _ "fmt" "strings" "sort" "adventofcode2023/utils" ) type Card int const ( _ Card = 1 + iota Two Three Four Five Six Seven Eight Nine Ten Jack Queen King Ace ) type Card2 int const ( _ Card2 = iota Joker Two2 Three2 Four2 Five2 Six2 Seven2 Eight2 Nine2 Ten2 Queen2 King2 Ace2 ) type HandType int const ( _ HandType = iota HighCard OnePair TwoPair ThreeKind FullHouse FourKind FiveKind ) type Hand struct { cards [5]Card bid int rank int handType HandType } type Hand2 struct { cards [5]Card2 bid int rank int handType HandType } func Part1(input string) int { total := 0 hands := parseInput(1, input) sort.Slice(hands, func(i, j int) bool { if hands[i].handType == hands[j].handType { for k:=0;k<5;k++{ if hands[i].cards[k] == hands[j].cards[k] { continue } return hands[i].cards[k] < hands[j].cards[k] } } return hands[i].handType < hands[j].handType }) for i,hand := range hands { total += (i+1) * hand.bid } return total } func Part2(input string) int { total := 0 hands := parseInput(2, input) sort.Slice(hands, func(i, j int) bool { if hands[i].handType == hands[j].handType { for k:=0;k<5;k++{ if hands[i].cards[k] == hands[j].cards[k] { continue } if hands[i].cards[k] == Jack {return true} if hands[j].cards[k] == Jack {return false} return hands[i].cards[k] < hands[j].cards[k] } } return hands[i].handType < hands[j].handType }) for i,hand := range hands { total += (i+1) * hand.bid } return total } func parseInput(part int, input string) ([]Hand) { var hand Hand var hands []Hand lines := strings.Split(input, "\n") for _, line := range lines { tokens := strings.Fields(line) hand.bid = utils.MustAtoi(tokens[1]) for i, j := range tokens[0] { hand.cards[i] = toCard(j) } hand.handType = toHandType(part, hand.cards) hands = append(hands, hand) } return hands } func toCard(j rune) Card { switch j { case '2': return Two case '3': return Three case '4': return Four case '5': return Five case '6': return Six case '7': return Seven case '8': return Eight case '9': return Nine case 'T': return Ten case 'J': return Jack case 'Q': return Queen case 'K': return King case 'A': return Ace } return -1 } func toHandType(part int, cards [5]Card) HandType { jokers := 0 handType := HighCard cardMap := make(map[Card]int) for _, card := range cards { if part == 2 && card == Jack { jokers++ } else { if _, ok := cardMap[card]; ok { cardMap[card]++ } else { cardMap[card] = 1 } } } cardSorted := ToSortedSlice(cardMap) if part == 2 && jokers == 5 { return FiveKind} if part == 2 && jokers > 0 { cardSorted[0].Value = cardSorted[0].Value + jokers } if cardSorted[0].Value == 5 { handType = FiveKind} if cardSorted[0].Value == 4 { handType = FourKind} if cardSorted[0].Value == 3 { if cardSorted[1].Value == 2 {handType = FullHouse} if cardSorted[1].Value == 1 {handType = ThreeKind} } if cardSorted[0].Value == 2 { if cardSorted[1].Value == 2 {handType = TwoPair} if cardSorted[1].Value == 1 {handType = OnePair} } return handType } //func toHandType(part int, cards [5]Card) HandType { // cardMap := make(map[Card]int) // for _, card := range cards { // if _, ok := cardMap[card]; ok { // cardMap[card]++ // } else { // cardMap[card] = 1 // } // } // if part == 2 { // switch cardMap[Jack] { // case 5: // return FiveKind // case 4: // return FiveKind // case 3: // if len(cardMap) == 2 {return FiveKind} // return FourKind // case 2: // switch len(cardMap) { // case 2: // return FiveKind // case 3: // return FourKind // case 4: // return ThreeKind // // } // case 1: // switch len(cardMap) { // case 2: // return FiveKind // case 3: // max := utils.MapFindMax(cardMap) // if max == 3 {return FourKind} // if max == 2 {return FullHouse} // case 4: // return ThreeKind // case 5: // return OnePair // // } // } // } // switch len(cardMap) { // case 5: // return HighCard // case 4: // return OnePair // case 3: // for _, count := range cardMap { // if count == 3 { // return ThreeKind // } // } // return TwoPair // case 2: // for _, count := range cardMap { // if count == 4 { // return FourKind // } // } // return FullHouse // case 1: // return FiveKind // } // return -1 //} // KeyValue is a struct to hold key-value pairs type KeyValue struct { Key Card Value int } func ToSortedSlice(myMap map[Card]int) []KeyValue { var keyValuePairs []KeyValue for key, value := range myMap { keyValuePairs = append(keyValuePairs, KeyValue{key, value}) } // Sort the slice by values sort.Slice(keyValuePairs, func(i, j int) bool { if keyValuePairs[i].Value == keyValuePairs[j].Value { return keyValuePairs[i].Key > keyValuePairs[j].Key } return keyValuePairs[i].Value > keyValuePairs[j].Value }) // Create a new map with sorted key-value pairs //sortedMap := make(map[Card]int) //for _, kv := range keyValuePairs { // sortedMap[kv.Key] = kv.Value //} return keyValuePairs }