chore: cleanup day 7 #10

Merged
xuu merged 3 commits from day07-enhance into main 2023-12-26 13:18:08 -07:00
3 changed files with 1091 additions and 66 deletions
Showing only changes of commit 50f1016372 - Show all commits

1000
day07/input2.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@ func main() {
} }
func run(scan *bufio.Scanner) (uint64, uint64) { func run(scan *bufio.Scanner) (uint64, uint64) {
var game Game var game1, game2 Game
for scan.Scan() { for scan.Scan() {
var cards string var cards string
@ -37,15 +37,18 @@ func run(scan *bufio.Scanner) (uint64, uint64) {
} }
fmt.Println("cards", cards, "bid", bid) fmt.Println("cards", cards, "bid", bid)
game.plays = append(game.plays, Play{bid, []rune(cards), &game}) game1.Append(cards, bid)
game2.Append(cards, bid)
} }
game.cardOrder = getOrder(cardTypes1) game1.cardTypes = cardTypes1
product1 := calcProduct(game) game1.cardOrder = getOrder(cardTypes1)
product1 := calcProduct(game1)
game.cardOrder = getOrder(cardTypes2) game2.cardTypes = cardTypes2
game.wildCard = 'J' game2.cardOrder = getOrder(cardTypes2)
product2 := calcProduct(game) game2.wildCard = 'J'
product2 := calcProduct(game2)
return product1, product2 return product1, product2
} }
@ -76,92 +79,108 @@ func getOrder(cardTypes []rune) map[rune]int {
type Game struct { type Game struct {
plays Plays plays Plays
cardOrder map[rune]int cardOrder map[rune]int
cardTypes []rune
wildCard rune wildCard rune
} }
func (g *Game) Append(cards string, bid int) {
p := Play{bid: bid, hand: []rune(cards), game: g}
g.plays = append(g.plays, p)
}
type Play struct { type Play struct {
bid int bid int
hand Hand hand Hand
cardCounts map[rune]int
strength int
game *Game game *Game
} }
type Hand []rune type Hand []rune
func (h Play) HandType() string { func (h *Play) HandType() string {
hc, _ := h.HighCard() hs := h.HandStrength()
switch { kind := hs& 0xf00000
case h.IsFiveOfKind(): hc := h.game.cardTypes[13-hs&0xf0000>>16]
switch kind {
case 0x700000:
return "5K-" + string(hc) return "5K-" + string(hc)
case h.IsFourOfKind(): case 0x600000:
return "4K-" + string(hc) return "4K-" + string(hc)
case h.IsFullHouse(): case 0x500000:
return "FH-" + string(hc) return "FH-" + string(hc)
case h.IsThreeOfKind(): case 0x400000:
return "3K-" + string(hc) return "3K-" + string(hc)
case h.IsTwoPair(): case 0x300000:
return "2P-" + string(hc) return "2P-" + string(hc)
case h.IsOnePair(): case 0x200000:
return "1P-" + string(hc) return "1P-" + string(hc)
case h.IsHighCard(): case 0x100000:
return "HC-" + string(hc) return "HC-" + string(hc)
} }
return "Uno" return "Uno"
} }
func (h Play) HandStrength() int { func (p *Play) HandStrength() int {
_, v := h.HighCard() _, v := p.HighCard()
switch { switch {
case h.IsFiveOfKind(): case p.IsFiveOfKind():
return 0x700000 | v p.strength = 0x700000 | v
case h.IsFourOfKind(): case p.IsFourOfKind():
return 0x600000 | v p.strength = 0x600000 | v
case h.IsFullHouse(): case p.IsFullHouse():
return 0x500000 | v p.strength = 0x500000 | v
case h.IsThreeOfKind(): case p.IsThreeOfKind():
return 0x400000 | v p.strength = 0x400000 | v
case h.IsTwoPair(): case p.IsTwoPair():
return 0x300000 | v p.strength = 0x300000 | v
case h.IsOnePair(): case p.IsOnePair():
return 0x200000 | v p.strength = 0x200000 | v
case h.IsHighCard(): case p.IsHighCard():
return 0x100000 | v p.strength = 0x100000 | v
} }
return 0 return p.strength
} }
func (h Play) IsFiveOfKind() bool { func (h Play) IsFiveOfKind() bool {
_, _, _, _, has5 := h.game.hasSame(h.hand) _, _, _, _, has5 := h.game.hasSame(h.cardCounts)
return has5 return has5
} }
func (h Play) IsFourOfKind() bool { func (h Play) IsFourOfKind() bool {
_, _, _, has4, _ := h.game.hasSame(h.hand) _, _, _, has4, _ := h.game.hasSame(h.cardCounts)
return has4 return has4
} }
func (h Play) IsFullHouse() bool { func (h Play) IsFullHouse() bool {
_, has2, has3, _, _ := h.game.hasSame(h.hand) _, has2, has3, _, _ := h.game.hasSame(h.cardCounts)
return has3 && has2 return has3 && has2
} }
func (h Play) IsThreeOfKind() bool { func (h Play) IsThreeOfKind() bool {
has1, _, has3, _, _ := h.game.hasSame(h.hand) has1, _, has3, _, _ := h.game.hasSame(h.cardCounts)
return has3 && has1 return has3 && has1
} }
func (h Play) IsTwoPair() bool { func (h Play) IsTwoPair() bool {
_, has2, has3, _, _ := h.game.hasSame(h.hand) _, has2, has3, _, _ := h.game.hasSame(h.cardCounts)
return !has3 && has2 && h.game.pairs(h.hand) == 2 return !has3 && has2 && h.game.pairs(h.cardCounts) == 2
} }
func (h Play) IsOnePair() bool { func (h Play) IsOnePair() bool {
_, has2, has3, _, _ := h.game.hasSame(h.hand) _, has2, has3, _, _ := h.game.hasSame(h.cardCounts)
return !has3 && has2 && h.game.pairs(h.hand) == 1 return !has3 && has2 && h.game.pairs(h.cardCounts) == 1
} }
func (h Play) IsHighCard() bool { func (h Play) IsHighCard() bool {
has1, has2, has3, has4, _ := h.game.hasSame(h.hand) has1, has2, has3, has4, _ := h.game.hasSame(h.cardCounts)
return has1 && !has2 && !has3 && !has4 return has1 && !has2 && !has3 && !has4
} }
func (h Play) HighCard() (rune, int) { func (h *Play) HighCard() (rune, int) {
if h.cardCounts == nil {
h.generateCounts()
}
var i int var i int
pairs := make(Pairs, 5) pairs := make(Pairs, 5)
cnt := h.game.Counts(h.hand) for r, c := range h.cardCounts {
for r, c := range cnt {
pairs[i].c = c pairs[i].c = c
pairs[i].r = r pairs[i].r = r
pairs[i].o = h.game.cardOrder[r] pairs[i].o = h.game.cardOrder[r]
@ -204,29 +223,32 @@ func (p Plays) Len() int { return len(p) }
func (p Plays) Less(i, j int) bool { return p[i].HandStrength() < p[j].HandStrength() } func (p Plays) Less(i, j int) bool { return p[i].HandStrength() < p[j].HandStrength() }
func (p Plays) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p Plays) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (g *Game) Counts(cards []rune) map[rune]int { func (p *Play) generateCounts() {
m := make(map[rune]int, len(g.cardOrder)) cardOrder := p.game.cardOrder
for _, c := range cards { wildCard := p.game.wildCard
m[c]++
p.cardCounts = make(map[rune]int, len(cardOrder))
for _, c := range p.hand {
p.cardCounts[c]++
} }
if g.wildCard != 0 && m[g.wildCard] > 0 {
if wildCard != 0 && p.cardCounts[wildCard] > 0 {
var maxK rune var maxK rune
var maxV int var maxV int
for k, v := range m { for k, v := range p.cardCounts {
if k != g.wildCard && v > maxV { if k != wildCard && v > maxV {
maxK, maxV = k, v maxK, maxV = k, v
} }
} }
if maxK != 0 { if maxK != 0 {
m[maxK] += m[g.wildCard] p.cardCounts[maxK] += p.cardCounts[wildCard]
delete(m, g.wildCard) delete(p.cardCounts, wildCard)
} }
} }
return m
} }
func (g *Game) hasSame(cards []rune) (has1, has2, has3, has4, has5 bool) { func (g *Game) hasSame(counts map[rune]int) (has1, has2, has3, has4, has5 bool) {
cnt := g.Counts(cards) for _, c := range counts {
for _, c := range cnt {
switch c { switch c {
case 1: case 1:
has1 = true has1 = true
@ -246,9 +268,9 @@ func (g *Game) hasSame(cards []rune) (has1, has2, has3, has4, has5 bool) {
} }
return return
} }
func (g *Game) pairs(cards []rune) int { func (g *Game) pairs(counts map[rune]int) int {
pairs := 0 pairs := 0
for _, n := range g.Counts(cards) { for _, n := range counts {
if n == 2 { if n == 2 {
pairs++ pairs++
} }

View File

@ -26,18 +26,21 @@ func TestHands(t *testing.T) {
var game Game var game Game
game.cardOrder = getOrder(cardTypes1) game.cardOrder = getOrder(cardTypes1)
h := Play{0, []rune("AAA23"), &game} h := Play{hand: []rune("AAA23"), game: &game}
// h.generateCounts()
is.Equal(h.HandType(), "3K-A") is.Equal(h.HandType(), "3K-A")
h = Play{0, []rune("JJJJJ"), &game} h = Play{hand: []rune("JJJJJ"), game:&game}
h.generateCounts()
is.Equal(h.HandType(), "5K-J") is.Equal(h.HandType(), "5K-J")
is.Equal(fmt.Sprintf("%x", h.HandStrength()), "7aaaaa") is.Equal(fmt.Sprintf("%x", h.HandStrength()), "7aaaaa")
h = Play{0, []rune("KKKKJ"), &game} h = Play{hand: []rune("KKKKJ"), game: &game}
is.Equal(h.HandType(), "4K-K") is.Equal(h.HandType(), "4K-K")
is.Equal(fmt.Sprintf("%x", h.HandStrength()), "6cccca") is.Equal(fmt.Sprintf("%x", h.HandStrength()), "6cccca")
h = Play{0, []rune("QQQJA"), &game} h = Play{hand: []rune("QQQJA"), game: &game}
is.Equal(h.HandType(), "3K-Q") is.Equal(h.HandType(), "3K-Q")
is.Equal(fmt.Sprintf("%x", h.HandStrength()), "4bbbad") is.Equal(fmt.Sprintf("%x", h.HandStrength()), "4bbbad")
} }