aoc24/day7/main.go
mstar 98c7b52a40 Day 7 complete
I like recursion and functional
2024-12-07 16:08:18 +01:00

118 lines
3.2 KiB
Go

package main
import (
"fmt"
"strconv"
"strings"
"sync"
"git.mstar.dev/mstar/aoc24/util"
"git.mstar.dev/mstar/goutils/other"
"git.mstar.dev/mstar/goutils/sliceutils"
)
type Group struct {
Target uint64
Elements []uint64
}
func parseLine(line string) (group Group) {
parts := strings.Split(line, ": ")
if len(parts) != 2 {
panic("Invalid line parts count")
}
group.Target = other.Must(strconv.ParseUint(parts[0], 10, 64))
group.Elements = []uint64{}
for _, elem := range strings.Split(parts[1], " ") {
if len(elem) == 0 {
continue
}
group.Elements = append(group.Elements, other.Must(strconv.ParseUint(elem, 10, 64)))
}
return
}
func checkGroup1(group *Group) uint64 {
// fmt.Printf("Checking group %v\n", group)
if len(group.Elements) == 2 {
if group.Elements[0]*group.Elements[1] == group.Target ||
group.Elements[0]+group.Elements[1] == group.Target {
// fmt.Printf("Group %v suceeded\n", group)
return 1
}
return 0
}
elemsMult := []uint64{group.Elements[0] * group.Elements[1]}
elemsMult = append(elemsMult, group.Elements[2:]...)
elemsAdd := []uint64{group.Elements[0] + group.Elements[1]}
elemsAdd = append(elemsAdd, group.Elements[2:]...)
return checkGroup1(&Group{group.Target, elemsAdd}) +
checkGroup1(&Group{group.Target, elemsMult})
}
func concatNrs(a, b uint64) uint64 {
return other.Must(strconv.ParseUint(fmt.Sprintf("%d%d", a, b), 10, 64))
}
func checkGroup2(group *Group) uint64 {
// fmt.Printf("Checking group %v\n", group)
if len(group.Elements) == 2 {
if group.Elements[0]*group.Elements[1] == group.Target ||
group.Elements[0]+group.Elements[1] == group.Target ||
concatNrs(group.Elements[0], group.Elements[1]) == group.Target {
// fmt.Printf("Group %v suceeded\n", group)
return 1
}
return 0
}
elemsMult := []uint64{group.Elements[0] * group.Elements[1]}
elemsMult = append(elemsMult, group.Elements[2:]...)
elemsAdd := []uint64{group.Elements[0] + group.Elements[1]}
elemsAdd = append(elemsAdd, group.Elements[2:]...)
elemsConc := []uint64{concatNrs(group.Elements[0], group.Elements[1])}
elemsConc = append(elemsConc, group.Elements[2:]...)
return checkGroup2(&Group{group.Target, elemsAdd}) +
checkGroup2(&Group{group.Target, elemsMult}) + checkGroup2(&Group{group.Target, elemsConc})
}
func main() {
inputLines := util.FileContentToNonEmptyLines(util.LoadFileFromArgs())
groups := sliceutils.Map(inputLines, func(t string) Group { return parseLine(t) })
// fmt.Printf("All groups: %v\n", groups)
var acc1 uint64 = 0
addChan1 := make(chan uint64, 1)
go func() {
for val := range addChan1 {
// fmt.Printf("Adding %d to acc\n", val)
acc1 += val
}
}()
wg1 := sync.WaitGroup{}
for _, group := range groups {
if checkGroup1(&group) != 0 {
acc1 += group.Target
// fmt.Printf("Group with target %d suceeded\n", group.Target)
}
// wg1.Add(1)
// go func(group Group) {
// if checkGroup1(&group) != 0 {
// fmt.Printf("Group with target %d suceeded\n", group.Target)
// addChan1 <- group.Target
// }
// wg1.Done()
// }(group)
}
wg1.Wait()
close(addChan1)
fmt.Printf("Task 1: %d\n", acc1)
var acc2 uint64 = 0
for _, group := range groups {
if checkGroup2(&group) != 0 {
acc2 += group.Target
}
}
fmt.Printf("Task 2: %d\n", acc2)
}