118 lines
3.2 KiB
Go
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)
|
|
}
|