chore: setup folders for aoc 2024
Some checks failed
Go Bump / bump (push) Failing after 9s
Go Test / build (push) Successful in 38s

This commit is contained in:
xuu
2024-10-26 11:38:38 -06:00
parent 50af2114d4
commit 3c9af95ec4
92 changed files with 72 additions and 1 deletions

View File

@@ -0,0 +1,5 @@
32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483

1000
aoc2023/day07/input.txt Normal file

File diff suppressed because it is too large Load Diff

1000
aoc2023/day07/input2.txt Normal file

File diff suppressed because it is too large Load Diff

247
aoc2023/day07/main.go Normal file
View File

@@ -0,0 +1,247 @@
package main
import (
"bufio"
"fmt"
"sort"
aoc "go.sour.is/advent-of-code"
)
func main() { aoc.MustResult(aoc.Runner(run)) }
type result struct {
valuePT1 uint64
valuePT2 uint64
}
func run(scan *bufio.Scanner) (result, error) {
var game Game
for scan.Scan() {
var cards string
var bid int
_, err := fmt.Sscanf(scan.Text(), "%s %d", &cards, &bid)
if err != nil {
panic(err)
}
fmt.Println("cards", cards, "bid", bid)
game.plays = append(game.plays, Play{bid, []rune(cards), &game})
}
game.cardOrder = getOrder(cardTypes1)
product1 := calcProduct(game)
game.cardOrder = getOrder(cardTypes2)
game.wildCard = 'J'
product2 := calcProduct(game)
return result{product1, product2}, nil
}
var cardTypes1 = []rune{'A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2'}
var cardTypes2 = []rune{'A', 'K', 'Q', 'T', '9', '8', '7', '6', '5', '4', '3', '2', 'J'}
func calcProduct(game Game) uint64 {
sort.Sort(game.plays)
var product uint64
for i, play := range game.plays {
rank := i + 1
fmt.Printf("play %d %s %d %s %x\n", rank, string(play.hand), play.bid, play.HandType(), play.HandStrength())
product += uint64(play.bid * rank)
}
return product
}
func getOrder(cardTypes []rune) map[rune]int {
cardOrder := make(map[rune]int, len(cardTypes))
for i, r := range cardTypes {
cardOrder[r] = len(cardTypes) - i
}
return cardOrder
}
type Game struct {
plays Plays
cardOrder map[rune]int
wildCard rune
}
type Play struct {
bid int
hand Hand
game *Game
}
type Hand []rune
func (h Play) HandType() string {
hc, _ := h.HighCard()
switch {
case h.IsFiveOfKind():
return "5K-" + string(hc)
case h.IsFourOfKind():
return "4K-" + string(hc)
case h.IsFullHouse():
return "FH-" + string(hc)
case h.IsThreeOfKind():
return "3K-" + string(hc)
case h.IsTwoPair():
return "2P-" + string(hc)
case h.IsOnePair():
return "1P-" + string(hc)
case h.IsHighCard():
return "HC-" + string(hc)
}
return "Uno"
}
func (h Play) HandStrength() int {
_, v := h.HighCard()
switch {
case h.IsFiveOfKind():
return 0x700000 | v
case h.IsFourOfKind():
return 0x600000 | v
case h.IsFullHouse():
return 0x500000 | v
case h.IsThreeOfKind():
return 0x400000 | v
case h.IsTwoPair():
return 0x300000 | v
case h.IsOnePair():
return 0x200000 | v
case h.IsHighCard():
return 0x100000 | v
}
return 0
}
func (h Play) IsFiveOfKind() bool {
_, _, _, _, has5 := h.game.hasSame(h.hand)
return has5
}
func (h Play) IsFourOfKind() bool {
_, _, _, has4, _ := h.game.hasSame(h.hand)
return has4
}
func (h Play) IsFullHouse() bool {
_, has2, has3, _, _ := h.game.hasSame(h.hand)
return has3 && has2
}
func (h Play) IsThreeOfKind() bool {
has1, _, has3, _, _ := h.game.hasSame(h.hand)
return has3 && has1
}
func (h Play) IsTwoPair() bool {
_, has2, has3, _, _ := h.game.hasSame(h.hand)
return !has3 && has2 && h.game.pairs(h.hand) == 2
}
func (h Play) IsOnePair() bool {
_, has2, has3, _, _ := h.game.hasSame(h.hand)
return !has3 && has2 && h.game.pairs(h.hand) == 1
}
func (h Play) IsHighCard() bool {
has1, has2, has3, has4, _ := h.game.hasSame(h.hand)
return has1 && !has2 && !has3 && !has4
}
func (h Play) HighCard() (rune, int) {
var i int
pairs := make(Pairs, 5)
cnt := h.game.Counts(h.hand)
for r, c := range cnt {
pairs[i].c = c
pairs[i].r = r
pairs[i].o = h.game.cardOrder[r]
i++
}
sort.Sort(sort.Reverse(pairs))
value := 0
for i, r := range h.hand {
if r == 0 {
continue
}
value |= h.game.cardOrder[r] << (4 * (4 - i))
}
return pairs[0].r, value
}
type Pairs []struct {
r rune
c int
o int
}
func (p Pairs) Len() int { return len(p) }
func (p Pairs) Less(i, j int) bool {
if p[i].c == p[j].c {
return p[i].o < p[j].o
}
return p[i].c < p[j].c
}
func (p Pairs) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
type Plays []Play
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) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (g *Game) Counts(cards []rune) map[rune]int {
m := make(map[rune]int, len(g.cardOrder))
for _, c := range cards {
m[c]++
}
if g.wildCard != 0 && m[g.wildCard] > 0 {
var maxK rune
var maxV int
for k, v := range m {
if k != g.wildCard && v > maxV {
maxK, maxV = k, v
}
}
if maxK != 0 {
m[maxK] += m[g.wildCard]
delete(m, g.wildCard)
}
}
return m
}
func (g *Game) hasSame(cards []rune) (has1, has2, has3, has4, has5 bool) {
cnt := g.Counts(cards)
for _, c := range cnt {
switch c {
case 1:
has1 = true
case 2:
has2 = true
case 3:
has3 = true
case 4:
has4 = true
case 5:
has5 = true
}
}
return
}
func (g *Game) pairs(cards []rune) int {
pairs := 0
for _, n := range g.Counts(cards) {
if n == 2 {
pairs++
}
}
return pairs
}

