adventofcode/2018/day08/day08.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(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
}