mirror of
https://github.com/Threnklyn/advent-of-code-go.git
synced 2026-05-18 19:13:27 +02:00
day07 poker scoring
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"flag"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/alexchao26/advent-of-code-go/cast"
|
||||
"github.com/alexchao26/advent-of-code-go/util"
|
||||
)
|
||||
|
||||
//go:embed input.txt
|
||||
var input string
|
||||
|
||||
func init() {
|
||||
// do this in init (not main) so test file has same input
|
||||
input = strings.TrimRight(input, "\n")
|
||||
if len(input) == 0 {
|
||||
panic("empty input.txt file")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
var part int
|
||||
flag.IntVar(&part, "part", 1, "part 1 or 2")
|
||||
flag.Parse()
|
||||
fmt.Println("Running part", part)
|
||||
|
||||
ans := part1(input)
|
||||
util.CopyToClipboard(fmt.Sprintf("%v", ans))
|
||||
fmt.Println("Output:", ans)
|
||||
}
|
||||
|
||||
func part1(input string) int {
|
||||
allPlayers := parseInput(input)
|
||||
|
||||
sort.Sort(allPlayers)
|
||||
|
||||
var ans int
|
||||
for i, player := range allPlayers {
|
||||
ans += int(player.bid) * int(i+1)
|
||||
}
|
||||
return ans
|
||||
}
|
||||
|
||||
type player struct {
|
||||
hand string
|
||||
bid int
|
||||
|
||||
handTypeScore int
|
||||
}
|
||||
|
||||
func parseInput(input string) (ans SortablePlayers) {
|
||||
for _, line := range strings.Split(input, "\n") {
|
||||
handAndBid := strings.Split(line, " ")
|
||||
pl := player{
|
||||
hand: handAndBid[0],
|
||||
bid: cast.ToInt(handAndBid[1]),
|
||||
}
|
||||
pl.handTypeScore = scoreHandType(pl.hand)
|
||||
ans = append(ans, pl)
|
||||
}
|
||||
return ans
|
||||
}
|
||||
|
||||
/* point assignments:
|
||||
five of a kind -> 7
|
||||
four of a kind -> 6
|
||||
full house -> 5
|
||||
three of a kind -> 4
|
||||
two pair -> 3
|
||||
one pair -> 2
|
||||
high card -> 1
|
||||
*/
|
||||
|
||||
func scoreHandType(hand string) int {
|
||||
counts := map[string]int{}
|
||||
for _, card := range strings.Split(hand, "") {
|
||||
counts[card]++
|
||||
}
|
||||
|
||||
// high card
|
||||
if len(counts) == 5 {
|
||||
return 1
|
||||
}
|
||||
// one pair
|
||||
if len(counts) == 4 {
|
||||
return 2
|
||||
}
|
||||
|
||||
if len(counts) == 3 {
|
||||
// either two pair or three of a kind
|
||||
for _, ct := range counts {
|
||||
if ct == 3 {
|
||||
return 4 // 3 of a kind, 3 1 1
|
||||
}
|
||||
}
|
||||
return 3 // two pair, 2 2 1
|
||||
}
|
||||
|
||||
if len(counts) == 2 {
|
||||
// full house (3 2) or four of a kind (4 1)
|
||||
for _, ct := range counts {
|
||||
if ct == 3 {
|
||||
return 5
|
||||
}
|
||||
}
|
||||
return 6
|
||||
}
|
||||
|
||||
if len(counts) == 1 {
|
||||
return 7
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("error scoring hand: %+v", hand))
|
||||
}
|
||||
|
||||
type SortablePlayers []player
|
||||
|
||||
func (ps SortablePlayers) Len() int { return len(ps) }
|
||||
func (ps SortablePlayers) Swap(i, j int) {
|
||||
ps[i], ps[j] = ps[j], ps[i]
|
||||
}
|
||||
func (ps SortablePlayers) Less(i, j int) bool {
|
||||
iTypeScore := ps[i].handTypeScore
|
||||
jTypeScore := ps[j].handTypeScore
|
||||
|
||||
if iTypeScore == jTypeScore {
|
||||
// higher score goes to end of ps slice
|
||||
return !doesPlayer1WinTiebreak(ps[i], ps[j])
|
||||
}
|
||||
return iTypeScore < jTypeScore
|
||||
}
|
||||
|
||||
var cardValuesMap = map[string]int{
|
||||
"A": 14,
|
||||
"K": 13,
|
||||
"Q": 12,
|
||||
"J": 11,
|
||||
"T": 10,
|
||||
"9": 9,
|
||||
"8": 8,
|
||||
"7": 7,
|
||||
"6": 6,
|
||||
"5": 5,
|
||||
"4": 4,
|
||||
"3": 3,
|
||||
"2": 2,
|
||||
}
|
||||
|
||||
// returns true if player1 wins the tie break
|
||||
func doesPlayer1WinTiebreak(p1, p2 player) bool {
|
||||
if p1.handTypeScore != p2.handTypeScore {
|
||||
panic("p1 and p2 scores do not have the same level hand")
|
||||
}
|
||||
p1Cards := strings.Split(p1.hand, "")
|
||||
p2Cards := strings.Split(p2.hand, "")
|
||||
for i := 0; i < len(p1Cards); i++ {
|
||||
if cardValuesMap[p1Cards[i]] > cardValuesMap[p2Cards[i]] {
|
||||
return true
|
||||
} else if cardValuesMap[p1Cards[i]] < cardValuesMap[p2Cards[i]] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
panic("not expecting to have two matching hands")
|
||||
}
|
||||
Reference in New Issue
Block a user