291 lines
5.1 KiB
Go
291 lines
5.1 KiB
Go
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
|
|
} |