+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
+}
\ No newline at end of file