2023: Day 4 and 5

master
Jonas Letzbor 2023-12-05 20:43:44 +01:00
parent 55fa420ed3
commit c20be6cf78
Signed by: RPJosh
GPG Key ID: 46D72F589702E55A
3 changed files with 281 additions and 4 deletions

View File

@ -1,11 +1,98 @@
package day_04 package day_04
import (
"fmt"
"regexp"
"strings"
"git.rpjosh.de/RPJosh/go-logger"
)
type Day struct{} type Day struct{}
func (d *Day) Part1(in string) string { func (d *Day) Part1(in string) string {
return ""
// Regex to get all numbers
numberRegex := regexp.MustCompile(`\w*`)
sum := 0
for _, val := range strings.Split(in, "\n") {
if val == "" {
continue
}
// Extract card numbers
numbers := strings.Split(val, ":")[1]
winning := strings.Split(numbers, "|")[0]
elfs := strings.Split(numbers, "|")[1]
// Loop through all numbers
points := 0
for _, number := range numberRegex.FindAllString(elfs, -1) {
if number == "" {
continue
}
if strings.Contains(winning, " "+number+" ") {
logger.Debug("Found matching number: %q (%s)", number, winning)
if points == 0 {
points = 1
} else {
points *= 2
}
}
}
sum += points
}
return fmt.Sprintf("%d", sum)
} }
func (d *Day) Part2(in string) string { func (d *Day) Part2(in string) string {
return "" // Regex to get all numbers
numberRegex := regexp.MustCompile(`\w*`)
cards := 0
numberOfCards := make(map[int]int, 0)
for i, val := range strings.Split(in, "\n") {
if val == "" {
continue
}
// Increment cards count
cards++
replicas := 0
if val, exists := numberOfCards[i]; exists {
logger.Info("Cards of game %d: %d", i+1, val)
cards += val
replicas = val
}
// Extract card numbers
numbers := strings.Split(val, ":")[1]
winning := strings.Split(numbers, "|")[0]
elfs := strings.Split(numbers, "|")[1]
// Loop through all numbers
points := 0
for _, number := range numberRegex.FindAllString(elfs, -1) {
if number == "" {
continue
}
if strings.Contains(winning, " "+number+" ") {
logger.Debug("Found matching number: %q (%s)", number, winning)
// Save number of cards
points++
numberOfCards[i+points] += 1
// Each card wins that also
numberOfCards[i+points] += replicas
}
}
}
return fmt.Sprintf("%d", cards)
} }

View File

@ -1,11 +1,165 @@
package day_05 package day_05
import (
"fmt"
"math"
"regexp"
"strings"
"sync"
"git.rpjosh.de/RPJosh/go-logger"
"rpjosh.de/adventOfCode/pkg/utils"
)
type Day struct{} type Day struct{}
func (d *Day) Part1(in string) string { func (d *Day) Part1(in string) string {
return ""
// Regex to get all numbers
numberRegex := regexp.MustCompile(`\d+`)
inSplit := strings.Split(in, "\n")
// Contains the previous values of the last "section"
lastValues := utils.ConvertArrayToInt(numberRegex.FindAllString(inSplit[0], -1))
// Copy last values for each mapping.
// It could be possible that an element is persent
// in multiple mapping values
lastValuesCurrMapp := make([]int, len(lastValues))
copy(lastValuesCurrMapp, lastValues)
for _, val := range inSplit[1:] {
// Get numbers of input
numbersString := numberRegex.FindAllString(val, -1)
numbers := utils.ConvertArrayToInt(numbersString)
// Re-Initialize values
if val == "" {
copy(lastValues, lastValuesCurrMapp)
}
// Don't do anything with invalid lines
if len(numbers) <= 2 {
continue
}
// Try to map the values
startDest := numbers[0]
startSource := numbers[1]
length := numbers[2]
logger.Debug("Found values %d %d %d", startDest, startSource, length)
// Try to find the value in lastValues
for v, val := range lastValues {
if val >= startSource && val < startSource+length {
diff := val - startSource
lastValuesCurrMapp[v] = startDest + diff
}
}
}
return fmt.Sprintf("%d", utils.GetMinValue(lastValues))
} }
func (d *Day) Part2(in string) string { func (d *Day) Part2(in string) string {
return "" // Regex to get all numbers
numberRegex := regexp.MustCompile(`\d+`)
inSplit := strings.Split(in, "\n")
offset := 0
// Multi thread
minValue := math.MaxInt32
var wg sync.WaitGroup
var mtx sync.Mutex
// Parse mapping once
mapping := make([][]int, 0)
for _, val := range inSplit[1:] {
// Get numbers of input
numbersString := numberRegex.FindAllString(val, -1)
numbers := utils.ConvertArrayToInt(numbersString)
if len(numbers) <= 2 && val != "" {
continue
}
mapping = append(mapping, numbers)
}
// Unfold paris of seed values
seeds := utils.ConvertArrayToInt(numberRegex.FindAllString(inSplit[offset], -1))
for i := 0; i+1 < len(seeds); i += 2 {
wg.Add(1)
go func(i int) {
lastMin := seeds[i]
for m := seeds[i]; m < seeds[i]+seeds[i+1]; m++ {
if m%5000000 == 0 {
logger.Debug("%d. Parsing %d", i, m)
}
// Bulk
if m%100000 == 0 || m == seeds[i]+seeds[i+1]-1 {
wg.Add(1)
go func(min, max int) {
rtc := d.ParseSingleFor2(min, max, &mapping)
mtx.Lock()
if rtc < minValue {
minValue = rtc
}
mtx.Unlock()
wg.Done()
}(lastMin, m)
lastMin = m
}
}
logger.Info("Finished %d", i)
wg.Done()
}(i)
// Limit max number of goroutines
if i != 0 && i%10 == 0 {
wg.Wait()
}
}
wg.Wait()
return fmt.Sprintf("%d", minValue)
}
func (d *Day) ParseSingleFor2(min int, max int, values *[][]int) int {
lastValues := make([]int, max-min)
for i := min; i < max; i++ {
lastValues[i-min] = i
}
// Copy last values for each mapping.
// It could be possible that an element is persent
// in multiple mapping values
lastValuesCurrMapp := make([]int, len(lastValues))
copy(lastValuesCurrMapp, lastValues)
for _, val := range *values {
// Re-Initialize values
if len(val) == 0 {
copy(lastValues, lastValuesCurrMapp)
continue
}
// Try to map the values
startDest := val[0]
startSource := val[1]
length := val[2]
// Try to find the value in lastValues
for v, val := range lastValues {
if val >= startSource && val < startSource+length {
diff := val - startSource
lastValuesCurrMapp[v] = startDest + diff
}
}
}
return utils.GetMinValue(lastValues)
} }

View File

@ -99,3 +99,39 @@ func IsInt(val string) bool {
_, err := strconv.Atoi(val) _, err := strconv.Atoi(val)
return err == nil return err == nil
} }
// GetMinValue returns the smallest number
// within the given array
func GetMinValue(values []int) int {
if len(values) == 0 {
return 0
}
min := values[0]
for _, val := range values {
if val < min {
min = val
}
}
return min
}
// ConvertToInt converts each number within
// []string to a number and returns the resulting array.
// Empty string values are ignored
func ConvertArrayToInt(values []string) []int {
rtc := make([]int, 0)
// Convert each value
for _, nmbString := range values {
if nmbString == "" {
continue
}
nmb := ToInt(nmbString)
rtc = append(rtc, nmb)
}
return rtc
}