195 lines
3.3 KiB
Go
195 lines
3.3 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
|
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
|
)
|
|
|
|
var p2 bool
|
|
|
|
// 251515138 is too high
|
|
|
|
func main() {
|
|
inp := h.StdinToStringSlice()
|
|
part1(inp)
|
|
fmt.Println()
|
|
part2(inp)
|
|
}
|
|
|
|
func part1(input []string) {
|
|
var hands []*Hand
|
|
for i := range input {
|
|
hands = append(hands, NewHand(input[i]))
|
|
}
|
|
|
|
sort.Sort(sort.Reverse(ByRank(hands)))
|
|
|
|
var total int
|
|
for i := range hands {
|
|
total += hands[i].bid * (i + 1)
|
|
}
|
|
fmt.Println()
|
|
fmt.Println("# Part 1")
|
|
fmt.Println(total)
|
|
}
|
|
|
|
func part2(input []string) {
|
|
p2 = true
|
|
var hands []*Hand
|
|
for i := range input {
|
|
hands = append(hands, NewHand(input[i]))
|
|
}
|
|
|
|
sort.Sort(sort.Reverse(ByRank(hands)))
|
|
|
|
var total int
|
|
for i := range hands {
|
|
total += hands[i].bid * (i + 1)
|
|
}
|
|
fmt.Println()
|
|
fmt.Println("# Part 2")
|
|
fmt.Println(total)
|
|
}
|
|
|
|
type Hand struct {
|
|
raw string
|
|
cards []byte
|
|
bid int
|
|
handType int
|
|
cardMap map[byte]int
|
|
}
|
|
|
|
const (
|
|
TypeFiveOfKind = 6
|
|
TypeFourOfKind = 5
|
|
TypeFullHouse = 4
|
|
TypeThreeOfKind = 3
|
|
TypeTwoPair = 2
|
|
TypeOnePair = 1
|
|
TypeHighCard = 0
|
|
)
|
|
|
|
var typeToString = map[int]string{
|
|
TypeFiveOfKind: "Five of a Kind",
|
|
TypeFourOfKind: "Four of a Kind",
|
|
TypeFullHouse: "Full House",
|
|
TypeThreeOfKind: "Three of a Kind",
|
|
TypeTwoPair: "Two Pair",
|
|
TypeOnePair: "One Pair",
|
|
TypeHighCard: "High Card",
|
|
}
|
|
|
|
func cardToValue(b byte) int {
|
|
switch b {
|
|
case 'T':
|
|
return 10
|
|
case 'J':
|
|
if p2 {
|
|
return 1
|
|
}
|
|
return 11
|
|
case 'Q':
|
|
return 12
|
|
case 'K':
|
|
return 13
|
|
case 'A':
|
|
return 14
|
|
}
|
|
return int(b - '0')
|
|
}
|
|
|
|
func NewHand(input string) *Hand {
|
|
hand := Hand{raw: input}
|
|
i := 0
|
|
for i = range input {
|
|
if input[i] == ' ' {
|
|
break
|
|
}
|
|
hand.cards = append(hand.cards, input[i])
|
|
}
|
|
hand.bid = h.Atoi(input[i:])
|
|
hand.handType = hand.findType()
|
|
return &hand
|
|
}
|
|
|
|
func (hand *Hand) findType() int {
|
|
hand.cardMap = make(map[byte]int)
|
|
for i := range hand.cards {
|
|
hand.cardMap[hand.cards[i]]++
|
|
}
|
|
if p2 {
|
|
if jCnt, ok := hand.cardMap['J']; ok {
|
|
var c byte
|
|
cCnt := h.MIN_INT
|
|
for k, v := range hand.cardMap {
|
|
if k != 'J' {
|
|
if v > cCnt {
|
|
cCnt = v
|
|
c = k
|
|
}
|
|
}
|
|
}
|
|
hand.cardMap[c] = hand.cardMap[c] + jCnt
|
|
delete(hand.cardMap, 'J')
|
|
}
|
|
}
|
|
max := h.MIN_INT
|
|
for _, v := range hand.cardMap {
|
|
if v > max {
|
|
max = v
|
|
}
|
|
}
|
|
switch len(hand.cardMap) {
|
|
case 5:
|
|
return TypeHighCard
|
|
case 4:
|
|
return TypeOnePair
|
|
case 3:
|
|
if max == 3 {
|
|
return TypeThreeOfKind
|
|
}
|
|
return TypeTwoPair
|
|
case 2:
|
|
if max == 3 {
|
|
return TypeFullHouse
|
|
}
|
|
return TypeFourOfKind
|
|
default:
|
|
return TypeFiveOfKind
|
|
}
|
|
}
|
|
|
|
func (hand Hand) String() string {
|
|
return fmt.Sprintf("%s %d", string(hand.cards), hand.bid)
|
|
}
|
|
|
|
type ByRank []*Hand
|
|
|
|
func (rank ByRank) Len() int { return len(rank) }
|
|
func (rank ByRank) Swap(i, j int) { rank[i], rank[j] = rank[j], rank[i] }
|
|
func (rank ByRank) Less(i, j int) bool {
|
|
if rank[i].handType > rank[j].handType {
|
|
return true
|
|
} else if rank[j].handType > rank[i].handType {
|
|
return false
|
|
}
|
|
for k := range rank[i].cards {
|
|
cmp := cmpCards(rank[i].cards[k], rank[j].cards[k])
|
|
if cmp != 0 {
|
|
return cmp == 1
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func cmpCards(c1, c2 byte) int {
|
|
if cardToValue(c1) > cardToValue(c2) {
|
|
return 1
|
|
} else if cardToValue(c1) < cardToValue(c2) {
|
|
return -1
|
|
}
|
|
return 0
|
|
}
|