package main import ( "fmt" h "git.bullercodeworks.com/brian/adventofcode/helpers" ) func main() { inp := h.StdinToStringSlice() var build *SNum for i := range inp { wrk, _ := ParseSNum(inp[i]) if build == nil { build = wrk } else { build = build.add(wrk) } } fmt.Println(build) v := build.needsExplode(0) fmt.Println("Needs Explode:", v) v.explode() fmt.Println(build) /* full := inp[0] for i := 1; i < len(inp); i++ { full = fmt.Sprintf("[%s,%s]", full, inp[i]) } */ } type SNum struct { parent, left, right *SNum regular bool value int } // ParseSNum returns an SNum and what's left of inp // after it was produced func ParseSNum(inp string) (*SNum, string) { // inp should always start with either a number or a '[' var rest string s := SNum{} if inp[0] == '[' { s.regular = false s.left, rest = ParseSNum(inp[1:]) s.right, rest = ParseSNum(rest[1:]) s.left.parent = &s s.right.parent = &s return &s, rest[1:] } else { s.regular = true var num []byte for i := range inp { if inp[i] >= '0' && inp[i] <= '9' { num = append(num, inp[i]) } else { s.value = h.Atoi(string(num)) return &s, inp[i:] } } } return &s, rest } func (s *SNum) needsExplode(depth int) *SNum { if depth == 4 && !s.regular { return s } if s.regular { return nil } if tst := s.left.needsExplode(depth + 1); tst != nil { return tst } else if tst := s.right.needsExplode(depth + 1); tst != nil { return tst } return nil } func (s *SNum) explode() { if s.parent == nil { return } s.parent.addToRegularRightOf(s.right.value, s) s.parent.addToRegularLeftOf(s.left.value, s) } func (s *SNum) addToRegularLeftOf(v int, c *SNum) { if s.right.regular { s.right.value += v } else { if s.right != nil && s.right == c { r := s.left.findRightmostRegular() if r != nil { r.value += v } } else if s.left != nil && s.left == c { s.parent.addToRegularLeftOf(v, s) } } } func (s *SNum) addToRegularRightOf(v int, c *SNum) { if s.left.regular { s.left.value += v } else if s.left != nil && s.left == c { l := s.right.findLeftmostRegular() if l != nil { l.value += v } } else if s.right != nil && s.right == c { s.parent.addToRegularRightOf(v, s) } } func (s *SNum) contains(n *SNum) bool { return s == n || s.left.contains(n) || s.right.contains(n) } func (s *SNum) findRightmostRegular() *SNum { if s.regular { return s } return s.right.findRightmostRegular() } func (s *SNum) findLeftmostRegular() *SNum { if s.regular { return s } return s.left.findLeftmostRegular() } func (s *SNum) add(n *SNum) *SNum { return &SNum{ left: s, right: n, } } func (s SNum) String() string { if s.regular { return fmt.Sprintf("%d", s.value) } return fmt.Sprintf("[%s,%s]", s.left, s.right) }