2022-12-06 21:10:52 +00:00
|
|
|
package day_05
|
|
|
|
|
2023-12-05 19:43:44 +00:00
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"math"
|
|
|
|
"regexp"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"git.rpjosh.de/RPJosh/go-logger"
|
|
|
|
"rpjosh.de/adventOfCode/pkg/utils"
|
|
|
|
)
|
|
|
|
|
2022-12-06 21:10:52 +00:00
|
|
|
type Day struct{}
|
|
|
|
|
|
|
|
func (d *Day) Part1(in string) string {
|
2023-12-05 19:43:44 +00:00
|
|
|
|
|
|
|
// 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))
|
2022-12-06 21:10:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Day) Part2(in string) string {
|
2023-12-05 19:43:44 +00:00
|
|
|
// 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)
|
2022-12-06 21:10:52 +00:00
|
|
|
}
|