diff --git a/day19/main.go b/day19/main.go index 04aad51..689d6cc 100644 --- a/day19/main.go +++ b/day19/main.go @@ -32,100 +32,18 @@ func run(scan *bufio.Scanner) (*result, error) { } // Is Part - if text[0] == '{' { - var p part - for _, s := range strings.Split(text[1:], ",") { - a, b, _ := strings.Cut(s, "=") - i := aoc.Atoi(b) - switch a { - case "x": - p.x = i - case "m": - p.m = i - case "a": - p.a = i - case "s": - p.s = i - } - } + if p, ok := scanPart(text); ok { parts = append(parts, p) continue } - name, text, _ := strings.Cut(text, "{") - var r []rule - for _, s := range strings.Split(text, ",") { - if a, b, ok := strings.Cut(s, "<"); ok { - b, c, _ := strings.Cut(b, ":") - r = append(r, rule{ - match: a, - op: "<", - value: aoc.Atoi(b), - queue: c, - }) - - continue - } - if a, b, ok := strings.Cut(s, ">"); ok { - b, c, _ := strings.Cut(b, ":") - r = append(r, rule{ - match: a, - op: ">", - value: aoc.Atoi(b), - queue: c, - }) - continue - } - - // default queue comes last - r = append(r, rule{queue: s}) - break - } - workflows[name] = r - } - - var rejected []part - var accepted []part - - for _, p := range parts { - workflow := "in" - -nextStep: - for workflow != "" { - for _, r := range workflows[workflow] { - if !r.Match(p) { - continue - } - workflow = r.queue - - if workflow == "A" { - accepted = append(accepted, p) - workflow = "" - break nextStep - } - if workflow == "R" { - rejected = append(rejected, p) - workflow = "" - break nextStep - } - - continue nextStep - } - + if name, r, ok := scanRule(text); ok { + workflows[name] = r } } - fmt.Println("accepted", accepted) - fmt.Println("rejected", rejected) - var result result - - for _, p := range accepted { - result.valuePT1 += p.x - result.valuePT1 += p.m - result.valuePT1 += p.a - result.valuePT1 += p.s - } + result.valuePT1 = solveWorkflow(parts, workflows) return &result, nil } @@ -133,15 +51,73 @@ nextStep: type part struct { x, m, a, s int } + func (p part) String() string { - return fmt.Sprintf("{x:%v m:%v a:%v s:%v}", p.x,p.m,p.a,p.s) + return fmt.Sprintf("{x:%v m:%v a:%v s:%v}", p.x, p.m, p.a, p.s) } +func scanPart(text string) (part, bool) { + var p part + + // Is Part + if text[0] == '{' { + for _, s := range strings.Split(text[1:], ",") { + a, b, _ := strings.Cut(s, "=") + i := aoc.Atoi(b) + switch a { + case "x": + p.x = i + case "m": + p.m = i + case "a": + p.a = i + case "s": + p.s = i + } + } + return p, true + } + return p, false +} + type rule struct { match string op string value int queue string } + +func scanRule(text string) (string, []rule, bool) { + name, text, _ := strings.Cut(text, "{") + var r []rule + for _, s := range strings.Split(text, ",") { + if a, b, ok := strings.Cut(s, "<"); ok { + b, c, _ := strings.Cut(b, ":") + r = append(r, rule{ + match: a, + op: "<", + value: aoc.Atoi(b), + queue: c, + }) + + continue + } + if a, b, ok := strings.Cut(s, ">"); ok { + b, c, _ := strings.Cut(b, ":") + r = append(r, rule{ + match: a, + op: ">", + value: aoc.Atoi(b), + queue: c, + }) + continue + } + + // default queue comes last + r = append(r, rule{queue: s}) + break + } + return name, r, len(r) > 0 +} func (r rule) Match(p part) bool { var value int @@ -161,17 +137,119 @@ func (r rule) Match(p part) bool { if r.op == ">" && value > r.value { return true } else if r.op == "<" && value < r.value { - return true - } - return false // no match + return true + } + return false // no match } +func solveWorkflow(parts []part, workflows map[string][]rule) int { + var rejected []part + var accepted []part -func in(n string, haystack ...string) bool { - for _, h := range haystack { - if n == h { - return true + for _, p := range parts { + workflow := "in" + + nextStep: + for workflow != "" { + for _, r := range workflows[workflow] { + if !r.Match(p) { + continue + } + workflow = r.queue + + if workflow == "A" { + accepted = append(accepted, p) + workflow = "" + break nextStep + } + if workflow == "R" { + rejected = append(rejected, p) + workflow = "" + break nextStep + } + + continue nextStep + } } } - return false + + fmt.Println("accepted", accepted) + fmt.Println("rejected", rejected) + + sum := 0 + for _, p := range accepted { + sum += p.x + sum += p.m + sum += p.a + sum += p.s + } + return sum } + +/* +in{s<1351:px, s>=1351:qqz} + +--> px{a<2006&&(x<1416||x>2662):A, a<2006&&x>=1416&&x<=2662:R, m>2090:A, a>=2006&&m<=2090&&s<537:R||x>2440:R, a>=2006&&m<=2090&&s<537&x<=2440:A} + +--> qqz{s>2770:A, m<1801&&m>838:A, m<1801&&a>1716:R, m<1801&&a<=1716:A, s<=2770&&m>=1801:R} + + + + + + + +in [/] +-- +s<1351 -> px +s>=1351 -> qqz + +px [/] +-- +s<1351 -> px + +a< 2006 -> qkq +m> 2090 -> A +a>=2006 -> ... +m<=2090 -> rfg + +qqz [ ] +-- +s>=1351 -> qqz + +s> 2770 -> qs +m< 1801 -> hdj + -> R + +qkq [ ] +-- +s< 1351 -> +a< 2006 -> + +x< 1416 -> A +x>=1416 -> crn + +rfg [ ] +-- +s< 1351 -> px +a>=2006 ->... +m<=2090 -> rfg + +s< 537 -> gd +x> 2440 -> R +s>= 537 ->... +x<=2440 -> A + +crn [ ] +-- +s< 1351 -> px +a< 2006 -> qkq +x>=1416 -> crn + +x> 2662 -> A +x<=2662 -> R + +A +-- + +*/ diff --git a/set.go b/set.go index 8b316d4..fc6939e 100644 --- a/set.go +++ b/set.go @@ -57,3 +57,12 @@ func (m *defaultMap[K, V]) Items() []pair[K, V] { } return items } + +func In[C comparable](n C, haystack ...C) bool { + for _, h := range haystack { + if n == h { + return true + } + } + return false +}