mirror of
https://github.com/Threnklyn/advent-of-code-go.git
synced 2026-06-07 20:53:30 +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