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())
}