diff options
Diffstat (limited to 'day19/main.go')
-rw-r--r-- | day19/main.go | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/day19/main.go b/day19/main.go new file mode 100644 index 0000000..96dac55 --- /dev/null +++ b/day19/main.go @@ -0,0 +1,105 @@ +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 +} |