2023 day 7
This commit is contained in:
parent
64a4dc3cf9
commit
eec219eeda
5
2023/07/example.txt
Normal file
5
2023/07/example.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
32T3K 765
|
||||||
|
T55J5 684
|
||||||
|
KK677 28
|
||||||
|
KTJJT 220
|
||||||
|
QQQJA 483
|
3
2023/07/go.mod
Normal file
3
2023/07/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module git.tristans.cloud/aoc/2023/07
|
||||||
|
|
||||||
|
go 1.21.4
|
1000
2023/07/input.txt
Normal file
1000
2023/07/input.txt
Normal file
File diff suppressed because it is too large
Load diff
125
2023/07/part1/main.go
Normal file
125
2023/07/part1/main.go
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"bufio"
|
||||||
|
"strings"
|
||||||
|
"slices"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
reader := bufio.NewReader(os.Stdin);
|
||||||
|
hands := [][2]string{}
|
||||||
|
for {
|
||||||
|
text, err := reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
strs := strings.Split(strings.Trim(text, "\n"), " ")
|
||||||
|
hands = append(hands, [2]string{strs[0], strs[1]});
|
||||||
|
}
|
||||||
|
slices.SortFunc(hands, func(a, b [2]string) int {
|
||||||
|
return Wins(a[0], b[0])
|
||||||
|
})
|
||||||
|
total := 0
|
||||||
|
for i, hand := range hands {
|
||||||
|
rank := i+1
|
||||||
|
bid, _ := strconv.Atoi(hand[1])
|
||||||
|
println(hand[0], rank, bid)
|
||||||
|
total += rank * bid
|
||||||
|
}
|
||||||
|
println(total)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func IsFiveOfAKind(hand string) (bool) {
|
||||||
|
return hand[0] == hand[1] && hand[0] == hand[2] && hand[0] == hand[3] && hand[0] == hand[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsFourOfAKind(hand string) (bool) {
|
||||||
|
|
||||||
|
cardMap := map[rune]int{}
|
||||||
|
for _, card := range hand {
|
||||||
|
cardMap[card] ++;
|
||||||
|
if cardMap[card] == 4 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func HasTriple(hand string) (bool) {
|
||||||
|
|
||||||
|
cardMap := map[rune]int{}
|
||||||
|
for _, card := range hand {
|
||||||
|
cardMap[card] ++;
|
||||||
|
}
|
||||||
|
for _,value := range cardMap {
|
||||||
|
if value == 3 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func PairCount(hand string) (int) {
|
||||||
|
|
||||||
|
cardMap := map[rune]int{}
|
||||||
|
for _, card := range hand {
|
||||||
|
cardMap[card] ++;
|
||||||
|
}
|
||||||
|
count := 0;
|
||||||
|
for _,value := range cardMap {
|
||||||
|
if value == 2 {
|
||||||
|
count ++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsFullHouse(hand string) (bool) {
|
||||||
|
return PairCount(hand) == 1 && HasTriple(hand)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetType(hand string) int {
|
||||||
|
pc := 0;
|
||||||
|
if IsFiveOfAKind(hand) {
|
||||||
|
return 6
|
||||||
|
} else if IsFourOfAKind(hand) {
|
||||||
|
return 5
|
||||||
|
} else if IsFullHouse(hand) {
|
||||||
|
return 4
|
||||||
|
} else if HasTriple(hand) {
|
||||||
|
return 3
|
||||||
|
} else if pc = PairCount(hand); pc == 2 {
|
||||||
|
return 2
|
||||||
|
} else if pc == 1 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func Wins(left string, right string) (int) {
|
||||||
|
leftType := GetType(left)
|
||||||
|
rightType := GetType(right)
|
||||||
|
if leftType == rightType {
|
||||||
|
return GetValue(left) - GetValue(right)
|
||||||
|
}
|
||||||
|
return leftType - rightType
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetValue(hand string) (int) {
|
||||||
|
cardValues := map[rune]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, '1': 1}
|
||||||
|
value := 0
|
||||||
|
for _, card := range hand {
|
||||||
|
value *= 14
|
||||||
|
value += cardValues[card]-1
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
116
2023/07/part1/main_test.go
Normal file
116
2023/07/part1/main_test.go
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIsFiveOfAKind(t *testing.T) {
|
||||||
|
if IsFiveOfAKind("AAAAQ") {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if !IsFiveOfAKind("AAAAA") {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsFourOfAKind(t *testing.T) {
|
||||||
|
if !IsFourOfAKind("AAAAQ") {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if IsFourOfAKind("AAAQQ") {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsFullHouse(t *testing.T) {
|
||||||
|
if !IsFullHouse("AAAQQ") {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if IsFullHouse("AAKQQ") {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if IsFullHouse("AAAAA") {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasTriple(t *testing.T) {
|
||||||
|
if HasTriple("AAKQQ") {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if HasTriple("AAAAQ") {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if !HasTriple("AAAQQ") {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPairCount(t *testing.T) {
|
||||||
|
if PairCount("AAKQQ") != 2 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if PairCount("AQKQA") != 2 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if PairCount("12345") != 0 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetType(t *testing.T) {
|
||||||
|
pass := GetType("AAAAA") == 6 &&
|
||||||
|
GetType("AAKAA") == 5 &&
|
||||||
|
GetType("AAKAK") == 4 &&
|
||||||
|
GetType("AAAKQ") == 3 &&
|
||||||
|
GetType("AAKK2") == 2 &&
|
||||||
|
GetType("AAK12") == 1 &&
|
||||||
|
GetType("12345") == 0
|
||||||
|
|
||||||
|
if !pass {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWins(t *testing.T) {
|
||||||
|
if Wins("AAAAA", "AAAA1") < 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
if Wins("AAAA1", "AAA11") < 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
if Wins("AAA11", "AAA12") < 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
if Wins("AAA12", "AA123") < 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
if Wins("AA123", "A1234") < 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
if Wins("A1234", "1234A") < 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
if Wins("AAAAK", "KAAAA") < 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
if Wins("12212", "22112") > 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
if Wins("77788", "77888") > 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetValue(t *testing.T) {
|
||||||
|
if GetValue("A") != 13 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if GetValue("AA") != 13*14 + 13 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if GetValue("KA") != 12*14 + 13 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
160
2023/07/part2/main.go
Normal file
160
2023/07/part2/main.go
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"bufio"
|
||||||
|
"strings"
|
||||||
|
"slices"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
reader := bufio.NewReader(os.Stdin);
|
||||||
|
hands := [][2]string{}
|
||||||
|
for {
|
||||||
|
text, err := reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
strs := strings.Split(strings.Trim(text, "\n"), " ")
|
||||||
|
hands = append(hands, [2]string{strs[0], strs[1]});
|
||||||
|
}
|
||||||
|
slices.SortFunc(hands, func(a, b [2]string) int {
|
||||||
|
return Wins(a[0], b[0])
|
||||||
|
})
|
||||||
|
total := 0
|
||||||
|
for i, hand := range hands {
|
||||||
|
rank := i+1
|
||||||
|
bid, _ := strconv.Atoi(hand[1])
|
||||||
|
println(hand[0], GetType(hand[0]), bid)
|
||||||
|
total += rank * bid
|
||||||
|
}
|
||||||
|
println(total)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func IsFiveOfAKind(cardMap CardMap) (bool) {
|
||||||
|
|
||||||
|
for suit, value := range cardMap {
|
||||||
|
jokers := cardMap['J']
|
||||||
|
if suit == 'J' {
|
||||||
|
jokers = 0
|
||||||
|
}
|
||||||
|
if value + jokers == 5 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsFourOfAKind(cardMap CardMap) (bool) {
|
||||||
|
for suit,value := range cardMap {
|
||||||
|
jokers := cardMap['J']
|
||||||
|
if suit == 'J' {
|
||||||
|
jokers = 0
|
||||||
|
}
|
||||||
|
if value + jokers == 4 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func HasTriple(cardMap CardMap) (bool) {
|
||||||
|
for suit,value := range cardMap {
|
||||||
|
jokers := cardMap['J']
|
||||||
|
if suit == 'J' {
|
||||||
|
jokers = 0
|
||||||
|
}
|
||||||
|
if value + jokers == 3 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func NoJokerPairCount(cardMap CardMap) (int) {
|
||||||
|
count := 0;
|
||||||
|
for _,value := range cardMap {
|
||||||
|
if value == 2 {
|
||||||
|
count ++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
func PairCount(cardMap CardMap) (int) {
|
||||||
|
count := 0;
|
||||||
|
jokers := cardMap['J']
|
||||||
|
for suit,value := range cardMap {
|
||||||
|
if suit == 'J' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if value == 2 {
|
||||||
|
count ++
|
||||||
|
} else if jokers > 0 && value == 1 {
|
||||||
|
count ++
|
||||||
|
jokers --
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsFullHouse(cardMap CardMap) (bool) {
|
||||||
|
if cardMap['J'] == 1 {
|
||||||
|
return NoJokerPairCount(cardMap) == 2
|
||||||
|
} else if cardMap['J'] == 0 {
|
||||||
|
return PairCount(cardMap) == 1 && HasTriple(cardMap)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetType(hand string) int {
|
||||||
|
cardMap := GetCardMap(hand)
|
||||||
|
if IsFiveOfAKind(cardMap) {
|
||||||
|
return 6
|
||||||
|
} else if IsFourOfAKind(cardMap) {
|
||||||
|
return 5
|
||||||
|
} else if IsFullHouse(cardMap) {
|
||||||
|
return 4
|
||||||
|
} else if HasTriple(cardMap) {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
return PairCount(cardMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Wins(left string, right string) (int) {
|
||||||
|
leftType := GetType(left)
|
||||||
|
rightType := GetType(right)
|
||||||
|
if leftType == rightType {
|
||||||
|
return GetValue(left) - GetValue(right)
|
||||||
|
}
|
||||||
|
return leftType - rightType
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetValue(hand string) (int) {
|
||||||
|
cardValues := map[rune]int{'A': 13, 'K': 12, 'Q': 11, 'T': 10, '9':9, '8':8, '7':7, '6':6, '5':5, '4':4, '3':3, '2': 2, 'J': 1}
|
||||||
|
value := 0
|
||||||
|
for _, card := range hand {
|
||||||
|
value *= 14
|
||||||
|
value += cardValues[card]-1
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
type CardMap = map[rune]int
|
||||||
|
|
||||||
|
func GetCardMap(hand string) (cardMap CardMap) {
|
||||||
|
cardMap = map[rune]int{};
|
||||||
|
for _, card := range hand {
|
||||||
|
cardMap[card] ++;
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
161
2023/07/part2/main_test.go
Normal file
161
2023/07/part2/main_test.go
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIsFiveOfAKind(t *testing.T) {
|
||||||
|
if IsFiveOfAKind(GetCardMap("AAAAQ")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if !IsFiveOfAKind(GetCardMap("AAAAA")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if !IsFiveOfAKind(GetCardMap("AAJAA")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if !IsFiveOfAKind(GetCardMap("AAJJJ")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsFourOfAKind(t *testing.T) {
|
||||||
|
if !IsFourOfAKind(GetCardMap("AAAAQ")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if IsFourOfAKind(GetCardMap("AAAQQ")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if !IsFourOfAKind(GetCardMap("AAAJQ")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if !IsFourOfAKind(GetCardMap("AJJJQ")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsFullHouse(t *testing.T) {
|
||||||
|
if !IsFullHouse(GetCardMap("AAAQQ")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if IsFullHouse(GetCardMap("AAKQQ")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if IsFullHouse(GetCardMap("AAAAA")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if !IsFullHouse(GetCardMap("AAJQQ")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if !IsFullHouse(GetCardMap("33J99")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if IsFullHouse(GetCardMap("JJ32A")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasTriple(t *testing.T) {
|
||||||
|
if HasTriple(GetCardMap("AAKQQ")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if HasTriple(GetCardMap("AAAAQ")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if !HasTriple(GetCardMap("AAAQQ")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if !HasTriple(GetCardMap("AAJQQ")) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJokerPairCount(t *testing.T) {
|
||||||
|
if PairCount(GetCardMap("AAKQQ")) != 2 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if PairCount(GetCardMap("AQKQA")) != 2 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if PairCount(GetCardMap("12345")) != 0 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if PairCount(GetCardMap("123J5")) != 1 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPairCount(t *testing.T) {
|
||||||
|
if NoJokerPairCount(GetCardMap("AAKQQ")) != 2 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if NoJokerPairCount(GetCardMap("AQKQA")) != 2 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if NoJokerPairCount(GetCardMap("12345")) != 0 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if NoJokerPairCount(GetCardMap("123J5")) != 0 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetType(t *testing.T) {
|
||||||
|
pass := GetType("AAAAA") == 6 &&
|
||||||
|
GetType("AAKAA") == 5 &&
|
||||||
|
GetType("AAKAK") == 4 &&
|
||||||
|
GetType("AAAKQ") == 3 &&
|
||||||
|
GetType("AAKK2") == 2 &&
|
||||||
|
GetType("AAK12") == 1 &&
|
||||||
|
GetType("12345") == 0
|
||||||
|
|
||||||
|
if !pass {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWins(t *testing.T) {
|
||||||
|
if Wins("AAAAA", "AAAA1") < 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
if Wins("AAAA1", "AAA11") < 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
if Wins("AAA11", "AAA12") < 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
if Wins("AAA12", "AA123") < 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
if Wins("AA123", "A1234") < 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
if Wins("A1234", "1234A") < 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
if Wins("AAAAK", "KAAAA") < 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
if Wins("12212", "22112") > 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
if Wins("77788", "77888") > 0 {
|
||||||
|
t.Fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetValue(t *testing.T) {
|
||||||
|
if GetValue("A") != 12 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if GetValue("AA") != 12*14 + 12 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if GetValue("KA") != 11*14 + 12 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if GetValue("JA") != 0*14 + 12 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue