106 lines
2.0 KiB
Go
106 lines
2.0 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
func main() {
|
|
patterns, targets := readData("example.txt")
|
|
fmt.Println(part1(patterns, targets), 6)
|
|
fmt.Println(part2(patterns, targets), 16)
|
|
|
|
patterns, targets = readData("data.txt")
|
|
fmt.Println(part1(patterns, targets), 280)
|
|
fmt.Println(part2(patterns, targets))
|
|
}
|
|
|
|
func part1(patterns []string, targets []string) (okCount int) {
|
|
notFound := make(map[string]bool)
|
|
for _, target := range targets {
|
|
if doable(patterns, target, notFound) {
|
|
okCount++
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func part2(patterns []string, targets []string) (okCount int) {
|
|
combis := make(map[string]int)
|
|
for _, target := range targets {
|
|
okCount += combinations(patterns, target, combis)
|
|
}
|
|
return
|
|
}
|
|
|
|
func combinations(patterns []string, target string, combis map[string]int) (combiCount int) {
|
|
if combiCountCache, ok := combis[target]; ok {
|
|
return combiCountCache
|
|
}
|
|
|
|
for _, p := range patterns {
|
|
if len(p) > len(target) {
|
|
continue
|
|
}
|
|
if target[:len(p)] != p {
|
|
continue
|
|
}
|
|
|
|
if len(p) == len(target) {
|
|
if p == target {
|
|
combiCount++
|
|
}
|
|
} else {
|
|
combiCount += combinations(patterns, target[len(p):], combis)
|
|
}
|
|
}
|
|
|
|
combis[target] = combiCount
|
|
return
|
|
}
|
|
|
|
func doable(patterns []string, target string, notFound map[string]bool) bool {
|
|
if len(target) == 0 {
|
|
return true
|
|
}
|
|
|
|
if _, n := notFound[target]; n {
|
|
return false
|
|
}
|
|
|
|
for _, p := range patterns {
|
|
if len(p) > len(target) {
|
|
continue
|
|
}
|
|
if target[:len(p)] != p {
|
|
continue
|
|
}
|
|
if doable(patterns, target[len(p):], notFound) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
notFound[target] = true
|
|
return false
|
|
}
|
|
|
|
func readData(fileName string) (patterns []string, targets []string) {
|
|
fp, _ := os.Open(fileName)
|
|
scanner := bufio.NewScanner(fp)
|
|
|
|
scanner.Scan()
|
|
patterns = strings.Split(scanner.Text(), ",")
|
|
for i, p := range patterns {
|
|
patterns[i] = strings.TrimSpace(p)
|
|
}
|
|
|
|
scanner.Scan()
|
|
for scanner.Scan() {
|
|
targets = append(targets, strings.TrimSpace(scanner.Text()))
|
|
}
|
|
|
|
return
|
|
}
|