Skip to content

Commit

Permalink
adds day 2021\18 chaos
Browse files Browse the repository at this point in the history
  • Loading branch information
jdrst committed Dec 18, 2021
1 parent 27b45b3 commit e1ec59c
Show file tree
Hide file tree
Showing 3 changed files with 579 additions and 0 deletions.
100 changes: 100 additions & 0 deletions 2021/18/input.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
[[6,[[9,4],[5,1]]],[[[6,5],[9,4]],2]]
[[7,3],[[3,[5,5]],8]]
[8,[[5,0],[[0,2],3]]]
[[[8,7],[[2,0],[7,5]]],1]
[[[2,[6,1]],[7,[6,1]]],[[7,3],1]]
[[2,[9,[0,0]]],[[[9,7],1],0]]
[[[[8,4],[2,3]],[[6,4],4]],0]
[[[1,3],1],[[3,8],[[2,3],[9,5]]]]
[[7,[5,9]],[[7,[9,1]],[3,[9,6]]]]
[[[5,3],5],[[[8,8],[5,6]],[6,5]]]
[3,[[4,1],3]]
[[[5,[2,0]],[[9,5],[9,2]]],[[[1,7],[6,9]],[[6,3],[8,6]]]]
[[[[9,3],[2,4]],[6,9]],[[[9,7],1],[[1,9],[2,9]]]]
[3,[[6,1],8]]
[[[[8,8],8],[[3,9],[9,3]]],[[8,8],[[7,1],[6,5]]]]
[[[8,9],[[2,7],6]],[[[2,9],[8,4]],[1,6]]]
[[4,[[4,4],0]],[[8,[1,8]],[9,[7,3]]]]
[[[[3,0],[7,2]],[[9,5],[9,5]]],[5,[0,[5,7]]]]
[5,[1,[[4,0],[8,5]]]]
[[0,0],[[[9,8],1],[[5,2],[4,6]]]]
[[5,8],[6,[[5,2],1]]]
[[1,[[1,4],8]],8]
[[[[1,7],[7,1]],[4,[8,0]]],0]
[[[[5,9],0],[0,8]],[2,[[6,2],2]]]
[2,[4,3]]
[[[[4,0],[2,2]],7],[[8,7],[[8,1],1]]]
[[[[6,0],[1,6]],[2,[6,2]]],[[9,6],[7,[8,2]]]]
[[3,5],[[9,[4,0]],[[6,5],[1,0]]]]
[[[[6,0],7],[8,[0,1]]],[[7,6],[[7,1],[9,6]]]]
[[3,[[6,4],4]],[0,[[3,5],[8,6]]]]
[[8,[[1,8],0]],[1,[[0,1],[6,2]]]]
[[6,[5,[5,4]]],9]
[[[[0,7],3],[[7,7],[1,2]]],[8,[2,1]]]
[[[7,[1,4]],[5,[9,8]]],[1,8]]
[[[0,7],[[3,6],[2,4]]],[[7,4],1]]
[[[5,[8,2]],[[4,9],[5,3]]],4]
[[5,[[3,3],0]],8]
[7,[2,1]]
[[3,8],[[[5,3],8],[[3,4],6]]]
[[[2,[0,9]],[0,5]],0]
[[6,[7,6]],[[[2,6],2],[[8,9],5]]]
[[[0,0],[[1,9],[0,6]]],[[5,[8,8]],[[6,9],[3,7]]]]
[[[[4,6],[8,4]],[2,[3,8]]],[8,0]]
[[0,0],[2,[[6,2],6]]]
[[[6,0],3],8]
[[[[6,1],[4,8]],[2,[3,0]]],7]
[[[0,[1,8]],[[8,1],6]],3]
[2,[0,2]]
[[[[9,6],8],[[1,9],[7,8]]],[[[0,6],[8,8]],[6,[2,3]]]]
[[0,[6,[7,4]]],[[[0,9],[2,3]],[[8,8],0]]]
[[[0,1],[7,[4,9]]],[[3,9],8]]
[[[1,9],7],[[0,5],[5,[7,9]]]]
[[[9,[2,5]],2],[7,[1,[7,7]]]]
[[[[0,4],[7,3]],2],5]
[[8,[7,4]],[[[8,2],[7,3]],[1,[7,8]]]]
[[[0,4],[[3,7],9]],6]
[[5,[[9,2],[7,0]]],[[8,2],[[1,4],9]]]
[2,[[[9,6],9],[2,3]]]
[[5,[[3,5],[3,8]]],[4,[2,9]]]
[[[5,2],[4,[4,1]]],[[[1,0],[8,7]],[[8,7],8]]]
[[4,[4,[0,9]]],[[1,8],4]]
[[[3,[4,0]],[[8,8],[1,6]]],[[4,0],[1,2]]]
[[[1,[1,8]],2],[[6,2],[9,[8,5]]]]
[9,[[[8,8],[8,3]],[3,[1,3]]]]
[[[2,[4,5]],[4,1]],[1,[[8,6],[1,5]]]]
[[0,[5,[7,6]]],[[8,6],[[9,9],1]]]
[[[5,[5,2]],2],[[[1,4],[3,7]],[4,3]]]
[[5,[[9,8],0]],[7,[[0,8],[7,8]]]]
[[[[8,0],6],[2,1]],[[[6,3],[3,1]],[[7,6],[7,2]]]]
[[[3,3],6],[2,[[8,4],5]]]
[[[6,[5,3]],[[6,4],3]],[[[4,8],0],[[0,6],[1,4]]]]
[[[3,[6,4]],2],[[[8,8],4],[[8,6],6]]]
[[[[6,9],1],[3,8]],[[5,[4,6]],2]]
[[5,6],3]
[[[5,[8,6]],[[4,2],[1,1]]],[[[0,7],[6,3]],[9,[7,7]]]]
[[7,[[4,0],6]],[[4,[6,4]],8]]
[[5,[[2,0],[9,4]]],[[[4,6],1],[[2,8],[8,5]]]]
[[[[3,5],[0,4]],[[5,0],3]],[[1,[8,9]],7]]
[[[[6,6],6],[[6,6],[4,3]]],0]
[[5,[2,5]],[6,[[7,8],2]]]
[[[7,[5,5]],[[7,4],[6,7]]],0]
[[[3,3],3],[[1,9],[0,[9,2]]]]
[[9,[4,1]],[6,[2,[9,6]]]]
[[4,7],[9,[3,0]]]
[[[8,2],[[9,8],[4,2]]],[[2,[3,7]],[7,[3,1]]]]
[[[[1,8],2],[0,[6,5]]],[[[2,7],[8,6]],[[8,9],[8,5]]]]
[[[7,[2,9]],[9,0]],5]
[[5,[2,[1,5]]],[0,7]]
[4,[[0,[0,3]],[[0,5],[9,0]]]]
[0,[[4,4],[[8,4],[3,8]]]]
[[[[4,9],0],[[4,4],9]],[[[6,1],[8,9]],[7,[2,3]]]]
[[[[4,2],[7,4]],0],[[5,[0,6]],[[0,5],4]]]
[[[1,0],8],[[[2,8],[2,9]],3]]
[[6,[1,[9,9]]],[2,2]]
[[[8,[6,7]],[6,[6,6]]],[[[2,3],5],0]]
[[[7,[6,9]],[[7,8],[2,8]]],[[4,[5,1]],5]]
[[[[6,3],[1,4]],7],[[9,1],[3,1]]]
[5,[[8,5],[[7,5],4]]]
[[4,[[4,0],0]],[6,[1,1]]]
[[[5,[9,2]],[9,0]],[[5,[5,7]],4]]
294 changes: 294 additions & 0 deletions 2021/18/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
package main

