package main import ( "bufio" "fmt" "log" "os" "strconv" "strings" ) var top *Node func main() { inp := StdinToString() hackTheGibson(inp) part1() part2() } var nodeIndex byte func hackTheGibson(inp string) { parts := strings.Split(inp, " ") var rem []int for i := range parts { rem = append(rem, Atoi(parts[i])) } top, _ = parseNode(rem) } func parseNode(vals []int) (*Node, []int) { id := nodeIndex nodeIndex = nodeIndex + 1 retN := &Node{ id: id, ChildCount: vals[0], MetaCount: vals[1], } rem := vals[2:] children := retN.ChildCount if children == 0 { retN.Metadata = rem[:retN.MetaCount] return retN, rem[retN.MetaCount:] } else { var cN *Node for children > 0 { cN, rem = parseNode(rem) retN.Children = append(retN.Children, cN) children-- } retN.Metadata = rem[:retN.MetaCount] rem = rem[retN.MetaCount:] } return retN, rem } func part1() { fmt.Println("= Part 1 =") fmt.Println(top.recurMetaSum()) } func part2() { fmt.Println("= Part 2 =") fmt.Println(top.value()) } type Node struct { id byte ChildCount int MetaCount int Metadata []int Children []*Node } var indent int func (n *Node) value() int { var ret int if n.ChildCount == 0 { for _, v := range n.Metadata { ret += v } } else { indent++ for _, v := range n.Metadata { if v > 0 && v <= n.ChildCount { ret += n.Children[v-1].value() } } indent-- } return ret } func (n *Node) recurMetaSum() int { var ret int for _, v := range n.Children { ret += v.recurMetaSum() } for _, v := range n.Metadata { ret += v } return ret } func (n *Node) string() string { ret := fmt.Sprintf("[ %d: %d %d ]", n.id, n.ChildCount, n.MetaCount) return ret } func StdinToString() string { var input string scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { input = input + scanner.Text() } return input } func Atoi(i string) int { var ret int var err error if ret, err = strconv.Atoi(i); err != nil { log.Fatal("Invalid Atoi") } return ret }