mirror of
https://github.com/Threnklyn/advent-of-code-go.git
synced 2026-05-18 19:13:27 +02:00
2015-day7: memo-ed graph dfs
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user