aoc2023/day09/oasis.go

150 lines
3.2 KiB
Go

package main
import(
"fmt"
"os"
"bufio"
"sync"
"time"
"regexp"
"strconv"
)
// Parallel code, global vars
type Series struct {
mu sync.Mutex
numStore [][]int
total uint64
}
func check(e error) {
if e != nil {
panic(e)
}
}
func PrintAndWait(x ...any) {
fmt.Print(x...)
fmt.Scanln()
}
// use defer timer("funcname")() when the function you want to
// test starts
func timer(name string) func() {
start := time.Now()
return func() {
fmt.Printf("%s took %v\n", name, time.Since(start))
}
}
func PredictValueBack(numbers []int) []int {
// Are we finished? By default, true
temp := true
for i := 0; i < len(numbers); i++ {
if numbers[i] != 0 {
temp = false
break
}
}
// Check to end recursion
if temp == true {
return numbers
}
newNums := make([]int, len(numbers) - 1)
for i := 0; i < len(numbers) - 1; i++ {
newNums[i] = numbers[i + 1] - numbers[i]
}
myNums := PredictValueBack(newNums)
addValue := newNums[0] - myNums[0]
// We need to append at the start
newNums = append([]int{addValue}, newNums...)
return newNums
}
func (ser *Series) CallPredictBack(numbers []int, wg *sync.WaitGroup) {
tempNum := PredictValueBack(numbers)
ser.mu.Lock()
ser.total += uint64(numbers[0] - tempNum[0])
ser.mu.Unlock()
wg.Done()
}
func PredictValue(numbers []int) []int {
// Are we finished? By default, true
temp := true
for i := 0; i < len(numbers); i++ {
if numbers[i] != 0 {
temp = false
break
}
}
// Check to end recursion
if temp == true {
return numbers
}
newNums := make([]int, len(numbers) - 1)
for i := 0; i < len(numbers) - 1; i++ {
newNums[i] = numbers[i + 1] - numbers[i]
}
myNums := PredictValue(newNums)
addValue := myNums[len(myNums) - 1]
newNums = append(newNums, newNums[len(newNums) - 1] + addValue)
return newNums
}
func (ser *Series) CallPredict(numbers []int, wg *sync.WaitGroup) {
tempNum := PredictValue(numbers)
lt := len(tempNum) - 1
ln := len(numbers) - 1
ser.mu.Lock()
ser.total += uint64(numbers[ln] + tempNum[lt])
ser.mu.Unlock()
wg.Done()
}
func main() {
defer timer("main")()
file, err := os.Open("./inputs/day09_input")
check(err)
defer file.Close()
var wg sync.WaitGroup
renum := regexp.MustCompile("(\\-[0-9]+|[0-9]+)")
ser := Series{ total: 0, }
lines := make([]string, 0)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
ser.numStore = make([][]int, len(lines))
for i := 0; i < len(lines); i++ {
temp := renum.FindAllString(lines[i], -1)
for j := 0; j < len(temp); j++ {
num, err := strconv.Atoi(temp[j])
check(err)
ser.numStore[i] = append(ser.numStore[i], num)
}
}
// Now I have a 2D array with all the numbers, I can start RECURSING
wg.Add(len(ser.numStore))
for i := 0; i < len(ser.numStore); i++ {
go ser.CallPredict(ser.numStore[i], &wg)
}
wg.Wait()
fmt.Printf("%d\n", ser.total)
ser.total = 0
wg.Add(len(ser.numStore))
for i := 0; i < len(ser.numStore); i++ {
go ser.CallPredictBack(ser.numStore[i], &wg)
}
wg.Wait()
fmt.Printf("%d\n", ser.total)
}