This commit is contained in:
gareth
2023-12-09 21:38:37 +00:00
4 changed files with 1329 additions and 1 deletions

291
2023/go/day07/day07.go Normal file
View File

@@ -0,0 +1,291 @@
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
}

View File

@@ -0,0 +1,33 @@
package day07
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestPart1(t *testing.T) {
r := Part1(
`32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483`)
require.Equal(t, 6440, r)
}
func TestPart2(t *testing.T) {
r := Part2(
`32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483`)
require.Equal(t, 5905, r)
}
func TestPart21(t *testing.T) {
r := Part2(
`QQKKJ 765
JKKK2 684`)
require.Equal(t, 5905, r)
}

1000
2023/go/day07/input.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -13,6 +13,7 @@ import (
"adventofcode2023/day04"
"adventofcode2023/day05"
"adventofcode2023/day06"
"adventofcode2023/day07"
)
// Usage: go run main.go <NN>
// assumes input is in day<NN>/input.txt
@@ -39,6 +40,9 @@ func main() {
case 6:
fmt.Printf("part 1: %d\n", day06.Part1(utils.Readfile(d)))
fmt.Printf("part 2: %d\n", day06.Part2(utils.Readfile(d)))
case 7:
fmt.Printf("part 1: %d\n", day07.Part1(utils.Readfile(d)))
fmt.Printf("part 2: %d\n", day07.Part2(utils.Readfile(d)))
default:
panic(fmt.Errorf("no such day: %d", d))
}
@@ -46,7 +50,7 @@ func main() {
// Reads day from os.Args.
func day() int {
latest := 5
latest := 6
if len(os.Args) == 1 {
return latest
}