diff --git a/intcode.go b/intcode.go index 455f4e9..390f5d0 100644 --- a/intcode.go +++ b/intcode.go @@ -1,6 +1,7 @@ package aoc2019 import ( + "log" "reflect" "strconv" "strings" @@ -8,6 +9,8 @@ import ( "github.com/pkg/errors" ) +var intcodeDebugging = false + type opCodeFlag int64 const ( @@ -88,8 +91,9 @@ func parseIntcode(code string) ([]int64, error) { return out, nil } -func executeIntcode(code []int64, in, out chan int64) ([]int64, error) { +func executeIntcode(code []int64, in interface{}, out chan int64) ([]int64, error) { var ( + inCB func() (int64, error) pos int64 relativeBase int64 ) @@ -98,6 +102,17 @@ func executeIntcode(code []int64, in, out chan int64) ([]int64, error) { defer close(out) } + switch in.(type) { + case nil: + inCB = func() (int64, error) { return 0, errors.New("No input available") } + case chan int64: + inCB = func() (int64, error) { return <-(in.(chan int64)), nil } + case func() (int64, error): + inCB = in.(func() (int64, error)) + default: + return nil, errors.New("Unsupported input type") + } + transformPos := func(param int64, op opCode, write bool) int64 { var addr int64 @@ -156,6 +171,11 @@ func executeIntcode(code []int64, in, out chan int64) ([]int64, error) { // Position is expected to be an OpCode op := parseOpCode(code[pos]) + + if intcodeDebugging { + log.Printf("OpCode execution: %#v", op) + } + switch op.Type { case opCodeTypeAddition: // p1 + p2 => p3 @@ -167,7 +187,11 @@ func executeIntcode(code []int64, in, out chan int64) ([]int64, error) { pos += 4 case opCodeTypeInput: // in => p1 - setParamValue(1, <-in, op) + v, err := inCB() + if err != nil { + return nil, errors.Wrap(err, "Unable to read input") + } + setParamValue(1, v, op) pos += 2 case opCodeTypeOutput: // p1 => out