RYELL5E4C3USLBBYJGITRHGLLIN4FCU76JUFHVWGYHZNSCKGBT5AC
package main
import (
"bufio"
"log"
"math"
"os"
"regexp"
"strconv"
"strings"
)
func main() {
if err := myMain(); err != nil {
log.Println(err)
}
}
func myMain() error {
testExplode := []struct {
in string
out string
}{
{"[[[[[9,8],1],2],3],4]", "[[[[0,9],2],3],4]"},
{"[7,[6,[5,[4,[3,2]]]]]", "[7,[6,[5,[7,0]]]]"},
{"[[6,[5,[4,[3,2]]]],1]", "[[6,[5,[7,0]]],3]"},
{"[[3,[2,[1,[7,3]]]],[6,[5,[4,[3,2]]]]]", "[[3,[2,[8,0]]],[9,[5,[4,[3,2]]]]]"},
{"[[3,[2,[8,0]]],[9,[5,[4,[3,2]]]]]", "[[3,[2,[8,0]]],[9,[5,[7,0]]]]"},
{"[[[[[4,3],4],4],[7,[[8,4],9]]],[1,1]]", "[[[[0,7],4],[7,[[8,4],9]]],[1,1]]"},
{"[[[[0,7],4],[7,[[8,4],9]]],[1,1]]", "[[[[0,7],4],[15,[0,13]]],[1,1]]"},
{"[[[[0,7],4],[[7,8],[0,[6,7]]]],[1,1]]", "[[[[0,7],4],[[7,8],[6,0]]],[8,1]]"},
}
for _, tc := range testExplode {
got := explode(tc.in)
if got != tc.out {
log.Fatalf("\nwant:\t%q\ngot:\t%q", tc.out, got)
}
}
testMagnitude := []struct {
in string
out int
}{
{"[[1,2],[[3,4],5]]", 143},
{"[[[[1,1],[2,2]],[3,3]],[4,4]]", 445},
{"[[[[0,7],4],[[7,8],[6,0]]],[8,1]]", 1384},
{"[[[[8,7],[7,7]],[[8,6],[7,7]]],[[[0,7],[6,6]],[8,7]]]", 3488},
}
for _, tc := range testMagnitude {
got, _ := magnitude(tc.in, 0)
if got != tc.out {
log.Fatalf("\nwant:\t%d\ngot:\t%d", tc.out, got)
}
}
in, err := parseInput("input.txt")
if err != nil {
return err
}
var ret string
for _, st := range in {
if ret == "" {
ret = st
} else {
ret = reduce("[" + ret + "," + st + "]")
}
}
log.Println(magnitude(ret, 0))
return nil
}
func magnitude(in string, pos int) (int, int) {
left, right := -1, -1
var rght bool
var skip int
for i := pos; i < len(in); i++ {
if in[i] == ']' {
skip = i - pos + 1
break
}
if in[i] == '[' {
var p int
if rght {
right, p = magnitude(in, i+1)
} else {
left, p = magnitude(in, i+1)
}
i += p
continue
}
switch in[i] {
case ',':
rght = true
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
tmp, err := strconv.Atoi(string(in[i]))
if err != nil {
log.Panicln(err)
}
if rght {
right = tmp
} else {
left = tmp
}
}
}
// log.Println("RETURN:", left, right)
if left == -1 || right == -1 {
return left + right + 1, skip
}
return 3*left + 2*right, skip
}
func reduce(in string) string {
if next := explode(in); next != in {
in = reduce(next)
} else if next := split(in); next != in {
in = reduce(next)
}
return in
}
func explode(in string) string {
var count int
for i, ch := range in {
if ch == '[' {
count++
if count == 5 {
return doExplode(in, i)
}
}
if ch == ']' {
count--
}
}
return in
}
var number = regexp.MustCompile(`\d+`)
func doExplode(in string, pivot int) string {
// log.Println(in[:pivot], in[pivot:])
lefts := number.FindAllStringSubmatchIndex(in[:pivot+1], -1)
rights := number.FindAllStringSubmatchIndex(in[pivot:], 3)
// log.Println("L:", lefts, "R:", rights)
// Exploding left item: 1st from rights
expLeft := []int{pivot + rights[0][0], pivot + rights[0][1]}
// Exploding right item: 2nd from rights
expRight := []int{pivot + rights[1][0], pivot + rights[1][1]}
var l, r []int
if len(lefts) > 0 {
l = []int{lefts[len(lefts)-1][0], lefts[len(lefts)-1][1]}
// log.Println("left value:", in[l[0]:l[1]])
}
if len(rights) > 2 { // rights has to be at least 3 long
r = []int{pivot + rights[2][0], pivot + rights[2][1]}
// log.Println("right value:", in[r[0]:r[1]])
}
ret := strings.Builder{}
if len(l) != 0 {
ret.WriteString(in[:l[0]])
leftNum, err := strconv.Atoi(in[l[0]:l[1]])
if err != nil {
log.Panicln(err)
}
explodeLeftNum, err := strconv.Atoi(in[expLeft[0]:expLeft[1]])
if err != nil {
log.Panicln(err)
}
ret.WriteString(strconv.Itoa(leftNum + explodeLeftNum))
ret.WriteString(in[l[1] : expLeft[0]-1])
} else {
ret.WriteString(in[:expLeft[0]-1])
}
ret.WriteByte('0')
if len(r) != 0 {
ret.WriteString(in[expRight[1]+1 : r[0]])
rightNum, err := strconv.Atoi(in[r[0]:r[1]])
if err != nil {
log.Panicln(err)
}
explodeRightNum, err := strconv.Atoi(in[expRight[0]:expRight[1]])
if err != nil {
log.Panicln(err)
}
ret.WriteString(strconv.Itoa(rightNum + explodeRightNum))
ret.WriteString(in[r[1]:])
} else {
ret.WriteString(in[expRight[1]+1:])
}
// log.Println("after doExplode", ret.String())
return ret.String()
}
var twodigit = regexp.MustCompile(`\d\d+`)
func split(in string) string {
if split := twodigit.FindStringIndex(in); len(split) != 0 {
in = doSplit(in, split)
}
return in
}
func doSplit(in string, split []int) string {
ret := strings.Builder{}
ret.WriteString(in[:split[0]])
sno, err := strconv.Atoi(in[split[0]:split[1]])
if err != nil {
log.Panicln(err)
}
ret.WriteByte('[')
ret.WriteString(strconv.Itoa(sno / 2))
ret.WriteByte(',')
ret.WriteString(strconv.Itoa(int(math.Ceil(float64(sno) / 2))))
ret.WriteByte(']')
ret.WriteString(in[split[1]:])
// log.Println("after doSplit", ret.String())
return ret.String()
}
func parseInput(fileName string) ([]string, error) {
ret := []string{}
fd, err := os.Open(fileName)
if err != nil {
return ret, err
}
defer fd.Close()
buf := bufio.NewScanner(fd)
for buf.Scan() {
ret = append(ret, buf.Text())
}
return ret, nil
}
[[[3,9],[7,2]],[[8,4],[[5,6],0]]]
[[[1,[4,9]],[[1,8],[1,5]]],[[[2,6],[6,7]],[[4,6],[9,0]]]]
[[[[9,2],1],[[0,7],[9,6]]],[[5,9],[7,[6,9]]]]
[8,9]
[[4,[6,1]],[2,[[6,7],2]]]
[[6,[[4,1],5]],[4,9]]
[[[0,6],[8,[8,5]]],[6,9]]
[[0,[1,0]],[[8,[7,4]],[[1,1],[5,0]]]]
[[[1,[0,1]],6],[1,9]]
[[2,[[9,0],[6,1]]],[[8,4],[5,7]]]
[[[[5,3],[0,9]],[1,[0,7]]],[[9,0],[2,[2,0]]]]
[[2,[2,[6,8]]],[[9,[5,4]],[4,[3,4]]]]
[[[[4,0],[7,0]],[[4,8],[5,8]]],[[[7,2],[2,2]],[[3,3],3]]]
[[5,0],5]
[[8,[[5,0],2]],[6,[5,1]]]
[[[9,[8,8]],[8,7]],[[[4,2],4],[[5,1],[4,8]]]]
[[[[1,1],3],5],9]
[[[[1,7],[6,5]],5],[[0,6],0]]
[[9,6],2]
[[[2,[0,8]],[8,[2,1]]],5]
[[[9,[3,7]],3],[0,[5,9]]]
[[[2,[1,7]],6],[[7,[8,2]],[[8,2],8]]]
[[[[1,2],1],5],2]
[4,[8,[3,9]]]
[[[[8,9],[6,0]],[[1,6],7]],8]
[[2,[8,1]],3]
[[2,2],[[8,[0,2]],[[5,0],5]]]
[9,[2,[[6,1],[8,9]]]]
[[4,[[6,6],4]],[[[9,3],[3,1]],5]]
[[[7,8],1],0]
[[[8,8],[[1,0],7]],[4,6]]
[9,8]
[[[[4,2],9],[[9,9],7]],[7,[9,[5,8]]]]
[[4,[4,[3,3]]],8]
[0,2]
[[4,[5,5]],[9,[[6,9],4]]]
[[[7,3],[[1,2],6]],[[[2,4],[6,7]],[[5,0],9]]]
[[[[2,0],5],[4,5]],[[[6,5],[6,0]],[1,[3,4]]]]
[[3,[6,8]],[[[3,0],0],[[2,8],7]]]
[[[4,[6,2]],[9,[4,1]]],[8,[3,4]]]
[[[6,[6,8]],[7,[2,0]]],[4,[[8,7],[1,6]]]]
[2,[0,[4,0]]]
[[[[0,5],1],8],[[9,[0,3]],3]]
[[[3,[5,2]],[3,[3,2]]],[[[7,3],1],7]]
[1,[[[1,8],[1,7]],0]]
[[8,6],[[0,4],4]]
[[[8,2],[4,6]],3]
[5,[[[7,5],[4,5]],[0,2]]]
[[3,[3,6]],6]
[[[[6,8],[5,7]],[[7,3],5]],[[8,[4,8]],8]]
[[[[5,8],[3,1]],[[3,7],[7,0]]],[[9,7],0]]
[[2,[[5,3],8]],0]
[0,[2,8]]
[[8,9],[[[2,2],[4,7]],[[4,0],1]]]
[[[[3,0],8],[[7,3],[6,1]]],[[3,8],[4,2]]]
[[[[6,7],[4,3]],[[3,9],5]],8]
[[[7,7],[[3,4],7]],[[[0,4],1],9]]
[[[7,5],5],[[2,[9,9]],[0,[3,5]]]]
[[[[3,3],[6,1]],[5,8]],[[4,7],[8,1]]]
[[[0,[7,3]],[6,[7,2]]],[[0,8],7]]
[[[2,7],[9,7]],[8,[3,8]]]
[[[0,2],6],[[9,[6,5]],[[3,9],1]]]
[[7,[[3,4],[2,8]]],[[[4,1],4],7]]
[[3,[[3,4],6]],[[3,9],[[4,5],[3,0]]]]
[[[5,[5,1]],[2,4]],[1,[[1,6],6]]]
[[[5,6],[[1,3],[5,0]]],[[[4,1],8],[5,5]]]
[[[[2,0],7],[[8,9],1]],[[[4,0],[1,6]],1]]
[[[2,0],[[4,2],[9,9]]],[4,9]]
[[[[1,9],6],2],[[5,4],[2,4]]]
[[[[4,1],[4,5]],[[2,3],2]],[3,[[8,8],1]]]
[[[[8,1],0],[2,2]],[[2,[7,1]],1]]
[[[7,4],[[1,3],5]],[[6,8],[[0,0],2]]]
[[[1,2],8],[[[1,7],[4,0]],[[8,2],8]]]
[[[0,8],[3,6]],[[[5,3],7],[9,7]]]
[[4,6],[[[7,9],[7,5]],[[4,6],[8,4]]]]
[[[[7,3],0],[[6,2],[7,2]]],[9,[[8,0],3]]]
[[[3,0],1],[[2,3],1]]
[[[5,[8,6]],[[1,2],2]],[[[1,4],6],[5,[7,1]]]]
[[[[1,5],8],[0,0]],4]
[[[7,[6,8]],3],[[5,1],[[2,8],[4,6]]]]
[3,[[[5,8],[4,5]],[[7,7],8]]]
[[6,[7,[8,2]]],[[9,0],0]]
[[[8,[7,6]],1],[[2,4],6]]
[[[[0,4],2],[0,7]],[6,6]]
[1,[[1,9],[9,3]]]
[[[[5,2],[5,3]],[[9,0],4]],2]
[[[[5,5],3],[7,[1,2]]],[6,[7,2]]]
[[[[2,1],3],8],[[2,[8,2]],[7,4]]]
[[8,[9,[1,8]]],[[[4,4],[0,6]],[6,3]]]
[[[1,6],[1,[2,5]]],0]
[[[[0,1],[7,2]],[[7,2],3]],[2,[[7,8],[0,7]]]]
[[[[1,8],8],[[5,7],[3,4]]],[[[2,5],[7,4]],[[8,4],9]]]
[[[2,2],[5,[1,0]]],[[[6,6],[3,0]],[[8,5],5]]]
[[[[8,2],[4,8]],[9,4]],[[8,[7,9]],0]]
[[3,[5,[2,4]]],[[[8,1],0],[[0,4],[4,5]]]]
[[5,[9,[3,8]]],[4,[1,[5,2]]]]
[[[3,[0,6]],[7,[8,7]]],[[6,8],[[8,7],0]]]
[[[[0,2],5],[4,6]],3]
[[6,7],[[1,[4,6]],9]]
[7,[3,[[8,8],5]]]
[[[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]]]
module main
go 1.17