package main import ( "bufio" "fmt" "os" "strconv" "github.com/davecgh/go-spew/spew" ) type Puzzle struct { Root *Node } func (p *Puzzle) Solution1() int { return p.Root.SumMetadata() } func (p *Puzzle) Solution2() int { return p.Root.Value() } /* 2 3 0 3 10 11 12 1 1 0 1 99 2 1 1 2 A---------------------------------- B----------- C----------- D----- */ type Node struct { Children []*Node Metadata []int } func (n *Node) SumMetadata() int { total := 0 for _, child := range n.Children { total += child.SumMetadata() } for _, meta := range n.Metadata { total += meta } return total } func (n *Node) Value() int { if len(n.Children) == 0 { return n.SumMetadata() } total := 0 for _, meta := range n.Metadata { if meta > 0 && meta <= len(n.Children) { total += n.Children[meta-1].Value() } } return total } func readNode(scanner *bufio.Scanner) *Node { if !scanner.Scan() { return nil } if err := scanner.Err(); err != nil { panic(err.Error()) } children, _ := strconv.Atoi(scanner.Text()) if !scanner.Scan() { return nil } if err := scanner.Err(); err != nil { panic(err.Error()) } metadata, _ := strconv.Atoi(scanner.Text()) node := Node{ Children: make([]*Node, children), Metadata: make([]int, metadata), } for t := 0; t < children; t++ { node.Children[t] = readNode(scanner) } for t := 0; t < metadata; t++ { if !scanner.Scan() { return nil } if err := scanner.Err(); err != nil { panic(err.Error()) } meta, _ := strconv.Atoi(scanner.Text()) node.Metadata[t] = meta } return &node } func main() { input, err := os.Open("input.txt") if err != nil { panic(err.Error()) } defer input.Close() scanner := bufio.NewScanner(input) scanner.Split(bufio.ScanWords) p := Puzzle{} p.Root = readNode(scanner) spew.Dump(p.Root) fmt.Println(p.Solution1()) fmt.Println(p.Solution2()) }