From d8eddf80e3d4ca4681590b0bbd84e6b620f8e050 Mon Sep 17 00:00:00 2001 From: oabrivard Date: Wed, 20 Dec 2023 08:56:56 +0100 Subject: [PATCH] Completed part 2 of Day 19 puzzle with a lot of help from https://github.com/rumkugel13 to debug my code (wouldn't have finished it otherwise) --- day19/day19.go | 89 +++++++++++++++++++++++++++++++++++++++++++++ day19/day19_test.go | 38 +++++++++++++++++++ 2 files changed, 127 insertions(+) diff --git a/day19/day19.go b/day19/day19.go index c4eaf37..b199a1b 100644 --- a/day19/day19.go +++ b/day19/day19.go @@ -64,6 +64,7 @@ func ParseWorkflows(lines []string) map[string]Workflow { wf = append(wf, Rule{ category: 'F', + operator: 0, action: wfLast, }) @@ -167,3 +168,91 @@ func Part1(lines []string) int { return sum } + +func countParts(mins Part, maxs Part) int { + result := 1 + + result *= maxs.xVal - mins.xVal + 1 + result *= maxs.mVal - mins.mVal + 1 + result *= maxs.aVal - mins.aVal + 1 + result *= maxs.sVal - mins.sVal + 1 + + return result +} + +func traverseWF(wfName string, workflows map[string]Workflow, mins Part, maxs Part) int { + if wfName == "R" { + return 0 + } + if wfName == "A" { + return countParts(mins, maxs) + } + + wf := workflows[wfName] + + result := 0 + for _, rule := range wf { + nextMins := mins + nextMaxs := maxs + + switch rule.operator { + case 0: + result += traverseWF(rule.action, workflows, mins, maxs) + case '<': + switch rule.category { + case 'x': + nextMaxs.xVal = rule.value - 1 + mins.xVal = rule.value + case 'm': + nextMaxs.mVal = rule.value - 1 + mins.mVal = rule.value + case 'a': + nextMaxs.aVal = rule.value - 1 + mins.aVal = rule.value + case 's': + nextMaxs.sVal = rule.value - 1 + mins.sVal = rule.value + } + result += traverseWF(rule.action, workflows, nextMins, nextMaxs) + case '>': + switch rule.category { + case 'x': + nextMins.xVal = rule.value + 1 + maxs.xVal = rule.value + case 'm': + nextMins.mVal = rule.value + 1 + maxs.mVal = rule.value + case 'a': + nextMins.aVal = rule.value + 1 + maxs.aVal = rule.value + case 's': + nextMins.sVal = rule.value + 1 + maxs.sVal = rule.value + } + result += traverseWF(rule.action, workflows, nextMins, nextMaxs) + } + } + + return result +} + +func Part2(lines []string) int { + idx := 0 + for i, line := range lines { + if strings.TrimSpace(line) == "" { + idx = i + break + } + } + + workflows := ParseWorkflows(lines[:idx]) + + fmt.Println(len(workflows)) + + mins := Part{1, 1, 1, 1} + maxs := Part{4000, 4000, 4000, 4000} + + result := traverseWF("in", workflows, mins, maxs) + + return result +} diff --git a/day19/day19_test.go b/day19/day19_test.go index 9ae00d8..8aafbc6 100644 --- a/day19/day19_test.go +++ b/day19/day19_test.go @@ -81,3 +81,41 @@ func TestPart1WithInput(t *testing.T) { t.Fatalf("expected 575412, got %d", result) } } + +func TestPart2(t *testing.T) { + lines := []string{ + "px{a<2006:qkq,m>2090:A,rfg}", + "pv{a>1716:R,A}", + "lnx{m>1548:A,A}", + "rfg{s<537:gd,x>2440:R,A}", + "qs{s>3448:A,lnx}", + "qkq{x<1416:A,crn}", + "crn{x>2662:A,R}", + "in{s<1351:px,qqz}", + "qqz{s>2770:qs,m<1801:hdj,R}", + "gd{a>3333:R,R}", + "hdj{m>838:A,pv}", + "", + "{x=787,m=2655,a=1222,s=2876}", + "{x=1679,m=44,a=2067,s=496}", + "{x=2036,m=264,a=79,s=2244}", + "{x=2461,m=1339,a=466,s=291}", + "{x=2127,m=1623,a=2188,s=1013}", + } + + result := Part2(lines) + + if result != 167409079868000 { + t.Fatalf("expected 167409079868000, got %d", result) + } +} + +func TestPart2WithInput(t *testing.T) { + lines := utils.ReadLines("input.txt") + + result := Part2(lines) + + if result != 126107942006821 { + t.Fatalf("expected 126107942006821, got %d", result) + } +}