DEV Community

Discussion on: AoC Day 8: Memory Maneuver

Collapse
 
bjarnemagnussen profile image
Bjarne Magnussen

Here is my Golang solution for today's problem. It was more easy for me to solve today, but made me learn to use pointers in Golang to consume the input string. I don't think this is necessarily the best way to use pointers, but I liked the simplicity in this case.

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

// A simple structure of a node.
type node struct {
    children []node
    metaData []int
}

// readLines reads a whole file into memory
// and returns a slice of its lines.
func readLines(path string) ([]string, error) {
    file, err := os.Open(path)
    if err != nil {
        return nil, err
    }
    defer file.Close()

    var lines []string
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        lines = append(lines, scanner.Text())
    }
    return lines, scanner.Err()
}

// function to consume elements from the input string.
func consume(parseNodes *[]string) int {
    i, _ := strconv.Atoi((*parseNodes)[0])
    *parseNodes = (*parseNodes)[1:]
    return i
}

// function to parse a node from the input string.
func readNode(parseNodes *[]string) node {
    // Read header
    numChildren := consume(parseNodes)
    numMetaData := consume(parseNodes)
    // Read children:
    var children []node
    for c := 0; c < numChildren; c++ {
        children = append(children, readNode(parseNodes))
    }
    // Read meta data:
    var metaData []int
    for m := 0; m < numMetaData; m++ {
        metaData = append(metaData, consume(parseNodes))
    }
    // Create and return node:
    return node{children: children, metaData: metaData}
}

// function to get the sum of meta data from a given node.
func getMeta(node node) int {
    // Read meta data of this node:
    meta := node.metaData
    // Run through each child and get meta data:
    for _, c := range node.children {
        meta = append(meta, getMeta(c))
    }
    var sum int
    // Sum the meta data:
    for _, m := range meta {
        sum += m
    }
    return sum
}

// function to get the value of a given node.
func getValue(node node) int {
    numChildren := len(node.children)
    var value int
    if numChildren == 0 {
        // If the node has no children return just the sum of
        // the meta data for thid node:
        value = getMeta(node)
    } else {
        // If this node has children return the sum of the
        // values for each child:
        for _, m := range node.metaData {
            m-- // for correct indexing
            if m >= 0 && m < numChildren {
                // Only get value if index is not out of bound
                value += getValue(node.children[m])
            }
        }
    }
    return value
}

func main() {
    data, err := readLines("input")
    if err != nil {
        panic(err)
    }
    nodeString := strings.Split(data[0], " ")

    root := readNode(&nodeString)

    fmt.Println("Part 1:")
    fmt.Println(getMeta(root))

    fmt.Println("Part 2:")
    fmt.Println(getValue(root))

}