From 7cc0053b33a1668299e2028032d09e9e9dedd391 Mon Sep 17 00:00:00 2001 From: Brian Buller Date: Mon, 9 Dec 2019 07:32:24 -0600 Subject: [PATCH] 2019 day 9 Complete! --- 2019/day08/main.go | 17 +++++ 2019/day09/input | 1 + 2019/day09/main.go | 56 ++++++++++++++ 2019/day09/testinput1 | 1 + 2019/day09/testinput2 | 1 + 2019/day09/testinput3 | 1 + 2019/intcode-processor/processor.go | 109 ++++++++++++++++++++-------- 7 files changed, 156 insertions(+), 30 deletions(-) create mode 100644 2019/day08/main.go create mode 100644 2019/day09/input create mode 100644 2019/day09/main.go create mode 100644 2019/day09/testinput1 create mode 100644 2019/day09/testinput2 create mode 100644 2019/day09/testinput3 diff --git a/2019/day08/main.go b/2019/day08/main.go new file mode 100644 index 0000000..b0b7c12 --- /dev/null +++ b/2019/day08/main.go @@ -0,0 +1,17 @@ +package main + +import ( + helpers "git.bullercodeworks.com/brian/adventofcode/helpers" +) + +func main() { + inp := helpers.StdinToStringSlice() + part1(inp) + part2(inp) +} + +func part1(inp []string) { +} + +func part2(inp []string) { +} diff --git a/2019/day09/input b/2019/day09/input new file mode 100644 index 0000000..b54e3b1 --- /dev/null +++ b/2019/day09/input @@ -0,0 +1 @@ +1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1102,3,1,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,521,1,1028,1101,0,36,1000,1102,30,1,1005,1101,21,0,1013,1101,26,0,1006,1102,31,1,1017,1101,24,0,1007,1101,0,1,1021,1102,27,1,1019,1101,23,0,1010,1101,0,38,1012,1102,35,1,1001,1101,25,0,1003,1102,20,1,1004,1101,0,37,1009,1101,424,0,1023,1102,39,1,1008,1102,406,1,1027,1102,1,413,1026,1101,0,29,1002,1102,1,0,1020,1102,34,1,1014,1102,1,28,1018,1102,1,33,1011,1102,300,1,1025,1102,1,22,1015,1102,305,1,1024,1101,32,0,1016,1102,427,1,1022,1101,512,0,1029,109,14,1205,6,197,1001,64,1,64,1106,0,199,4,187,1002,64,2,64,109,-18,1207,8,19,63,1005,63,215,1105,1,221,4,205,1001,64,1,64,1002,64,2,64,109,10,1208,-1,28,63,1005,63,237,1106,0,243,4,227,1001,64,1,64,1002,64,2,64,109,-2,2102,1,0,63,1008,63,22,63,1005,63,263,1105,1,269,4,249,1001,64,1,64,1002,64,2,64,109,11,21107,40,39,0,1005,1015,289,1001,64,1,64,1106,0,291,4,275,1002,64,2,64,109,9,2105,1,0,4,297,1105,1,309,1001,64,1,64,1002,64,2,64,109,-13,2101,0,-5,63,1008,63,25,63,1005,63,329,1105,1,335,4,315,1001,64,1,64,1002,64,2,64,109,1,1206,8,353,4,341,1001,64,1,64,1105,1,353,1002,64,2,64,109,3,2108,37,-6,63,1005,63,375,4,359,1001,64,1,64,1106,0,375,1002,64,2,64,109,-16,1207,2,36,63,1005,63,397,4,381,1001,64,1,64,1105,1,397,1002,64,2,64,109,28,2106,0,0,1001,64,1,64,1106,0,415,4,403,1002,64,2,64,109,-3,2105,1,-1,1106,0,433,4,421,1001,64,1,64,1002,64,2,64,109,-12,2108,25,-6,63,1005,63,449,1105,1,455,4,439,1001,64,1,64,1002,64,2,64,109,-19,1202,8,1,63,1008,63,38,63,1005,63,479,1001,64,1,64,1105,1,481,4,461,1002,64,2,64,109,14,2107,25,0,63,1005,63,497,1105,1,503,4,487,1001,64,1,64,1002,64,2,64,109,24,2106,0,-3,4,509,1001,64,1,64,1105,1,521,1002,64,2,64,109,-20,1208,-2,37,63,1005,63,543,4,527,1001,64,1,64,1106,0,543,1002,64,2,64,109,7,21102,41,1,0,1008,1018,43,63,1005,63,563,1105,1,569,4,549,1001,64,1,64,1002,64,2,64,109,-7,1205,10,587,4,575,1001,64,1,64,1106,0,587,1002,64,2,64,109,-11,1202,5,1,63,1008,63,30,63,1005,63,609,4,593,1106,0,613,1001,64,1,64,1002,64,2,64,109,4,1201,5,0,63,1008,63,34,63,1005,63,637,1001,64,1,64,1105,1,639,4,619,1002,64,2,64,109,12,1206,5,651,1105,1,657,4,645,1001,64,1,64,1002,64,2,64,109,9,21101,42,0,-7,1008,1018,39,63,1005,63,677,1105,1,683,4,663,1001,64,1,64,1002,64,2,64,109,-2,21101,43,0,-8,1008,1015,43,63,1005,63,705,4,689,1106,0,709,1001,64,1,64,1002,64,2,64,109,-25,2107,38,10,63,1005,63,727,4,715,1106,0,731,1001,64,1,64,1002,64,2,64,109,7,2102,1,2,63,1008,63,24,63,1005,63,757,4,737,1001,64,1,64,1105,1,757,1002,64,2,64,109,-13,1201,10,0,63,1008,63,29,63,1005,63,779,4,763,1105,1,783,1001,64,1,64,1002,64,2,64,109,30,21108,44,41,-3,1005,1019,803,1001,64,1,64,1106,0,805,4,789,1002,64,2,64,109,-2,21102,45,1,-7,1008,1013,45,63,1005,63,827,4,811,1105,1,831,1001,64,1,64,1002,64,2,64,109,-16,21107,46,47,7,1005,1011,849,4,837,1106,0,853,1001,64,1,64,1002,64,2,64,109,9,21108,47,47,0,1005,1013,875,4,859,1001,64,1,64,1106,0,875,1002,64,2,64,109,-10,2101,0,2,63,1008,63,30,63,1005,63,901,4,881,1001,64,1,64,1105,1,901,4,64,99,21102,1,27,1,21102,1,915,0,1106,0,922,21201,1,51805,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,942,0,0,1106,0,922,22101,0,1,-1,21201,-2,-3,1,21101,0,957,0,1105,1,922,22201,1,-1,-2,1105,1,968,21201,-2,0,-2,109,-3,2105,1,0 diff --git a/2019/day09/main.go b/2019/day09/main.go new file mode 100644 index 0000000..479e2e6 --- /dev/null +++ b/2019/day09/main.go @@ -0,0 +1,56 @@ +package main + +import ( + "bufio" + "fmt" + "io/ioutil" + "os" + "strings" + "time" + + intcode "git.bullercodeworks.com/brian/adventofcode/2019/intcode-processor" + helpers "git.bullercodeworks.com/brian/adventofcode/helpers" +) + +func main() { + progFileName := "input" + if len(os.Args) > 1 { + progFileName = os.Args[1] + } + dat, err := ioutil.ReadFile(progFileName) + if err != nil { + fmt.Println("Error reading program file:", err.Error()) + os.Exit(1) + } + var prog []int + stringDat := strings.TrimSpace(string(dat)) + for _, v := range strings.Split(stringDat, ",") { + prog = append(prog, helpers.Atoi(v)) + } + part1(prog) +} + +func part1(inp []int) { + p := intcode.NewProgram(inp) + //p.EnableDebug() + go p.Run() + for p.State() != intcode.RET_DONE { + if p.State() == intcode.RET_ERR { + panic(p.Error()) + } + if p.NeedsInput() { + fmt.Print("Requesting Input: ") + reader := bufio.NewReader(os.Stdin) + inp, err := reader.ReadString('\n') + if err != nil { + fmt.Println("Input Error:", err.Error()) + } else { + p.Input(helpers.Atoi(strings.TrimSpace(inp))) + } + } + if p.NeedsOutput() { + fmt.Println(p.Output()) + } + time.Sleep(1) + } +} diff --git a/2019/day09/testinput1 b/2019/day09/testinput1 new file mode 100644 index 0000000..2ce40b6 --- /dev/null +++ b/2019/day09/testinput1 @@ -0,0 +1 @@ +109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99 diff --git a/2019/day09/testinput2 b/2019/day09/testinput2 new file mode 100644 index 0000000..50a032d --- /dev/null +++ b/2019/day09/testinput2 @@ -0,0 +1 @@ +1102,34915192,34915192,7,4,7,99,0 diff --git a/2019/day09/testinput3 b/2019/day09/testinput3 new file mode 100644 index 0000000..f0c3e19 --- /dev/null +++ b/2019/day09/testinput3 @@ -0,0 +1 @@ +104,1125899906842624,99 diff --git a/2019/intcode-processor/processor.go b/2019/intcode-processor/processor.go index 5ca9224..a230d76 100644 --- a/2019/intcode-processor/processor.go +++ b/2019/intcode-processor/processor.go @@ -15,12 +15,14 @@ const ( OP_JIF = 6 OP_ILT = 7 OP_IEQ = 8 + OP_RBS = 9 OP_EXT = 99 ) const ( MODE_POS = iota MODE_IMM + MODE_REL ) const ( @@ -33,6 +35,7 @@ type Program struct { originalCode []int code []int ptr int + relBase int state int error error @@ -41,6 +44,8 @@ type Program struct { input chan int waitingForOutput bool output chan int + + debug bool } func NewProgram(prog []int) *Program { @@ -52,6 +57,20 @@ func NewProgram(prog []int) *Program { return p } +func (p *Program) EnableDebug() { + p.debug = true +} + +func (p *Program) DisableDebug() { + p.debug = false +} + +func (p *Program) DebugLog(l string) { + if p.debug { + fmt.Print(l) + } +} + func (p *Program) Reset() { copy(p.code, p.originalCode) p.ptr = 0 @@ -61,6 +80,7 @@ func (p *Program) Reset() { p.waitingForOutput = false p.input = make(chan int) p.output = make(chan int) + p.relBase = 0 } func (p *Program) GetCode() []int { @@ -89,11 +109,13 @@ func (p *Program) Step() int { p.error = errors.New("Pointer Exception") return RET_ERR } + p.DebugLog(p.String() + "\n") intcode := p.readNext() p.ptr++ switch p.opCode(intcode) { case OP_ADD: v1, v2, v3 := p.readNextThree() + p.DebugLog(fmt.Sprintf("ADD %d (%d, %d, %d)\n", intcode, v1, v2, v3)) p.ptr = p.ptr + 3 p.opAdd(intcode, v1, v2, v3) if p.error != nil { @@ -102,6 +124,7 @@ func (p *Program) Step() int { return RET_OK case OP_MLT: v1, v2, v3 := p.readNextThree() + p.DebugLog(fmt.Sprintf("MLT %d (%d, %d, %d)\n", intcode, v1, v2, v3)) p.ptr = p.ptr + 3 p.opMult(intcode, v1, v2, v3) if p.error != nil { @@ -110,6 +133,7 @@ func (p *Program) Step() int { return RET_OK case OP_INP: v1 := p.readNext() + p.DebugLog(fmt.Sprintf("INP %d (%d)\n", intcode, v1)) p.ptr++ p.opInp(intcode, v1) if p.error != nil { @@ -119,6 +143,7 @@ func (p *Program) Step() int { case OP_OUT: v1 := p.readNext() p.ptr++ + p.DebugLog(fmt.Sprintf("OUT %d (%d)\n", intcode, v1)) p.opOut(intcode, v1) if p.error != nil { return RET_ERR @@ -126,6 +151,7 @@ func (p *Program) Step() int { return RET_OK case OP_JIT: v1, v2 := p.readNextTwo() + p.DebugLog(fmt.Sprintf("JIT %d (%d, %d)\n", intcode, v1, v2)) p.ptr = p.ptr + 2 p.opJumpIfTrue(intcode, v1, v2) if p.error != nil { @@ -134,6 +160,7 @@ func (p *Program) Step() int { return RET_OK case OP_JIF: v1, v2 := p.readNextTwo() + p.DebugLog(fmt.Sprintf("JIF %d (%d, %d)\n", intcode, v1, v2)) p.ptr = p.ptr + 2 p.opJumpIfFalse(intcode, v1, v2) if p.error != nil { @@ -142,6 +169,7 @@ func (p *Program) Step() int { return RET_OK case OP_ILT: v1, v2, dest := p.readNextThree() + p.DebugLog(fmt.Sprintf("ILT %d (%d, %d, %d)\n", intcode, v1, v2, dest)) p.ptr = p.ptr + 3 p.opIfLessThan(intcode, v1, v2, dest) if p.error != nil { @@ -150,24 +178,39 @@ func (p *Program) Step() int { return RET_OK case OP_IEQ: v1, v2, dest := p.readNextThree() + p.DebugLog(fmt.Sprintf("IEQ %d (%d, %d, %d)\n", intcode, v1, v2, dest)) p.ptr = p.ptr + 3 p.opIfEqual(intcode, v1, v2, dest) if p.error != nil { return RET_ERR } return RET_OK + case OP_RBS: + v1 := p.readNext() + p.DebugLog(fmt.Sprintf("RBS %d (%d)\n", intcode, v1)) + p.ptr = p.ptr + 1 + p.opModRelBase(intcode, v1) + if p.error != nil { + return RET_ERR + } + return RET_OK case OP_EXT: + p.DebugLog(fmt.Sprintf("EXT %d\n", intcode)) return RET_DONE } + p.error = errors.New(fmt.Sprintf("Invalid OpCode (%d)", intcode)) + p.DebugLog(p.String()) return RET_ERR } func (p *Program) GetProgramValueAt(idx int) int { + p.ensureLength(idx) return p.code[idx] } func (p *Program) SetProgramValueAt(idx, val int) { + p.ensureLength(idx) p.code[idx] = val } @@ -188,28 +231,48 @@ func (p *Program) paramMode(intcode, pNum int) int { return ((intcode - p.opCode(intcode)) / int(plc)) % 10 } -func (p *Program) readNext() int { - if len(p.code) <= p.ptr { - p.error = errors.New("Pointer Exception") +func (p *Program) ensureLength(idx int) { + for len(p.code) < idx+1 { + p.code = append(p.code, 0) } +} + +func (p *Program) readNext() int { + p.ensureLength(p.ptr) return p.code[p.ptr] } func (p *Program) readNextTwo() (int, int) { + p.ensureLength(p.ptr + 1) return p.code[p.ptr], p.code[p.ptr+1] } func (p *Program) readNextThree() (int, int, int) { + p.ensureLength(p.ptr + 2) return p.code[p.ptr], p.code[p.ptr+1], p.code[p.ptr+2] } func (p *Program) get(mode, v int) int { if mode == MODE_POS { + p.ensureLength(v) return p.code[v] + } else if mode == MODE_REL { + p.ensureLength(p.relBase + v) + return p.code[p.relBase+v] } return v } +func (p *Program) set(mode, idx, v int) { + if mode == MODE_POS { + p.ensureLength(idx) + p.code[idx] = v + } else if mode == MODE_REL { + p.ensureLength(p.relBase + idx) + p.code[p.relBase+idx] = v + } +} + func (p *Program) Input(v int) { p.input <- v p.waitingForInput = false @@ -223,30 +286,18 @@ func (p *Program) Output() int { func (p *Program) opAdd(intcode, a1, a2, dest int) { a1md, a2md, destmd := p.paramMode(intcode, 0), p.paramMode(intcode, 1), p.paramMode(intcode, 2) - if destmd != MODE_POS { - p.error = errors.New("Invalid Destination Mode") - p.state = RET_ERR - } - p.code[dest] = p.get(a1md, a1) + p.get(a2md, a2) + p.set(destmd, dest, p.get(a1md, a1)+p.get(a2md, a2)) } func (p *Program) opMult(intcode, a1, a2, dest int) { a1md, a2md, destmd := p.paramMode(intcode, 0), p.paramMode(intcode, 1), p.paramMode(intcode, 2) - if destmd != MODE_POS { - p.error = errors.New("Invalid Destination Mode") - p.state = RET_ERR - } - p.code[dest] = p.get(a1md, a1) * p.get(a2md, a2) + p.set(destmd, dest, p.get(a1md, a1)*p.get(a2md, a2)) } func (p *Program) opInp(intcode, dest int) { destmd := p.paramMode(intcode, 0) - if destmd != MODE_POS { - p.error = errors.New("Invalid Destination Mode") - p.state = RET_ERR - } p.waitingForInput = true - p.code[dest] = <-p.input + p.set(destmd, dest, <-p.input) p.waitingForInput = false } @@ -273,32 +324,30 @@ func (p *Program) opJumpIfFalse(intcode, v1, v2 int) { func (p *Program) opIfLessThan(intcode, v1, v2, dest int) { v1md, v2md, destmd := p.paramMode(intcode, 0), p.paramMode(intcode, 1), p.paramMode(intcode, 2) - if destmd != MODE_POS { - p.error = errors.New("Invalid Destination Mode") - p.state = RET_ERR - } if p.get(v1md, v1) < p.get(v2md, v2) { - p.code[dest] = 1 + p.set(destmd, dest, 1) } else { - p.code[dest] = 0 + p.set(destmd, dest, 0) } } func (p *Program) opIfEqual(intcode, v1, v2, dest int) { v1md, v2md, destmd := p.paramMode(intcode, 0), p.paramMode(intcode, 1), p.paramMode(intcode, 2) - if destmd != MODE_POS { - p.error = errors.New("Invalid Destination Mode") - p.state = RET_ERR - } if p.get(v1md, v1) == p.get(v2md, v2) { - p.code[dest] = 1 + p.set(destmd, dest, 1) } else { - p.code[dest] = 0 + p.set(destmd, dest, 0) } } +func (p *Program) opModRelBase(intcode, v1 int) { + v1md := p.paramMode(intcode, 0) + p.relBase = p.relBase + p.get(v1md, v1) +} + func (p Program) String() string { var ret string + ret = ret + fmt.Sprintf("(PTR: %d, RBS: %d)\n", p.ptr, p.relBase) for k := range p.code { if k == p.ptr { ret = fmt.Sprintf("%s [%d]", ret, p.code[k])