129 lines
2.0 KiB
Go
129 lines
2.0 KiB
Go
|
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("Sum:", 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
|
||
|
}
|