package main import ( "bufio" "fmt" "os" "strconv" "time" ) func mustAtoi(line rune) int { i, _ := strconv.Atoi(string(line)) return i } func main() { start := time.Now() partOne() duration := time.Since(start) partTwo() duration2 := time.Since(start) fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration) } func makeScanner(test bool) *bufio.Scanner { var f *os.File if test { f, _ = os.Open("inputs/testinput") } else { f, _ = os.Open("inputs/input") } reader := bufio.NewReader(f) return bufio.NewScanner(reader) } type pair struct { parent *pair leftp *pair left int rightp *pair right int } func Parse(raw string) *pair { root := &pair{} var current *pair left := true for _, v := range raw { switch v { case '[': if current == nil { current = root } else { p := &pair{parent: current} if left { current.leftp = p } else { current.rightp = p } current = p } left = true case ']': current = current.parent case ',': left = false case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': if left { current.left = mustAtoi(v) } else { current.right = mustAtoi(v) } case ' ': continue default: panic("what the: " + string(v)) } } return root } func (p *pair) String() string { var left, right string if p.leftp == nil { left = fmt.Sprintf("%d", p.left) } else { left = p.leftp.String() } if p.rightp == nil { right = fmt.Sprintf("%d", p.right) } else { right = p.rightp.String() } return fmt.Sprintf("[%s,%s]", left, right) } func (p *pair) Magnitude() int { left := 0 right := 0 if p.leftp == nil { left = p.left } else { left = p.leftp.Magnitude() } if p.rightp == nil { right = p.right } else { right = p.rightp.Magnitude() } return left*3 + right*2 } func Add(left, right *pair) *pair { return &pair{ leftp: left, rightp: right, } } func Reduce(p *pair) { for { if MustExplode(0, p) { Explode(p) } else if MustSplit(p) { Split(p) } else { break } } } func Split(p *pair) bool { if p.left > 9 { p.leftp = &pair{ left: p.left / 2, right: (p.left / 2) + (p.left % 2), } p.left = 0 return true } if p.leftp != nil { m := Split(p.leftp) if m { return true } } if p.right > 9 { p.rightp = &pair{ left: p.right / 2, right: (p.right / 2) + (p.right % 2), } p.right = 0 return true } if p.rightp != nil { m := Split(p.rightp) if m { return true } } return false } func MustSplit(p *pair) bool { if p.left > 9 || p.right > 9 { return true } if p.leftp != nil { m := MustSplit(p.leftp) if m { return true } } if p.rightp != nil { m := MustSplit(p.rightp) if m { return true } } return false } func MustExplode(depth int, p *pair) bool { if depth >= 4 { return true } if p.leftp != nil { m := MustExplode(depth+1, p.leftp) if m { return true } } if p.rightp != nil { m := MustExplode(depth+1, p.rightp) if m { return true } } return false } func Explode(p *pair) { } func partOne() { scanner := makeScanner(false) scanner.Scan() line := scanner.Text() total := Parse(line) for scanner.Scan() { line := scanner.Text() total = Add(total, Parse(line)) } fmt.Println(total) } func partTwo() { scanner := makeScanner(false) for scanner.Scan() { // line := scanner.Text() } }