Today we learned about CamelCards, a game of poker meant to play on the back of a camel. The most interesting part here was the parsing of the cards and figuring out how to properly rank them. Part 2 turned out to be as easy as tracking Jokers.
package main
import (
"fmt"
"sort"
"strconv"
"strings"
"time"
"arjenwiersma.nl/aoc/internal/aoc"
)
type Card struct {
bid int
hand []int
jokers int
}
func (c *Card) strongerThen(o *Card) bool {
for i, v := range c.hand {
if v > o.hand[i] {
return true
} else if v < o.hand[i] {
return false
}
}
return false
}
func (c *Card) rank() int {
freq := make([]int, 15)
for _, v := range c.hand {
if v == 1 { // skip counting the joker
continue
}
freq[v]++
}
sort.Ints(freq)
freq[len(freq)-1] += c.jokers
strength := 2 * freq[len(freq)-1]
// full house and 2 pair
if freq[len(freq)-2] == 2 {
strength += 1
}
return strength
}
func NewCard(s string, bid int, p2 bool) *Card {
c := &Card{}
c.bid = bid
c.jokers = 0
for p := 0; p < len(s); p++ {
if s[p]-'0' >= 2 && s[p]-'0' <= 9 {
c.hand = append(c.hand, int(s[p]-'0'))
} else {
x := 10
switch s[p] {
case 'A':
x = 14
case 'K':
x = 13
case 'Q':
x = 12
case 'J':
if p2 {
c.jokers += 1
x = 1
} else {
x = 11
}
case 'T':
x = 10
}
c.hand = append(c.hand, x)
}
}
return c
}
func (c *Card) String() string {
return fmt.Sprintf("%v (%d)", c.hand, c.bid)
}
func main() {
content := aoc.AsLines("2023/Day07/input.txt")
var cards []*Card
for _, v := range content {
p := strings.Split(v, " ")
b, _ := strconv.Atoi(p[1])
c := NewCard(p[0], b, false)
cards = append(cards, c)
}
startTime := time.Now()
lessFunc := func(i, j int) bool {
if cards[i].rank() == cards[j].rank() {
return cards[j].strongerThen(cards[i])
}
return cards[i].rank() < cards[j].rank()
}
sort.Slice(cards, lessFunc)
res := 0
for i, c := range cards {
res += (i + 1) * c.bid
}
endTime := time.Now()
elapsed := endTime.Sub(startTime)
if 251216224 != res {
panic("Wrong answer")
}
fmt.Printf("Part 1: %d (%v)\n", res, elapsed) // 251216224
cards = []*Card{}
for _, v := range content {
p := strings.Split(v, " ")
b, _ := strconv.Atoi(p[1])
c := NewCard(p[0], b, true)
cards = append(cards, c)
}
startTime = time.Now()
sort.Slice(cards, lessFunc)
res = 0
for i, c := range cards {
res += (i + 1) * c.bid
}
endTime = time.Now()
elapsed = endTime.Sub(startTime)
if 250825971 != res {
panic("Wrong part 2")
}
fmt.Printf("Part 2: %d (%v)\n", res, elapsed) // 250825971
}