Merge branch 'master' of https://gitea.kageds.com/alan/adventofcode
This commit is contained in:
291
2023/go/day07/day07.go
Normal file
291
2023/go/day07/day07.go
Normal 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
|
||||||
|
}
|
||||||
33
2023/go/day07/day07_test.go
Normal file
33
2023/go/day07/day07_test.go
Normal 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
1000
2023/go/day07/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,7 @@ import (
|
|||||||
"adventofcode2023/day04"
|
"adventofcode2023/day04"
|
||||||
"adventofcode2023/day05"
|
"adventofcode2023/day05"
|
||||||
"adventofcode2023/day06"
|
"adventofcode2023/day06"
|
||||||
|
"adventofcode2023/day07"
|
||||||
)
|
)
|
||||||
// Usage: go run main.go <NN>
|
// Usage: go run main.go <NN>
|
||||||
// assumes input is in day<NN>/input.txt
|
// assumes input is in day<NN>/input.txt
|
||||||
@@ -39,6 +40,9 @@ func main() {
|
|||||||
case 6:
|
case 6:
|
||||||
fmt.Printf("part 1: %d\n", day06.Part1(utils.Readfile(d)))
|
fmt.Printf("part 1: %d\n", day06.Part1(utils.Readfile(d)))
|
||||||
fmt.Printf("part 2: %d\n", day06.Part2(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:
|
default:
|
||||||
panic(fmt.Errorf("no such day: %d", d))
|
panic(fmt.Errorf("no such day: %d", d))
|
||||||
}
|
}
|
||||||
@@ -46,7 +50,7 @@ func main() {
|
|||||||
|
|
||||||
// Reads day from os.Args.
|
// Reads day from os.Args.
|
||||||
func day() int {
|
func day() int {
|
||||||
latest := 5
|
latest := 6
|
||||||
if len(os.Args) == 1 {
|
if len(os.Args) == 1 {
|
||||||
return latest
|
return latest
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user