aoc2024/day-19/internal/two/solve.go

73 lines
1.3 KiB
Go

package two
import (
"bytes"
"cmp"
"slices"
"strings"
log "github.com/sirupsen/logrus"
)
func Solve(buf []byte) (int, error) {
r := bytes.NewReader(buf)
stripes, designs, err := parseLines(r)
if err != nil {
return 0, err
}
conc := len(designs)
countChan := make(chan int)
for _, design := range designs {
go func() {
count, ok := numPossibleArrangement(design, stripes, make(map[string]int))
if ok {
log.Debugf("design: %s is possible in %d ways", design, count)
countChan <- count
return
}
countChan <- 0
}()
}
var totalCount int
for range conc {
count := <-countChan
totalCount += count
}
return totalCount, nil
}
func numPossibleArrangement(design string, stripes []string, memo map[string]int) (int, bool) {
if len(design) == 0 {
return 1, true
}
greedy := []string{}
for _, stripe := range stripes {
if strings.HasPrefix(design, stripe) {
greedy = append(greedy, stripe)
}
}
slices.SortFunc(greedy, func(a, b string) int {
return cmp.Compare(len(b), len(a))
})
var totalCount int
for _, g := range greedy {
if count, ok := memo[design[len(g):]]; ok {
totalCount += count
continue
}
count, ok := numPossibleArrangement(design[len(g):], stripes, memo)
if ok {
totalCount += count
}
memo[design[len(g):]] = count
}
return totalCount, true
}