First (unsuccessful) attempt at day 7.1.

This commit is contained in:
Anna Rose 2018-12-09 23:46:35 -05:00
parent 0388b57112
commit f6ea56d266
No known key found for this signature in database
GPG Key ID: 8D9ACA841015C59A
6 changed files with 238 additions and 0 deletions

29
2018/day07-1.go Normal file
View File

@ -0,0 +1,29 @@
package main
import (
"fmt"
"strings"
"internal/tree"
"internal/util"
)
func main() {
data := util.ReadInput()
// Build a tree of dependencies.
root := tree.BuildDependencyTree(data)
// Walk the tree and determine the correct ordering.
order := tree.FindOrder(root)
output := strings.Builder{}
for _, node := range order {
if node.Name == 0 {
continue
}
output.WriteRune(node.Name)
}
fmt.Println(output.String())
}

View File

@ -0,0 +1,44 @@
// BreadthFirstOrder and its companion functions ended up not giving the
// right solution, but I'm leaving them here as a useful generic tree
// algorithm.
package tree
func BreadthFirstOrder(root *Node) []*Node {
seen := make(map[rune]bool)
return breadthFirstOrderR(root, seen)
}
func findTreeRoot(depMap map[rune]*Node) *Node {
for _, node := range depMap {
if len(node.Parents) == 0 {
return node
}
}
return nil
}
func breadthFirstOrderR(node *Node, seen map[rune]bool) []*Node {
order := []*Node{}
// handle root
if len(node.Parents) == 0 {
order = append(order, node)
seen[node.Name] = true
}
// add children we haven't seen before
for _, child := range node.Children {
if _, ok := seen[child.Name]; !ok {
order = append(order, child)
seen[child.Name] = true
}
}
// recurse
for _, child := range node.Children {
order = append(order, breadthFirstOrderR(child, seen)...)
}
return order
}

View File

@ -0,0 +1,33 @@
package tree
import (
"fmt"
)
func DebugPrintTree(root *Node) {
debugPrintTreeR(root, 0)
}
func debugPrintTreeR(node *Node, level int) {
for i := 0; i < level; i++ {
fmt.Printf(" ")
}
DebugPrintNode(node)
for _, child := range node.Children {
debugPrintTreeR(child, level+1)
}
}
func DebugPrintNode(node *Node) {
fmt.Printf("%c @ %p. Children: ", node.Name, node)
for _, child := range node.Children {
fmt.Printf("%c ", child.Name)
}
fmt.Printf("Parents: ")
for _, parent := range node.Parents {
fmt.Printf("%c ", parent.Name)
}
fmt.Printf("\n")
}

View File

@ -0,0 +1,51 @@
package tree
import "fmt" // debug
// FindOrder determines the correct order according to these rules:
// 1. A node cannot come before all of its parents have been included.
// 2. At any given time, the lowest-lettered step must be executed.
func FindOrder(root *Node) []*Node {
seen := make(map[rune]bool)
return findOrderR(root, seen)
}
func findOrderR(node *Node, seen map[rune]bool) []*Node {
order := []*Node{}
// debug
fmt.Printf("In node: %c | Children: ", node.Name)
for _, child := range node.Children {
fmt.Printf("%c ", child.Name)
}
fmt.Printf("| Parents: ")
for _, parent := range node.Parents {
fmt.Printf("%c ", parent.Name)
}
fmt.Println()
// end debug
// add the node, but only if all its parents have been seen
if len(node.Parents) == 0 {
seen[node.Name] = true
} else {
for _, parent := range node.Parents {
if _, ok := seen[parent.Name]; !ok {
return order
}
}
if _, ok := seen[node.Name]; !ok {
order = append(order, node)
fmt.Printf("Added node: %c\n", node.Name)
seen[node.Name] = true
}
}
// recurse
for _, child := range node.Children {
order = append(order, findOrderR(child, seen)...)
}
return order
}

View File

@ -0,0 +1,67 @@
package tree
import (
"regexp"
"sort"
)
type Node struct {
Name rune
Parents []*Node
Children []*Node
}
// BuildDependencyTree parses the input and returns the root node.
func BuildDependencyTree(data []string) *Node {
depMap := make(map[rune]*Node)
parentRegex := regexp.MustCompile("Step ([A-Z]) must")
childRegex := regexp.MustCompile("step ([A-Z]) can begin")
for _, line := range data {
parent := rune(parentRegex.FindSubmatch([]byte(line))[1][0])
child := rune(childRegex.FindSubmatch([]byte(line))[1][0])
// Create the nodes if they don't exist
if depMap[parent] == nil {
depMap[parent] = &Node{Name: parent}
}
if depMap[child] == nil {
depMap[child] = &Node{Name: child}
}
// Get each node and add the dependency info.
pNode := depMap[parent]
cNode := depMap[child]
pNode.Children = append(pNode.Children, cNode)
cNode.Parents = append(cNode.Parents, pNode)
}
// sort the children in each node
for _, node := range depMap {
sortChildren(node)
}
return BuildTreeRoot(depMap)
}
func sortChildren(node *Node) {
children := node.Children
sort.Slice(children[:], func(i, j int) bool {
return children[i].Name < children[j].Name
})
}
func BuildTreeRoot(depMap map[rune]*Node) *Node {
root := &Node{Name: 0}
for _, node := range depMap {
if len(node.Parents) == 0 {
root.Children = append(root.Children, node)
node.Parents = append(node.Parents, root)
}
}
sortChildren(root)
return root
}

View File

@ -0,0 +1,14 @@
package util
func ReverseString(s string) string {
runes := []rune(s)
i := 0
j := len(runes) - 1
for i < j {
runes[i], runes[j] = runes[j], runes[i]
i++
j--
}
return string(runes)
}