import (
"fmt"
"math"
"strings"

"github.com/jdrst/adventofgo/util"
)

type sfnum struct {
parent, left, right *sfnum
first, second *int
}

func main() {
fmt.Printf("First part: %v\n", partOne(util.ReadFile("input.txt")))
fmt.Printf("Second part: %v\n", partTwo(util.ReadFile("input.txt")))
}

func partOne(file util.File) int {
lines := file.AsLines()

for i := 0; i < len(lines)-1; i++ {
left := toSfnum(string(lines[i]))
right := toSfnum(string(lines[i+1]))

newLeft := &sfnum{left: left, right: right}
newLeft.left.parent = newLeft
newLeft.right.parent = newLeft
newLeft.reduce()
lines[i+1] = util.Line(newLeft.String())
}

last := toSfnum(string(lines[len(lines)-1]))
last.reduce()
return *last.magnitude()
}

func partTwo(file util.File) int {
lines := file.AsLines()

max := math.MinInt
for i := 0; i < len(lines); i++ {
for j := 0; j < len(lines); j++ {
if j == i {
continue
}
left := toSfnum(string(lines[i]))
right := toSfnum(string(lines[j]))
result := &sfnum{left: left, right: right}
result.left.parent = result
result.right.parent = result
result.reduce()
mag := result.magnitude()
if *mag > max {
max = *mag
}
}
}
for i := 0; i < len(lines); i++ {
for j := 0; j < len(lines); j++ {
if j == i {
continue
}
left := toSfnum(string(lines[i]))
right := toSfnum(string(lines[j]))
result := &sfnum{left: right, right: left}
result.left.parent = result
result.right.parent = result
result.reduce()
mag := result.magnitude()
if *mag > max {
max = *mag
}
}
}
return max
}

