2015-day7: memo-ed graph dfs

This commit is contained in:
alexchao26
2020-12-26 14:07:21 -05:00
parent 7a8155b606
commit 2738d6a271
2 changed files with 123 additions and 0 deletions
+76
View File
@@ -0,0 +1,76 @@
package main
import (
"flag"
"fmt"
"math"
"regexp"
"strings"
"github.com/alexchao26/advent-of-code-go/cast"
"github.com/alexchao26/advent-of-code-go/util"
)
func main() {
var part int
flag.IntVar(&part, "part", 1, "part 1 or 2")
flag.Parse()
fmt.Println("Running part", part)
ans := someAssemblyRequired(util.ReadFile("./input.txt"), part)
fmt.Println("Output:", ans)
}
func someAssemblyRequired(input string, part int) int {
wireToRule := map[string]string{}
// generate graph of wires to their source rule
for _, inst := range strings.Split(input, "\n") {
parts := strings.Split(inst, " -> ")
wireToRule[parts[1]] = parts[0]
}
aSignal := memoDFS(wireToRule, "a", map[string]int{})
if part == 1 {
return aSignal
}
// for part 2, override the value sent to wire b, then get output to a again
wireToRule["b"] = cast.ToString(aSignal)
return memoDFS(wireToRule, "a", map[string]int{})
}
func memoDFS(graph map[string]string, entry string, memo map[string]int) int {
if memoVal, ok := memo[entry]; ok {
return memoVal
}
// if it's a number, return the casted value
if regexp.MustCompile("[0-9]").MatchString(entry) {
return cast.ToInt(entry)
}
sourceRule := graph[entry]
parts := strings.Split(sourceRule, " ")
var result int
switch {
case len(parts) == 1:
result = memoDFS(graph, parts[0], memo)
case parts[0] == "NOT":
start := memoDFS(graph, parts[1], memo)
result = (math.MaxUint16) ^ start
case parts[1] == "AND":
result = memoDFS(graph, parts[0], memo) & memoDFS(graph, parts[2], memo)
case parts[1] == "OR":
result = memoDFS(graph, parts[0], memo) | memoDFS(graph, parts[2], memo)
case parts[1] == "LSHIFT":
result = memoDFS(graph, parts[0], memo) << memoDFS(graph, parts[2], memo)
case parts[1] == "RSHIFT":
result = memoDFS(graph, parts[0], memo) >> memoDFS(graph, parts[2], memo)
}
memo[entry] = result
return result
}
+47
View File
@@ -0,0 +1,47 @@
package main
import (
"testing"
"github.com/alexchao26/advent-of-code-go/util"
)
var exampleOutputH = `123 -> x
456 -> y
x AND y -> d
x OR y -> e
x LSHIFT 2 -> f
y RSHIFT 2 -> g
NOT x -> h
NOT y -> i
h -> a` // added last rule to output to a (same as real question)
// Expect these final registers
// d: 72
// e: 507
// f: 492
// g: 114
// h: 65412
// i: 65079
// x: 123
// y: 456
func Test_someAssemblyRequired(t *testing.T) {
tests := []struct {
name string
input string
part int
want int
}{
{"example h -> a", exampleOutputH, 1, 65412},
{"part1 actual", util.ReadFile("input.txt"), 1, 16076},
{"part2 actual", util.ReadFile("input.txt"), 2, 2797},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := someAssemblyRequired(tt.input, tt.part); got != tt.want {
t.Errorf("someAssemblyRequired() = %v, want %v", got, tt.want)
}
})
}
}