What a mess! 18-20, no Part 2 solve. Oh well!
This commit is contained in:
389
2023/19/code.go
Normal file
389
2023/19/code.go
Normal file
@@ -0,0 +1,389 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/jpillora/puzzler/harness/aoc"
|
||||
)
|
||||
|
||||
func main() {
|
||||
aoc.Harness(run)
|
||||
}
|
||||
|
||||
// on code change, run will be executed 4 times:
|
||||
// 1. with: false (part1), and example input
|
||||
// 2. with: true (part2), and example input
|
||||
// 3. with: false (part1), and user input
|
||||
// 4. with: true (part2), and user input
|
||||
// the return value of each run is printed to stdout
|
||||
type Part struct {
|
||||
X int
|
||||
M int
|
||||
A int
|
||||
S int
|
||||
}
|
||||
|
||||
type PartAcceptor struct {
|
||||
Wfl []Workflow
|
||||
Xmax int
|
||||
Xmin int
|
||||
Mmax int
|
||||
Mmin int
|
||||
Amax int
|
||||
Amin int
|
||||
Smax int
|
||||
Smin int
|
||||
}
|
||||
|
||||
type Workflow struct {
|
||||
Comparing string
|
||||
CompareType string
|
||||
Value int
|
||||
Result string
|
||||
Method func(p Part) string
|
||||
}
|
||||
|
||||
func run(part2 bool, input string) any {
|
||||
// when you're ready to do part 2, remove this "not implemented" block
|
||||
workflows := make(map[string][]Workflow)
|
||||
parts := make([]Part, 0)
|
||||
|
||||
inParts := false
|
||||
for _, l := range strings.Split(input, "\n") {
|
||||
if l == "" {
|
||||
inParts = true
|
||||
continue
|
||||
}
|
||||
|
||||
if !inParts {
|
||||
cutoff := strings.Index(l, "{")
|
||||
name := l[0:cutoff]
|
||||
wkflow := l[cutoff+1 : len(l)-1]
|
||||
|
||||
functions := make([]Workflow, 0)
|
||||
for _, wkF := range strings.Split(wkflow, ",") {
|
||||
|
||||
if strings.Contains(wkF, ":") {
|
||||
// Mapping function
|
||||
spl := strings.Split(wkF, ":")
|
||||
|
||||
comparing := spl[0][0:2]
|
||||
compared, _ := strconv.Atoi(spl[0][2:])
|
||||
res := spl[1]
|
||||
|
||||
if comparing == "x>" {
|
||||
functions = append(functions, Workflow{"x", ">", compared, res, func(p Part) string {
|
||||
if p.X > compared {
|
||||
return res
|
||||
}
|
||||
return ""
|
||||
}})
|
||||
} else if comparing == "x<" {
|
||||
functions = append(functions, Workflow{"x", "<", compared, res, func(p Part) string {
|
||||
if p.X < compared {
|
||||
return res
|
||||
}
|
||||
return ""
|
||||
}})
|
||||
} else if comparing == "m>" {
|
||||
functions = append(functions, Workflow{"m", ">", compared, res, func(p Part) string {
|
||||
if p.M > compared {
|
||||
return res
|
||||
}
|
||||
return ""
|
||||
}})
|
||||
} else if comparing == "m<" {
|
||||
functions = append(functions, Workflow{"m", "<", compared, res, func(p Part) string {
|
||||
if p.M < compared {
|
||||
return res
|
||||
}
|
||||
return ""
|
||||
}})
|
||||
} else if comparing == "a>" {
|
||||
functions = append(functions, Workflow{"a", ">", compared, res, func(p Part) string {
|
||||
if p.A > compared {
|
||||
return res
|
||||
}
|
||||
return ""
|
||||
}})
|
||||
} else if comparing == "a<" {
|
||||
functions = append(functions, Workflow{"a", "<", compared, res, func(p Part) string {
|
||||
if p.A < compared {
|
||||
return res
|
||||
}
|
||||
return ""
|
||||
}})
|
||||
} else if comparing == "s>" {
|
||||
functions = append(functions, Workflow{"s", ">", compared, res, func(p Part) string {
|
||||
if p.S > compared {
|
||||
return res
|
||||
}
|
||||
return ""
|
||||
}})
|
||||
} else if comparing == "s<" {
|
||||
functions = append(functions, Workflow{"s", "<", compared, res, func(p Part) string {
|
||||
if p.S < compared {
|
||||
return res
|
||||
}
|
||||
return ""
|
||||
}})
|
||||
} else {
|
||||
panic("!??")
|
||||
}
|
||||
|
||||
} else {
|
||||
// Just a return function
|
||||
functions = append(functions, Workflow{"", "", 0, wkF, func(p Part) string { return wkF }})
|
||||
}
|
||||
}
|
||||
|
||||
workflows[name] = functions
|
||||
} else {
|
||||
l = strings.Replace(strings.Replace(l, "{", "", -1), "}", "", -1)
|
||||
|
||||
spl := strings.Split(l, ",")
|
||||
|
||||
x, _ := strconv.Atoi(spl[0][2:])
|
||||
m, _ := strconv.Atoi(spl[1][2:])
|
||||
a, _ := strconv.Atoi(spl[2][2:])
|
||||
s, _ := strconv.Atoi(spl[3][2:])
|
||||
|
||||
parts = append(parts, Part{x, m, a, s})
|
||||
}
|
||||
}
|
||||
|
||||
if part2 {
|
||||
pa := PartAcceptor{workflows["in"], 4000, 1, 4000, 1, 4000, 1, 4000, 1}
|
||||
|
||||
pas := []PartAcceptor{pa}
|
||||
|
||||
combos := int64(0)
|
||||
for len(pas) > 0 {
|
||||
//fmt.Printf("%v\n", pas)
|
||||
p := pas[0]
|
||||
pas = pas[1:]
|
||||
|
||||
for _, wf := range p.Wfl {
|
||||
if wf.CompareType != "" {
|
||||
//fmt.Printf("Splitting comparator\n")
|
||||
// Comparator! Will split
|
||||
if wf.CompareType == ">" {
|
||||
if wf.Comparing == "x" && p.Xmax > wf.Value {
|
||||
if p.Xmin > wf.Value {
|
||||
if wf.Result == "A" {
|
||||
fmt.Printf("Accepted: %v\n", p)
|
||||
combos += int64(p.Xmax-p.Xmin+1) * int64(p.Mmax-p.Mmin+1) * int64(p.Amax-p.Amin+1) * int64(p.Smax-p.Smin+1)
|
||||
} else if wf.Result != "R" {
|
||||
newP := PartAcceptor{workflows[wf.Result], p.Xmax, p.Xmin, p.Mmax, p.Mmin, p.Amax, p.Amin, p.Smax, p.Smin}
|
||||
pas = append(pas, newP)
|
||||
}
|
||||
} else { // Split
|
||||
if wf.Result == "A" {
|
||||
fmt.Printf("Accepted (split): %v\n", p)
|
||||
combos += int64(p.Xmax-(wf.Value+1)+1) * int64(p.Mmax-p.Mmin+1) * int64(p.Amax-p.Amin+1) * int64(p.Smax-p.Smin+1)
|
||||
} else if wf.Result != "R" {
|
||||
newP := PartAcceptor{workflows[wf.Result], p.Xmax, p.Xmin, p.Mmax, p.Mmin, p.Amax, p.Amin, p.Smax, p.Smin}
|
||||
pas = append(pas, newP)
|
||||
}
|
||||
|
||||
p.Xmax = wf.Value
|
||||
}
|
||||
} else if wf.Comparing == "m" && p.Mmax > wf.Value {
|
||||
if p.Mmin > wf.Value {
|
||||
if wf.Result == "A" {
|
||||
fmt.Printf("Accepted: %v\n", p)
|
||||
combos += int64(p.Xmax-p.Xmin+1) * int64(p.Mmax-p.Mmin+1) * int64(p.Amax-p.Amin+1) * int64(p.Smax-p.Smin+1)
|
||||
} else if wf.Result != "R" {
|
||||
newP := PartAcceptor{workflows[wf.Result], p.Xmax, p.Xmin, p.Mmax, p.Mmin, p.Amax, p.Amin, p.Smax, p.Smin}
|
||||
pas = append(pas, newP)
|
||||
}
|
||||
} else { // Split
|
||||
if wf.Result == "A" {
|
||||
fmt.Printf("Accepted: %v\n", p)
|
||||
combos += int64(p.Xmax-p.Xmin+1) * int64(p.Mmax-(wf.Value+1)+1) * int64(p.Amax-p.Amin+1) * int64(p.Smax-p.Smin+1)
|
||||
} else if wf.Result != "R" {
|
||||
newP := PartAcceptor{workflows[wf.Result], p.Xmax, p.Xmin, p.Mmax, p.Mmin, p.Amax, p.Amin, p.Smax, p.Smin}
|
||||
pas = append(pas, newP)
|
||||
}
|
||||
|
||||
p.Mmax = wf.Value
|
||||
}
|
||||
} else if wf.Comparing == "a" && p.Amax > wf.Value {
|
||||
if p.Amin > wf.Value {
|
||||
if wf.Result == "A" {
|
||||
fmt.Printf("Accepted: %v\n", p)
|
||||
combos += int64(p.Xmax-p.Xmin+1) * int64(p.Mmax-p.Mmin+1) * int64(p.Amax-p.Amin+1) * int64(p.Smax-p.Smin+1)
|
||||
} else if wf.Result != "R" {
|
||||
newP := PartAcceptor{workflows[wf.Result], p.Xmax, p.Xmin, p.Mmax, p.Mmin, p.Amax, p.Amin, p.Smax, p.Smin}
|
||||
pas = append(pas, newP)
|
||||
}
|
||||
} else { // Split
|
||||
if wf.Result == "A" {
|
||||
fmt.Printf("Accepted: %v\n", p)
|
||||
combos += int64(p.Xmax-p.Xmin+1) * int64(p.Mmax-p.Mmin+1) * int64(p.Amax-(wf.Value+1)+1) * int64(p.Smax-p.Smin+1)
|
||||
} else if wf.Result != "R" {
|
||||
newP := PartAcceptor{workflows[wf.Result], p.Xmax, p.Xmin, p.Mmax, p.Mmin, p.Amax, p.Amin, p.Smax, p.Smin}
|
||||
pas = append(pas, newP)
|
||||
}
|
||||
|
||||
p.Amax = wf.Value
|
||||
}
|
||||
} else if wf.Comparing == "s" && p.Smax > wf.Value {
|
||||
if p.Smin > wf.Value {
|
||||
if wf.Result == "A" {
|
||||
fmt.Printf("Accepted: %v\n", p)
|
||||
combos += int64(p.Xmax-p.Xmin+1) * int64(p.Mmax-p.Mmin+1) * int64(p.Amax-p.Amin+1) * int64(p.Smax-p.Smin+1)
|
||||
} else if wf.Result != "R" {
|
||||
newP := PartAcceptor{workflows[wf.Result], p.Xmax, p.Xmin, p.Mmax, p.Mmin, p.Amax, p.Amin, p.Smax, p.Smin}
|
||||
pas = append(pas, newP)
|
||||
}
|
||||
} else { // Split
|
||||
if wf.Result == "A" {
|
||||
fmt.Printf("Accepted: %v\n", p)
|
||||
combos += int64(p.Xmax-p.Xmin+1) * int64(p.Mmax-p.Mmin+1) * int64(p.Amax-p.Amin+1) * int64(p.Smax-p.Smin+1)
|
||||
} else if wf.Result != "R" {
|
||||
newP := PartAcceptor{workflows[wf.Result], p.Xmax, p.Xmin, p.Mmax, p.Mmin, p.Amax, p.Amin, p.Smax, wf.Value + 1}
|
||||
pas = append(pas, newP)
|
||||
}
|
||||
|
||||
p.Smax = wf.Value
|
||||
}
|
||||
}
|
||||
} else if wf.CompareType == "<" {
|
||||
if wf.Comparing == "x" && p.Xmin < wf.Value {
|
||||
if p.Xmax < wf.Value {
|
||||
if wf.Result == "A" {
|
||||
fmt.Printf("Accepted: %v\n", p)
|
||||
combos += int64(p.Xmax-p.Xmin+1) * int64(p.Mmax-p.Mmin+1) * int64(p.Amax-p.Amin+1) * int64(p.Smax-p.Smin+1)
|
||||
} else if wf.Result != "R" {
|
||||
newP := PartAcceptor{workflows[wf.Result], p.Xmax, p.Xmin, p.Mmax, p.Mmin, p.Amax, p.Amin, p.Smax, p.Smin}
|
||||
pas = append(pas, newP)
|
||||
}
|
||||
} else { // Split
|
||||
if wf.Result == "A" {
|
||||
fmt.Printf("Accepted (split): %v\n", p)
|
||||
combos += int64((wf.Value-1)-p.Xmin+1) * int64(p.Mmax-p.Mmin+1) * int64(p.Amax-p.Amin+1) * int64(p.Smax-p.Smin+1)
|
||||
} else if wf.Result != "R" {
|
||||
newP := PartAcceptor{workflows[wf.Result], p.Xmax, p.Xmin, p.Mmax, p.Mmin, p.Amax, p.Amin, p.Smax, p.Smin}
|
||||
pas = append(pas, newP)
|
||||
}
|
||||
|
||||
p.Xmin = wf.Value
|
||||
}
|
||||
} else if wf.Comparing == "m" && p.Mmin < wf.Value {
|
||||
if p.Mmax < wf.Value {
|
||||
if wf.Result == "A" {
|
||||
fmt.Printf("Accepted: %v\n", p)
|
||||
combos += int64(p.Xmax-p.Xmin+1) * int64(p.Mmax-p.Mmin+1) * int64(p.Amax-p.Amin+1) * int64(p.Smax-p.Smin+1)
|
||||
} else if wf.Result != "R" {
|
||||
newP := PartAcceptor{workflows[wf.Result], p.Xmax, p.Xmin, p.Mmax, p.Mmin, p.Amax, p.Amin, p.Smax, p.Smin}
|
||||
pas = append(pas, newP)
|
||||
}
|
||||
} else { // Split
|
||||
if wf.Result == "A" {
|
||||
fmt.Printf("Accepted: %v\n", p)
|
||||
combos += int64(p.Xmax-p.Xmin+1) * int64((wf.Value-1)-p.Mmin+1) * int64(p.Amax-p.Amin+1) * int64(p.Smax-p.Smin+1)
|
||||
} else if wf.Result != "R" {
|
||||
newP := PartAcceptor{workflows[wf.Result], p.Xmax, p.Xmin, p.Mmax, p.Mmin, p.Amax, p.Amin, p.Smax, p.Smin}
|
||||
pas = append(pas, newP)
|
||||
}
|
||||
|
||||
p.Mmin = wf.Value
|
||||
}
|
||||
} else if wf.Comparing == "a" && p.Amin < wf.Value {
|
||||
if p.Amax < wf.Value {
|
||||
if wf.Result == "A" {
|
||||
fmt.Printf("Accepted: %v\n", p)
|
||||
combos += int64(p.Xmax-p.Xmin+1) * int64(p.Mmax-p.Mmin+1) * int64(p.Amax-p.Amin+1) * int64(p.Smax-p.Smin+1)
|
||||
} else if wf.Result != "R" {
|
||||
newP := PartAcceptor{workflows[wf.Result], p.Xmax, p.Xmin, p.Mmax, p.Mmin, p.Amax, p.Amin, p.Smax, p.Smin}
|
||||
pas = append(pas, newP)
|
||||
}
|
||||
} else { // Split
|
||||
if wf.Result == "A" {
|
||||
fmt.Printf("Accepted: %v\n", p)
|
||||
combos += int64(p.Xmax-p.Xmin+1) * int64(p.Mmax-p.Mmin+1) * int64((wf.Value-1)-p.Amin+1) * int64(p.Smax-p.Smin+1)
|
||||
} else if wf.Result != "R" {
|
||||
newP := PartAcceptor{workflows[wf.Result], p.Xmax, p.Xmin, p.Mmax, p.Mmin, p.Amax, p.Amin, p.Smax, p.Smin}
|
||||
pas = append(pas, newP)
|
||||
}
|
||||
|
||||
p.Amin = wf.Value
|
||||
}
|
||||
} else if wf.Comparing == "s" && p.Smin < wf.Value {
|
||||
if p.Smax < wf.Value {
|
||||
if wf.Result == "A" {
|
||||
fmt.Printf("Accepted: %v\n", p)
|
||||
combos += int64(p.Xmax-p.Xmin+1) * int64(p.Mmax-p.Mmin+1) * int64(p.Amax-p.Amin+1) * int64(p.Smax-p.Smin+1)
|
||||
} else if wf.Result != "R" {
|
||||
newP := PartAcceptor{workflows[wf.Result], p.Xmax, p.Xmin, p.Mmax, p.Mmin, p.Amax, p.Amin, p.Smax, p.Smin}
|
||||
pas = append(pas, newP)
|
||||
}
|
||||
} else { // Split
|
||||
if wf.Result == "A" {
|
||||
fmt.Printf("Accepted: %v\n", p)
|
||||
combos += int64(p.Xmax-p.Xmin+1) * int64(p.Mmax-p.Mmin+1) * int64(p.Amax-p.Amin+1) * int64((wf.Value-1)-p.Smin+1)
|
||||
} else if wf.Result != "R" {
|
||||
newP := PartAcceptor{workflows[wf.Result], p.Xmax, p.Xmin, p.Mmax, p.Mmin, p.Amax, p.Amin, p.Smax, p.Smin}
|
||||
pas = append(pas, newP)
|
||||
}
|
||||
|
||||
p.Smin = wf.Value
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic("!?!?")
|
||||
}
|
||||
|
||||
} else if wf.Result == "A" {
|
||||
// Auto accept
|
||||
fmt.Printf("Accepted: %v\n", p)
|
||||
combos += int64(p.Xmax-p.Xmin+1) * int64(p.Mmax-p.Mmin+1) * int64(p.Amax-p.Amin+1) * int64(p.Smax-p.Smin+1)
|
||||
} else if wf.Result == "R" {
|
||||
// Do nothing, rejected
|
||||
fmt.Printf("Rejected: %v\n", p)
|
||||
} else {
|
||||
//fmt.Printf("Moved to %v (%v)\n", wf.Result, p)
|
||||
p.Wfl = workflows[wf.Result]
|
||||
pas = append(pas, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Expect: 167409079868000
|
||||
// Getting: 397530093888000
|
||||
|
||||
return combos
|
||||
|
||||
}
|
||||
|
||||
ratingSum := 0
|
||||
for _, p := range parts {
|
||||
wk := workflows["in"]
|
||||
|
||||
for wk != nil {
|
||||
workflowOne:
|
||||
for _, fnc := range wk {
|
||||
res := fnc.Method(p)
|
||||
|
||||
if res != "" {
|
||||
if res == "A" {
|
||||
ratingSum += (p.X + p.M + p.A + p.S)
|
||||
wk = nil
|
||||
} else if res == "R" {
|
||||
wk = nil
|
||||
} else {
|
||||
// it's a mapping
|
||||
wk = workflows[res]
|
||||
}
|
||||
break workflowOne
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// solve part 1 here
|
||||
return ratingSum
|
||||
}
|
||||
Reference in New Issue
Block a user