|
|
|
@ -64,6 +64,7 @@ func ParseWorkflows(lines []string) map[string]Workflow {
|
|
|
|
|
|
|
|
|
|
|
|
wf = append(wf, Rule{
|
|
|
|
wf = append(wf, Rule{
|
|
|
|
category: 'F',
|
|
|
|
category: 'F',
|
|
|
|
|
|
|
|
operator: 0,
|
|
|
|
action: wfLast,
|
|
|
|
action: wfLast,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
@ -167,3 +168,91 @@ func Part1(lines []string) int {
|
|
|
|
|
|
|
|
|
|
|
|
return sum
|
|
|
|
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
|
|
|
|
|
|
|
|
}
|
|
|
|
|