2021 Day 18 Complete
This commit is contained in:
parent
8a4a437947
commit
4c8c1f2a9c
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
|
|
||||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||||
)
|
)
|
||||||
@ -11,25 +12,34 @@ func main() {
|
|||||||
|
|
||||||
var build *SNum
|
var build *SNum
|
||||||
for i := range inp {
|
for i := range inp {
|
||||||
wrk, _ := ParseSNum(inp[i])
|
wrk := ParseSNum(inp[i])
|
||||||
if build == nil {
|
if build == nil {
|
||||||
build = wrk
|
build = wrk
|
||||||
} else {
|
} else {
|
||||||
build = build.add(wrk)
|
build = build.add(wrk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println(build)
|
fmt.Println()
|
||||||
v := build.needsExplode(0)
|
fmt.Println("# Part 1")
|
||||||
fmt.Println("Needs Explode:", v)
|
fmt.Println("Magnitude:", build.magnitude())
|
||||||
v.explode()
|
fmt.Println()
|
||||||
fmt.Println(build)
|
fmt.Println("# Part 2")
|
||||||
|
highest := h.MIN_INT
|
||||||
|
for i := 0; i < len(inp)-1; i++ {
|
||||||
|
for j := i + 1; j < len(inp); j++ {
|
||||||
|
w1 := ParseSNum(inp[i]).add(ParseSNum(inp[j]))
|
||||||
|
w2 := ParseSNum(inp[j]).add(ParseSNum(inp[i]))
|
||||||
|
|
||||||
/*
|
m1, m2 := w1.magnitude(), w2.magnitude()
|
||||||
full := inp[0]
|
if m1 >= m2 && m1 > highest {
|
||||||
for i := 1; i < len(inp); i++ {
|
highest = m1
|
||||||
full = fmt.Sprintf("[%s,%s]", full, inp[i])
|
} else if m2 > highest {
|
||||||
|
highest = m2
|
||||||
}
|
}
|
||||||
*/
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("Highest magnitude from 2:", highest)
|
||||||
|
//3225 is too low
|
||||||
}
|
}
|
||||||
|
|
||||||
type SNum struct {
|
type SNum struct {
|
||||||
@ -38,16 +48,21 @@ type SNum struct {
|
|||||||
value int
|
value int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ParseSNum(inp string) *SNum {
|
||||||
|
s, _ := rParseSNum(inp)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
// ParseSNum returns an SNum and what's left of inp
|
// ParseSNum returns an SNum and what's left of inp
|
||||||
// after it was produced
|
// after it was produced
|
||||||
func ParseSNum(inp string) (*SNum, string) {
|
func rParseSNum(inp string) (*SNum, string) {
|
||||||
// inp should always start with either a number or a '['
|
// inp should always start with either a number or a '['
|
||||||
var rest string
|
var rest string
|
||||||
s := SNum{}
|
s := SNum{}
|
||||||
if inp[0] == '[' {
|
if inp[0] == '[' {
|
||||||
s.regular = false
|
s.regular = false
|
||||||
s.left, rest = ParseSNum(inp[1:])
|
s.left, rest = rParseSNum(inp[1:])
|
||||||
s.right, rest = ParseSNum(rest[1:])
|
s.right, rest = rParseSNum(rest[1:])
|
||||||
s.left.parent = &s
|
s.left.parent = &s
|
||||||
s.right.parent = &s
|
s.right.parent = &s
|
||||||
return &s, rest[1:]
|
return &s, rest[1:]
|
||||||
@ -66,13 +81,21 @@ func ParseSNum(inp string) (*SNum, string) {
|
|||||||
return &s, rest
|
return &s, rest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When exploding or splitting, we need to find the leftmost pair that matches the condition
|
||||||
func (s *SNum) needsExplode(depth int) *SNum {
|
func (s *SNum) needsExplode(depth int) *SNum {
|
||||||
if depth == 4 && !s.regular {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
if s.regular {
|
if s.regular {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if depth >= 4 {
|
||||||
|
if !s.left.regular {
|
||||||
|
return s.left.needsExplode(depth + 1)
|
||||||
|
} else if !s.right.regular {
|
||||||
|
return s.right.needsExplode(depth + 1)
|
||||||
|
} else {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if tst := s.left.needsExplode(depth + 1); tst != nil {
|
if tst := s.left.needsExplode(depth + 1); tst != nil {
|
||||||
return tst
|
return tst
|
||||||
} else if tst := s.right.needsExplode(depth + 1); tst != nil {
|
} else if tst := s.right.needsExplode(depth + 1); tst != nil {
|
||||||
@ -85,34 +108,69 @@ func (s *SNum) explode() {
|
|||||||
if s.parent == nil {
|
if s.parent == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.parent.addToRegularRightOf(s.right.value, s)
|
|
||||||
s.parent.addToRegularLeftOf(s.left.value, s)
|
s.parent.addToRegularLeftOf(s.left.value, s)
|
||||||
|
s.parent.addToRegularRightOf(s.right.value, s)
|
||||||
|
// Replace s with a regular number that just equals 0
|
||||||
|
s.regular, s.value = true, 0
|
||||||
|
s.right, s.left = nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SNum) needsSplit() *SNum {
|
||||||
|
if s == nil || (s.regular && s.value >= 10) {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
if tst := s.left.needsSplit(); tst != nil {
|
||||||
|
return tst
|
||||||
|
} else if tst := s.right.needsSplit(); tst != nil {
|
||||||
|
return tst
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SNum) split() {
|
||||||
|
if s.parent == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := int(math.Floor(float64(s.value) / 2))
|
||||||
|
r := int(math.Ceil(float64(s.value) / 2))
|
||||||
|
n := SNum{
|
||||||
|
parent: s.parent,
|
||||||
|
left: &SNum{
|
||||||
|
regular: true,
|
||||||
|
value: int(l),
|
||||||
|
},
|
||||||
|
right: &SNum{
|
||||||
|
regular: true,
|
||||||
|
value: int(r),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
n.left.parent = &n
|
||||||
|
n.right.parent = &n
|
||||||
|
if s.parent.left == s {
|
||||||
|
s.parent.left = &n
|
||||||
|
} else if s.parent.right == s {
|
||||||
|
s.parent.right = &n
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SNum) addToRegularLeftOf(v int, c *SNum) {
|
func (s *SNum) addToRegularLeftOf(v int, c *SNum) {
|
||||||
if s.right.regular {
|
if s == nil || v == 0 {
|
||||||
s.right.value += v
|
return
|
||||||
} else {
|
|
||||||
if s.right != nil && s.right == c {
|
|
||||||
r := s.left.findRightmostRegular()
|
|
||||||
if r != nil {
|
|
||||||
r.value += v
|
|
||||||
}
|
}
|
||||||
|
if s.right != nil && s.right == c {
|
||||||
|
s.left.addToRightmostRegular(v)
|
||||||
} else if s.left != nil && s.left == c {
|
} else if s.left != nil && s.left == c {
|
||||||
s.parent.addToRegularLeftOf(v, s)
|
s.parent.addToRegularLeftOf(v, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SNum) addToRegularRightOf(v int, c *SNum) {
|
func (s *SNum) addToRegularRightOf(v int, c *SNum) {
|
||||||
if s.left.regular {
|
if s == nil || v == 0 {
|
||||||
s.left.value += v
|
return
|
||||||
} 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 {
|
if s.left == c {
|
||||||
|
s.right.addToLeftmostRegular(v)
|
||||||
|
} else if s.right == c {
|
||||||
s.parent.addToRegularRightOf(v, s)
|
s.parent.addToRegularRightOf(v, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,24 +179,49 @@ func (s *SNum) contains(n *SNum) bool {
|
|||||||
return s == n || s.left.contains(n) || s.right.contains(n)
|
return s == n || s.left.contains(n) || s.right.contains(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SNum) findRightmostRegular() *SNum {
|
func (s *SNum) addToRightmostRegular(v int) {
|
||||||
if s.regular {
|
if s.regular {
|
||||||
return s
|
s.value += v
|
||||||
|
} else if s.right != nil {
|
||||||
|
s.right.addToRightmostRegular(v)
|
||||||
}
|
}
|
||||||
return s.right.findRightmostRegular()
|
|
||||||
}
|
}
|
||||||
func (s *SNum) findLeftmostRegular() *SNum {
|
func (s *SNum) addToLeftmostRegular(v int) {
|
||||||
if s.regular {
|
if s.regular {
|
||||||
return s
|
s.value += v
|
||||||
|
} else if s.left != nil {
|
||||||
|
s.left.addToLeftmostRegular(v)
|
||||||
}
|
}
|
||||||
return s.left.findLeftmostRegular()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SNum) add(n *SNum) *SNum {
|
func (s *SNum) add(n *SNum) *SNum {
|
||||||
return &SNum{
|
wrk := SNum{
|
||||||
left: s,
|
left: s,
|
||||||
right: n,
|
right: n,
|
||||||
}
|
}
|
||||||
|
s.parent = &wrk
|
||||||
|
n.parent = &wrk
|
||||||
|
|
||||||
|
changed := true
|
||||||
|
for changed {
|
||||||
|
changed = false
|
||||||
|
if v := wrk.needsExplode(0); v != nil {
|
||||||
|
v.explode()
|
||||||
|
changed = true
|
||||||
|
} else if v := wrk.needsSplit(); v != nil {
|
||||||
|
v.split()
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &wrk
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SNum) magnitude() int {
|
||||||
|
if s.regular {
|
||||||
|
return s.value
|
||||||
|
}
|
||||||
|
return s.left.magnitude()*3 + s.right.magnitude()*2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s SNum) String() string {
|
func (s SNum) String() string {
|
||||||
|
2
2021/day18/testinput2
Normal file
2
2021/day18/testinput2
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[[[[4,3],4],4],[7,[[8,4],9]]]
|
||||||
|
[1,1]
|
10
2021/day18/testinput3
Normal file
10
2021/day18/testinput3
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]]
|
||||||
|
[[[5,[2,8]],4],[5,[[9,9],0]]]
|
||||||
|
[6,[[[6,2],[5,6]],[[7,6],[4,7]]]]
|
||||||
|
[[[6,[0,7]],[0,9]],[4,[9,[9,0]]]]
|
||||||
|
[[[7,[6,4]],[3,[1,3]]],[[[5,5],1],9]]
|
||||||
|
[[6,[[7,3],[3,2]]],[[[3,8],[5,7]],4]]
|
||||||
|
[[[[5,4],[7,7]],8],[[8,3],8]]
|
||||||
|
[[9,3],[[9,9],[6,[4,9]]]]
|
||||||
|
[[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]]
|
||||||
|
[[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]]
|
Loading…
Reference in New Issue
Block a user