func (num *sfnum) magnitude() *int {
if num.left != nil {
num.first = num.left.magnitude()
}
if num.right != nil {
num.second = num.right.magnitude()
}
res := *num.first*3 + *num.second*2
return &res
}

func (num *sfnum) explode() {
// fmt.Printf("exploding [%v,%v]\n", *num.first, *num.second)
left, isLeft := findRegularLeft(num)
if left != nil {
if isLeft {
new := *left.first + *num.first
left.first = &new
} else {
new := *left.second + *num.first
left.second = &new
}
}
right, isLeft := findRegularRight(num)
if right != nil {
if isLeft {
new := *right.first + *num.second
right.first = &new
} else {
new := *right.second + *num.second
right.second = &new
}
}
null := 0
if num.parent.left == num {
num.parent.first = &null
num.parent.left = nil
}
if num.parent.right == num {
num.parent.second = &null
num.parent.right = nil
}
}

func (num *sfnum) split(left bool) {
split := func(from int) *sfnum {
newLeft := from / 2
newRight := from / 2
if from%2 == 1 {
newRight++
}
return &sfnum{first: &newLeft, second: &newRight, parent: num}
}
if left {
// fmt.Printf("splitting [%v,]\n", *num.first)
num.left = split(*num.first)
num.first = nil
} else {
// fmt.Printf("splitting [,%v]\n", *num.second)
num.right = split(*num.second)
num.second = nil
}
}

func (num *sfnum) reduce() {
noResult := true
explode:
for noResult {
// fmt.Println(num)
noResult = num.explodeRecursive(0)
}
noResult = true
for noResult {
// fmt.Println(num)
noResult = num.splitRecursive()
if noResult {
goto explode
}
}
}

func (num *sfnum) explodeRecursive(depth int) bool {
res := false
if depth > 3 {
num.explode()
return true
}
if num.left != nil {
res = num.left.explodeRecursive(depth + 1)
}
if !res && num.right != nil {
res = num.right.explodeRecursive(depth + 1)
}
return res
}

func (num *sfnum) splitRecursive() bool {
res := false
if num.left != nil {
res = num.left.splitRecursive()
}
if !res && num.first != nil && *num.first > 9 {
num.split(true)
return true
}
if !res && num.right != nil {
res = num.right.splitRecursive()
}
if !res && num.second != nil && *num.second > 9 {
num.split(false)
return true
}
return res
}

func findRegularLeft(num *sfnum) (res *sfnum, isFirst bool) {
if num.parent == nil {
return nil, true
}
if num.parent.first != nil {
return num.parent, true
}
if num.parent.left != num {
res := findRightMost(num.parent.left)
return res, false
}
return findRegularLeft(num.parent)
}

func findRegularRight(num *sfnum) (res *sfnum, isFirst bool) {
if num.parent == nil {
return nil, false
}
if num.parent.second != nil {
return num.parent, false
}
if num.parent.right != num {
res := findLeftMost(num.parent.right)
return res, true
}
return findRegularRight(num.parent)
}

func findLeftMost(num *sfnum) *sfnum {
if num.left != nil {
return findLeftMost(num.left)
}
if num.first != nil {
return num
}
return nil
}

func findRightMost(num *sfnum) *sfnum {
if num.right != nil {
return findRightMost(num.right)
}
if num.second != nil {
return num
}
return nil
}

func toSfnum(s string) *sfnum {
num := &sfnum{}
isLeft := true
for _, c := range s[1 : len(s)-1] {
switch c {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
if isLeft {
fst := int(c - '0')
num.first = &fst
} else {
snd := int(c - '0')
num.second = &snd
isLeft = true
}
case ',':
isLeft = false
case '[':
child := &sfnum{parent: num}
if isLeft {
num.left = child
} else {
num.right = child
isLeft = true
}
num = child
case ']':
num = num.parent
}
}
return num
}

func (num *sfnum) String() string {
sb := strings.Builder{}
sb.WriteRune('[')
if num.left != nil {
sb.WriteString(fmt.Sprint(num.left))
}
if num.first != nil {
sb.WriteString(fmt.Sprint(*num.first))
}
sb.WriteRune(',')
if num.right != nil {
sb.WriteString(fmt.Sprint(num.right))
}
if num.second != nil {
sb.WriteString(fmt.Sprint(*num.second))
}
sb.WriteRune(']')
return sb.String()
}
Loading

0 comments on commit e1ec59c

Please sign in to comment.