advent2022

Advent of Code 2022 Solutions
git clone git://bsandro.tech/advent2022
Log | Files | Refs | README | LICENSE

commit 5d1f81a28d79bf586f3d77cc74e14cd081701260
parent e45241ffc2509f27bcd841269a3a101305d14927
Author: bsandro <email@bsandro.tech>
Date:   Fri, 16 Dec 2022 23:26:47 +0000

Day 16 part 1 rework - sample works, input still does not :(

Diffstat:
Mday16/main.go | 245++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
1 file changed, 150 insertions(+), 95 deletions(-)

diff --git a/day16/main.go b/day16/main.go @@ -1,60 +1,75 @@ package main import ( - "strings" "bufio" "fmt" "log" "os" "sort" + "strings" ) type Valve struct { - name string - rate int - open bool + name string + rate int + open bool connections []string } + func (v Valve) String() string { - return fmt.Sprintf("%s,%d,[%s]", v.name, v.rate, strings.Join(v.connections, ",")) + return fmt.Sprintf("%s,%d,[%s]", v.name, v.rate, + strings.Join(v.connections, ",")) } type Step struct { name, parent string } type Path struct { - name string - valve *Valve - path []string + name string + valve *Valve + path Strings + nested Paths + sumRate int // valve.rate + max(nested rates) } + func (p Path) Score() int { - return (10+p.valve.rate) / len(p.path) + return (10 + p.valve.rate) / len(p.path) } func (p Path) String() string { - s:=fmt.Sprintf("(%s:%d:%d:%d){", p.name, p.valve.rate, len(p.path),p.Score()) + s := fmt.Sprintf("(%s:%d:%d:%d sum:%d){", p.name, + p.valve.rate, len(p.path), p.Score(), p.sumRate) s += strings.Join(p.path, "->") s += "}" + if len(p.nested) > 0 { + for _, n := range p.nested { + s += "~>" + s += n.String() + } + } return s } type Paths []Path + func (ps Paths) String() string { var s string - for _,p:=range ps{ - s+=p.String()+"\n" + for _, p := range ps { + s += p.String() + + "\n" } return s } func (ps Paths) Len() int { return len(ps) } -func (ps Paths) Swap(i,j int) { ps[i],ps[j] = ps[j],ps[i] } -func (ps Paths) Less(i,j int) bool { - if ps[i].Score() == ps[j].Score() { - return len(ps[i].path) < len(ps[j].path) - } else { - return ps[i].Score() > ps[j].Score() - } +func (ps Paths) Swap(i, j int) { + ps[i], ps[j] = ps[j], ps[i] } -func (ps Paths) Find(name string) (*Path) { +func (ps Paths) Less(i, j int) bool { + //return ps[i].valve.rate > ps[j].valve.rate + /*if ps[i].sumRate == ps[j].sumRate { return len(ps[i].path) < len(ps[j].path) + }*/ + return ps[i].sumRate > ps[j].sumRate +} +func (ps Paths) Find(name string) *Path { for _, p := range ps { if p.name == name { return &p @@ -64,71 +79,94 @@ func (ps Paths) Find(name string) (*Path) { } type Valves map[string]*Valve + +func (vs Valves) SumRates(names Strings) int { + sum := 0 + for _, n := range names { + sum += vs[n].rate + } + return sum +} func (vs Valves) String() string { var out string - for k,v := range vs { - out += "["+k+"]:"+v.String()+"\n" + for k, v := range vs { + out += "[" + k + "]:" + v.String() + "\n" } return out } + +func (vs Valves) FindRoutes(start string, steps int, visited Strings) Paths { + steps-- + // opening the valve costs 1 + if steps <= 1 { + //fmt.Println("route exhausted") + return Paths{} + } + visited = append(visited, start) + paths := vs.GetPaths(start, visited, steps+1) + //fmt.Println("FindRoutes", steps, start) fmt.Println(paths) + for i, p := range paths { + paths[i].sumRate = paths[i].valve.rate * steps + paths[i].nested = vs.FindRoutes(p.name, steps-len(p.path), visited) + if len(paths[i].nested) > 0 { + sort.Sort(paths[i].nested) + paths[i].sumRate += paths[i].nested[0].sumRate + } + } + + return paths +} func (vs Valves) FindPath(start, end string) (Path, bool) { - var path Path - path.valve = vs[end] - path.name = end - var upcoming []Step - visited := make(map[string]string) // name:parent - - upcoming = append(upcoming, Step{name:start,parent:""}) - for len(upcoming)>0{ - cur:=upcoming[0].name - parent:=upcoming[0].parent + var path Path + path.valve = vs[end] + path.name = end + var upcoming []Step + visited := make(map[string]string) // name:parent + + upcoming = append(upcoming, Step{name: start, parent: ""}) + for len(upcoming) > 0 { + cur := upcoming[0].name + parent := upcoming[0].parent upcoming = upcoming[1:] - if _,exists:=visited[cur];exists { + if _, exists := visited[cur]; exists { continue } - visited[cur]=parent - for _,s:=range vs[cur].connections{ - if _,exists:=visited[s];!exists { - //if start=="BB"&& end=="JJ"{ - // fmt.Printf("(bb->jj) cur %s, trying nested %s\n", cur,s) - //} + visited[cur] = parent + for _, s := range vs[cur].connections { + if _, exists := visited[s]; !exists { if s == end { - //fmt.Println("start,end,s,cur,parent:", start,end,s,cur,parent) - //fmt.Println("visited:",visited) - // unwind - // parent <- cur < s path.path = append(path.path, s, cur) - if parent!="" { + if parent != "" { path.path = append(path.path, parent) } - c:=parent//visited[parent] - for c!="" { - c=visited[c] - if c!="" { + c := parent + for c != "" { + c = visited[c] + if c != "" { path.path = append(path.path, c) } } - //if start=="BB"&& end=="JJ"{ - //fmt.Println("path:", start, end, path.path) - //} return path, true } else { - upcoming = append(upcoming, Step{name:s,parent:cur}) + upcoming = append(upcoming, Step{name: s, parent: cur}) } - } + } } } - - return path, false + + return path, false } -func (vs Valves) GetPaths(start string) Paths { + +func (vs Valves) GetPaths(start string, excluded Strings, limit int) Paths { var paths Paths - for _,v:= range vs { - if v.name==start || v.open || v.rate == 0 { continue } - if p,found:=vs.FindPath(start,v.name);found{ + for _, v := range vs { + if v.name == start || v.open || v.rate == 0 || excluded.Has(v.name) { + continue + } + if p, found := vs.FindPath(start, v.name); found && (len(p.path) <= limit) { paths = append(paths, p) } else { - log.Fatal("no path:", start, v.name) + //log.Fatal("no path:", start, v.name) } } sort.Sort(paths) @@ -136,9 +174,10 @@ func (vs Valves) GetPaths(start string) Paths { } type Strings []string + func (ss Strings) Has(s string) bool { - for _, s1:=range ss { - if s1==s { + for _, s1 := range ss { + if s1 == s { return true } } @@ -166,59 +205,72 @@ func day16(input_file string) { for scanner.Scan() { in := scanner.Text() in1, in2, found := strings.Cut(in, "; ") - if !found {log.Fatal("parsing error")} + if !found { + log.Fatal("parsing error") + } var vname string var vrate int cnt, err := fmt.Sscanf(in1, "Valve %s has flow rate=%d", &vname, &vrate) - if cnt!=2 || err!=nil {log.Fatal("parsing error:",err)} + if cnt != 2 || err != nil { + log.Fatal("parsing error:", err) + } in2s := strings.SplitN(in2, " ", 5) conns_s := in2s[4] conns := strings.Split(conns_s, ", ") - valves[vname] = &Valve{name:vname, rate:vrate, connections:conns} - + valves[vname] = &Valve{name: vname, rate: vrate, connections: conns} + } if err = scanner.Err(); err != nil { log.Fatal(err) } - fmt.Print(valves) - fmt.Println("--------") + //fmt.Print(valves) - rate:=0 - pressure:=0 - v:=valves["AA"] - for i:=1;i<=30;{ - paths:=valves.GetPaths(v.name) - //fmt.Println("~~~>", v.name) + paths := valves.FindRoutes("AA", 29, Strings{}) + //fmt.Println("FindRoutes path:", paths) + var pathway Strings + sort.Sort(paths) + /*for _, p:=range paths{ + fmt.Println(p.sumRate) + }*/ + p := &paths[0] + for { + pathway = append(pathway, p.name) + //fmt.Println(p.sumRate) + if len(p.nested) > 0 { + sort.Sort(p.nested) + p = &p.nested[0] + } else { + break + } + } + fmt.Println(pathway) + + rate := 0 + pressure := 0 + v := valves["AA"] + for i := 1; i <= 30; { + //paths := valves.GetPaths(v.name, Strings{}) fmt.Println("~~~>", v.name) //fmt.Println(paths) - if len(paths) > 0 { - left:=30-i - var path *Path - for j, p := range paths { - if len(p.path) <= left { - path = &paths[j] - break - } - } - if path == nil { - break - } - //path:=paths[0] - fmt.Printf("%s -> %s (%d)\n", v.name, path.name, len(path.path)) + if len(pathway) > 0 { + //left := 30 - i + path, _ := valves.FindPath(v.name, pathway[0]) + plen := len(path.path) + pathway = pathway[1:] + fmt.Printf("%s -> %s (%d)\n", v.name, path.name, plen) //fmt.Println(path) - pressure+=rate*(len(path.path)) - i+=len(path.path)-1 - v=valves[path.name] + pressure += rate * plen + i += plen - 1 + v = valves[path.name] v.open = true - rate+=v.rate + rate += v.rate fmt.Printf("[%d] rate:%d, pressure:%d\n", i, rate, pressure) - i++ } else { //fmt.Printf("[%d] no more paths\n", i) - i++ - pressure+=rate + pressure += rate } + i++ //fmt.Println("===============") } fmt.Printf("rate:%d, pressure:%d\n", rate, pressure) @@ -227,3 +279,6 @@ func day16(input_file string) { //2591 too high //1634 too low //2096 too low +//2128 wrong +//2342 wrong +//2297 wrong