View File

@@ -0,0 +1,74 @@
package main
import (
"bufio"
"bytes"
"fmt"
"testing"
_ "embed"
"github.com/matryer/is"
)
// AKQJT98765432
// dcba987654321
//go:embed example.txt
var example []byte
//go:embed input.txt
var input []byte
func TestHands(t *testing.T) {
is := is.New(t)
var game Game
game.cardOrder = getOrder(cardTypes1)
h := Play{0, []rune("AAA23"), &game}
is.Equal(h.HandType(), "3K-A")
h = Play{0, []rune("JJJJJ"), &game}
is.Equal(h.HandType(), "5K-J")
is.Equal(fmt.Sprintf("%x", h.HandStrength()), "7aaaaa")
h = Play{0, []rune("KKKKJ"), &game}
is.Equal(h.HandType(), "4K-K")
is.Equal(fmt.Sprintf("%x", h.HandStrength()), "6cccca")
h = Play{0, []rune("QQQJA"), &game}
is.Equal(h.HandType(), "3K-Q")
is.Equal(fmt.Sprintf("%x", h.HandStrength()), "4bbbad")
}
func TestPower(t *testing.T) {
for i := 1; i <= 13; i++ {
for j := 100; j < 800; j += 100 {
t.Log(i, j, i+j)
}
}
}
func TestExample(t *testing.T) {
is := is.New(t)
scan := bufio.NewScanner(bytes.NewReader(example))
r, err := run(scan)
is.NoErr(err)
is.Equal(r.valuePT1, uint64(6440))
is.Equal(r.valuePT2, uint64(5905))
}
func TestSolution(t *testing.T) {
is := is.New(t)
scan := bufio.NewScanner(bytes.NewReader(input))
r, err := run(scan)
is.NoErr(err)
t.Log("score1", r.valuePT1)
is.Equal(r.valuePT1, uint64(248559379))
t.Log("score2", r.valuePT2)
is.Equal(r.valuePT2, uint64(249631254))
}