2023: Day 7
parent
5b38cb0f30
commit
15985840a4
|
@ -1,11 +1,284 @@
|
||||||
package day_07
|
package day_07
|
||||||
|
|
||||||
type Day struct{}
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.rpjosh.de/RPJosh/go-logger"
|
||||||
|
"rpjosh.de/adventOfCode/pkg/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Day struct {
|
||||||
|
hands map[byte]int
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Day) Part1(in string) string {
|
func (d *Day) Part1(in string) string {
|
||||||
return ""
|
inSplit := strings.Split(in, "\n")
|
||||||
|
//inSplit := []string{"23332 246"}
|
||||||
|
|
||||||
|
hands := map[byte]int{
|
||||||
|
'A': 0,
|
||||||
|
'K': 1,
|
||||||
|
'Q': 2,
|
||||||
|
'J': 3,
|
||||||
|
'T': 4,
|
||||||
|
'9': 5,
|
||||||
|
'8': 6,
|
||||||
|
'7': 7,
|
||||||
|
'6': 8,
|
||||||
|
'5': 9,
|
||||||
|
'4': 10,
|
||||||
|
'3': 11,
|
||||||
|
'2': 12,
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.SliceStable(inSplit, func(a, b int) bool {
|
||||||
|
aVal := getTypeOrders(strings.Split(inSplit[a], " ")[0])
|
||||||
|
bVal := getTypeOrders(strings.Split(inSplit[b], " ")[0])
|
||||||
|
|
||||||
|
if aVal > bVal {
|
||||||
|
return true
|
||||||
|
} else if aVal == bVal {
|
||||||
|
// Get first number
|
||||||
|
aS := strings.Split(inSplit[a], " ")[0]
|
||||||
|
bS := strings.Split(inSplit[b], " ")[0]
|
||||||
|
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
if hands[aS[i]] > hands[bS[i]] {
|
||||||
|
return true
|
||||||
|
} else if hands[aS[i]] == hands[bS[i]] {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.Error("Two values are the same. What to do?")
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
rtc := 0
|
||||||
|
for i, val := range inSplit {
|
||||||
|
if val == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
logger.Debug("%s == %d", val, getTypeOrders(strings.Split(val, " ")[0]))
|
||||||
|
rtc += (i + 1) * utils.ToInt(strings.Split(val, " ")[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%d", rtc)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Values struct {
|
||||||
|
val rune
|
||||||
|
count int
|
||||||
|
positions string
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTypeOrders(numbers string) int {
|
||||||
|
|
||||||
|
if len(numbers) < 4 {
|
||||||
|
logger.Error("Received invalid input: %q", numbers)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Five in a row
|
||||||
|
if strings.Count(numbers, string(numbers[0])) == 5 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Four in a row
|
||||||
|
if strings.Count(numbers, string(numbers[0])) == 4 || strings.Count(numbers, string(numbers[1])) == 4 {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
// Prepare values
|
||||||
|
numbersSorted := utils.SortRunes(numbers)
|
||||||
|
runeMap := map[rune]int{}
|
||||||
|
|
||||||
|
// Three of a kind or full house
|
||||||
|
vals := make([]Values, 3)
|
||||||
|
for i, val := range numbers {
|
||||||
|
if vals[0].val == val {
|
||||||
|
vals[0].count += 1
|
||||||
|
vals[0].positions += fmt.Sprintf("%d", i)
|
||||||
|
} else if vals[1].val == val {
|
||||||
|
vals[1].count += 1
|
||||||
|
vals[1].positions += fmt.Sprintf("%d", i)
|
||||||
|
} else if vals[2].val == val {
|
||||||
|
vals[2].count += 1
|
||||||
|
vals[2].positions += fmt.Sprintf("%d", i)
|
||||||
|
} else if vals[0].count == 0 {
|
||||||
|
vals[0].val = val
|
||||||
|
vals[0].count = 1
|
||||||
|
vals[0].positions += fmt.Sprintf("%d", i)
|
||||||
|
} else if vals[1].count == 0 {
|
||||||
|
vals[1].val = val
|
||||||
|
vals[1].count = 1
|
||||||
|
vals[1].positions += fmt.Sprintf("%d", i)
|
||||||
|
} else if vals[2].count == 0 {
|
||||||
|
vals[2].val = val
|
||||||
|
vals[2].count = 1
|
||||||
|
vals[2].positions += fmt.Sprintf("%d", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We need three same kinds
|
||||||
|
threeValid := false
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
if vals[i].count == 3 {
|
||||||
|
threeValid = true
|
||||||
|
/*
|
||||||
|
//logger.Debug("==== Having three")
|
||||||
|
// In order
|
||||||
|
lastVal := int(vals[i].positions[0])
|
||||||
|
for _, r := range vals[i].positions[1:] {
|
||||||
|
//logger.Debug("order: %d %d", lastVal, r-1)
|
||||||
|
if lastVal == int(r)-1 {
|
||||||
|
threeValid = true
|
||||||
|
lastVal = int(r)
|
||||||
|
} else {
|
||||||
|
threeValid = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if threeValid && ((vals[0].count == 3 && vals[1].count == 1) || (vals[1].count == 3 && vals[0].count == 1) || vals[2].count == 3 && vals[0].count == 1) {
|
||||||
|
return 4
|
||||||
|
} else if threeValid && (vals[1].count == 2 || vals[0].count == 2 || vals[3].count == 2) {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
|
||||||
|
// Two pair
|
||||||
|
runeMap = map[rune]int{}
|
||||||
|
for _, val := range numbersSorted {
|
||||||
|
runeMap[val] += 1
|
||||||
|
}
|
||||||
|
pairs := 0
|
||||||
|
for _, val := range runeMap {
|
||||||
|
if val == 2 {
|
||||||
|
pairs += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Two pairs
|
||||||
|
if pairs == 2 {
|
||||||
|
return 5
|
||||||
|
}
|
||||||
|
|
||||||
|
// One pair
|
||||||
|
if pairs == 1 {
|
||||||
|
return 6
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we need to distinct?
|
||||||
|
areDistinct := true
|
||||||
|
for _, val := range runeMap {
|
||||||
|
if val > 1 {
|
||||||
|
logger.Fatal("Values are not distinct. That's a logic error: %q", numbers)
|
||||||
|
areDistinct = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if areDistinct {
|
||||||
|
return 7
|
||||||
|
}
|
||||||
|
|
||||||
|
return 10
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day) GetBestJokerValue(numbers string) string {
|
||||||
|
// Nothing to do here
|
||||||
|
if !strings.Contains(numbers, "J") {
|
||||||
|
return numbers
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through every 'J'. A 'J' can occur twice -> Brute force with recursion :)
|
||||||
|
bestNumbers := ""
|
||||||
|
lastValue := 20
|
||||||
|
for k := range d.hands {
|
||||||
|
// Not allowed - endless loop!
|
||||||
|
if k == 'J' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
lastJ := strings.LastIndex(numbers, "J")
|
||||||
|
numbersNew := utils.ReplaceCharacterInString(numbers, string(k), lastJ)
|
||||||
|
|
||||||
|
// Replace any other 'J' value
|
||||||
|
numbersNew = d.GetBestJokerValue(numbersNew)
|
||||||
|
|
||||||
|
// Test the value
|
||||||
|
result := getTypeOrders(numbersNew)
|
||||||
|
|
||||||
|
// Better result
|
||||||
|
if result < lastValue {
|
||||||
|
lastValue = result
|
||||||
|
bestNumbers = numbersNew
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bestNumbers
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Day) Part2(in string) string {
|
func (d *Day) Part2(in string) string {
|
||||||
return ""
|
inSplit := strings.Split(in, "\n")
|
||||||
|
//inSplit := []string{"23332 246"}
|
||||||
|
|
||||||
|
d.hands = map[byte]int{
|
||||||
|
'A': 0,
|
||||||
|
'K': 1,
|
||||||
|
'Q': 2,
|
||||||
|
'T': 4,
|
||||||
|
'9': 5,
|
||||||
|
'8': 6,
|
||||||
|
'7': 7,
|
||||||
|
'6': 8,
|
||||||
|
'5': 9,
|
||||||
|
'4': 10,
|
||||||
|
'3': 11,
|
||||||
|
'2': 12,
|
||||||
|
'J': 13,
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.SliceStable(inSplit, func(a, b int) bool {
|
||||||
|
aVal := getTypeOrders(d.GetBestJokerValue(strings.Split(inSplit[a], " ")[0]))
|
||||||
|
bVal := getTypeOrders(d.GetBestJokerValue(strings.Split(inSplit[b], " ")[0]))
|
||||||
|
|
||||||
|
if aVal > bVal {
|
||||||
|
return true
|
||||||
|
} else if aVal == bVal {
|
||||||
|
// Get first number
|
||||||
|
aS := strings.Split(inSplit[a], " ")[0]
|
||||||
|
bS := strings.Split(inSplit[b], " ")[0]
|
||||||
|
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
if d.hands[aS[i]] > d.hands[bS[i]] {
|
||||||
|
return true
|
||||||
|
} else if d.hands[aS[i]] == d.hands[bS[i]] {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.Error("Two values are the same. What to do?")
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
rtc := 0
|
||||||
|
for i, val := range inSplit {
|
||||||
|
if val == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
logger.Debug("%s == %d", val, getTypeOrders(strings.Split(val, " ")[0]))
|
||||||
|
rtc += (i + 1) * utils.ToInt(strings.Split(val, " ")[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%d", rtc)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,10 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.rpjosh.de/RPJosh/go-logger"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Copies the given string to the clipboard.
|
// Copies the given string to the clipboard.
|
||||||
|
@ -89,7 +88,7 @@ func PrintError(format string, a ...any) {
|
||||||
func ToInt(val string) int {
|
func ToInt(val string) int {
|
||||||
value, err := strconv.Atoi(val)
|
value, err := strconv.Atoi(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal("Failed to convert %q to a number: %s", val, err)
|
panic(fmt.Sprintf("Failed to convert %q to a number: %s", val, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
@ -135,3 +134,19 @@ func ConvertArrayToInt(values []string) []int {
|
||||||
|
|
||||||
return rtc
|
return rtc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SortRunes sorts a string based on the rune value
|
||||||
|
// of every character
|
||||||
|
func SortRunes(value string) string {
|
||||||
|
runeSlice := []rune(value)
|
||||||
|
sort.Slice(runeSlice, func(i, j int) bool {
|
||||||
|
return runeSlice[i] < runeSlice[j]
|
||||||
|
})
|
||||||
|
return string(runeSlice)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReplaceCharacterInString replaces the character at the given index with
|
||||||
|
// the provided value
|
||||||
|
func ReplaceCharacterInString(str, replace string, index int) string {
|
||||||
|
return str[:index] + replace + str[index+1:]
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue