Skip to content

Commit 89e6374

Browse files
committed
feat(2017): refactor day 7
Refactored Day 7 of 2017 to use the common framework. Successfully migrated solution and integrated it into the runner.
1 parent cb72411 commit 89e6374

3 files changed

Lines changed: 1295 additions & 0 deletions

File tree

2017/days/7/day07.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
"strconv"
7+
"strings"
8+
9+
"github.com/markkovari/advent_of_code/aoc-go-common"
10+
)
11+
12+
type Day07 struct{}
13+
14+
type Node struct {
15+
Name string
16+
Weight int
17+
Edges []string
18+
}
19+
20+
func (d Day07) Part1(input string) string {
21+
graph := parse(input)
22+
allNames := make(map[string]bool)
23+
for k := range graph { allNames[k] = true }
24+
for _, node := range graph {
25+
for _, name := range node.Edges {
26+
delete(allNames, name)
27+
}
28+
}
29+
var nameAtBottom string
30+
for name := range allNames { nameAtBottom = name }
31+
return nameAtBottom
32+
}
33+
34+
func (d Day07) Part2(input string) string {
35+
graph := parse(input)
36+
currentNode := d.Part1(input)
37+
weightCalculator := calcWeight(graph)
38+
39+
var siblings []string
40+
for {
41+
weightToDependents := make(map[int][]string)
42+
for _, dependentName := range graph[currentNode].Edges {
43+
weight := weightCalculator(dependentName)
44+
weightToDependents[weight] = append(weightToDependents[weight], dependentName)
45+
}
46+
47+
if len(weightToDependents) > 1 {
48+
siblings = graph[currentNode].Edges
49+
for _, names := range weightToDependents {
50+
if len(names) == 1 {
51+
currentNode = names[0]
52+
}
53+
}
54+
} else if len(weightToDependents) == 1 {
55+
currentWeight := weightCalculator(currentNode)
56+
for _, sib := range siblings {
57+
if sib != currentNode {
58+
desiredWeight := weightCalculator(sib)
59+
return fmt.Sprintf("%d", graph[currentNode].Weight-(currentWeight-desiredWeight))
60+
}
61+
}
62+
} else {
63+
break
64+
}
65+
}
66+
return "0"
67+
}
68+
69+
func parse(input string) map[string]Node {
70+
lines := strings.Split(input, "\n")
71+
graph := make(map[string]Node)
72+
re := regexp.MustCompile(`([a-z]+) \((\d+)\)(?: -> (.*))?`)
73+
for _, l := range lines {
74+
if l == "" { continue }
75+
caps := re.FindStringSubmatch(l)
76+
name := caps[1]
77+
weight, _ := strconv.Atoi(caps[2])
78+
var edges []string
79+
if caps[3] != "" {
80+
edges = strings.Split(caps[3], ", ")
81+
}
82+
graph[name] = Node{Name: name, Weight: weight, Edges: edges}
83+
}
84+
return graph
85+
}
86+
87+
func calcWeight(graph map[string]Node) func(string) int {
88+
memo := make(map[string]int)
89+
var closureFunc func(string) int
90+
closureFunc = func(rootName string) int {
91+
if wt, ok := memo[rootName]; ok { return wt }
92+
sum := graph[rootName].Weight
93+
for _, dependent := range graph[rootName].Edges {
94+
sum += closureFunc(dependent)
95+
}
96+
memo[rootName] = sum
97+
return sum
98+
}
99+
return closureFunc
100+
}
101+
102+
func main() {
103+
common.Run(2017, 7, Day07{})
104+
}

0 commit comments

Comments
 (0)