Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
30bdd9b016
|
|||
15b34197ee
|
@ -48,6 +48,7 @@ type Day17 struct {
|
||||
|
||||
func (d *Day17) Parse() {
|
||||
d.program = u.LoadIntcodeProgram("17p")
|
||||
// d.program.SetDebugASCIIPrint(true)
|
||||
}
|
||||
|
||||
func (d Day17) Num() int {
|
||||
@ -388,9 +389,8 @@ func (d *Day17) Part2() string {
|
||||
row := 0
|
||||
var outputState int
|
||||
var lastOutput int64
|
||||
var instructionStr string
|
||||
d.program.RunIn(func(inputStep int) int64 {
|
||||
return int64(instructionStr[inputStep-1])
|
||||
panic("unexpected read")
|
||||
}, func(val int64, state u.IntcodeProgramState) {
|
||||
rVal := rune(val)
|
||||
if outputState == 0 {
|
||||
@ -401,7 +401,7 @@ func (d *Day17) Part2() string {
|
||||
|
||||
if rVal == '\n' && lastOutput == '\n' {
|
||||
if outputState == 0 {
|
||||
instructionStr = beforeGrid.solvePath(beforeBotLocation, beforeBotFacing)
|
||||
d.program.FeedInputString(beforeGrid.solvePath(beforeBotLocation, beforeBotFacing))
|
||||
}
|
||||
outputState++
|
||||
row = 0
|
||||
|
85
days/21.go
Normal file
85
days/21.go
Normal file
@ -0,0 +1,85 @@
|
||||
package days
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
u "parnic.com/aoc2019/utilities"
|
||||
)
|
||||
|
||||
type Day21 struct {
|
||||
program u.IntcodeProgram
|
||||
}
|
||||
|
||||
func (d *Day21) Parse() {
|
||||
d.program = u.LoadIntcodeProgram("21p")
|
||||
// d.program.SetDebugASCIIPrint(true)
|
||||
}
|
||||
|
||||
func (d Day21) Num() int {
|
||||
return 21
|
||||
}
|
||||
|
||||
func (d *Day21) Part1() string {
|
||||
// if there's any hole up to 3 ahead of us but there's ground where we'd land if we jumped
|
||||
// (a jump takes 4 spaces), go ahead and jump
|
||||
cmds := []string{
|
||||
// check if a hole at 1 or 2 ahead
|
||||
"NOT A T",
|
||||
"NOT B J",
|
||||
// store that result in J
|
||||
"OR T J",
|
||||
// check if a hole at 3 ahead
|
||||
"NOT C T",
|
||||
// store hole in 1, 2, or 3 in T
|
||||
"OR J T",
|
||||
// set J true if hole in 1, 2, or 3
|
||||
"OR T J",
|
||||
// set J true if also no hole at 4 ahead
|
||||
"AND D J",
|
||||
"WALK",
|
||||
}
|
||||
instructionStr := strings.Join(cmds, "\n") + "\n"
|
||||
d.program.FeedInputString(instructionStr)
|
||||
|
||||
res := d.program.Run()
|
||||
|
||||
return fmt.Sprintf("Hull damage value when walking: %s%d%s", u.TextBold, res, u.TextReset)
|
||||
}
|
||||
|
||||
func (d *Day21) Part2() string {
|
||||
// @
|
||||
// #####.#.##.##.###
|
||||
// ABCDEFGHI
|
||||
// using the first program, this kills us. if we jump, we land at D and H becomes our new D, so it won't jump again.
|
||||
// but if we waited to jump until we got one more ahead, we'd be ok.
|
||||
// so now we want to know essentially the same thing as part 1, but also if our multiple (immediate second jump) would be successful.
|
||||
// in problem terms, that's: if there's a hole at 1 or 2 ahead, and there's a hole at C with ground at H, and there's ground at D.
|
||||
// so now for the above example we'd wait to jump until here:
|
||||
// @
|
||||
// #####.#.##.##.###
|
||||
// ABCDEFGHI
|
||||
// and all will be well.
|
||||
cmds := []string{
|
||||
// check if a hole at 1 or 2 ahead
|
||||
"NOT A J",
|
||||
"NOT B T",
|
||||
// store that result in J
|
||||
"OR T J",
|
||||
// check if a hole at 3 ahead...
|
||||
"NOT C T",
|
||||
// and ground at 8 ahead (so we can immediately jump again if needed)...
|
||||
"AND H T",
|
||||
// combine those into J
|
||||
"OR T J",
|
||||
// and ensure we also still have a place to land if we jumped right away
|
||||
"AND D J",
|
||||
"RUN",
|
||||
}
|
||||
instructionStr := strings.Join(cmds, "\n") + "\n"
|
||||
d.program.FeedInputString(instructionStr)
|
||||
|
||||
res := d.program.Run()
|
||||
|
||||
return fmt.Sprintf("Hull damage value when running: %s%d%s", u.TextBold, res, u.TextReset)
|
||||
}
|
1
inputs/21p.txt
Normal file
1
inputs/21p.txt
Normal file
File diff suppressed because one or more lines are too long
1
main.go
1
main.go
@ -54,6 +54,7 @@ var dayMap = []day{
|
||||
&days.Day18{},
|
||||
&days.Day19{},
|
||||
&days.Day20{},
|
||||
&days.Day21{},
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
@ -28,6 +28,8 @@ type IntcodeProgram struct {
|
||||
program []int64
|
||||
relativeBase int
|
||||
haltRequested bool
|
||||
printASCII bool
|
||||
feedInput []rune
|
||||
}
|
||||
|
||||
type IntcodeProgramState struct {
|
||||
@ -140,14 +142,15 @@ func (p *IntcodeProgram) Reset() {
|
||||
p.relativeBase = 0
|
||||
}
|
||||
|
||||
func (p *IntcodeProgram) Run() {
|
||||
p.RunIn(func(int) int64 { return 0 }, func(int64, IntcodeProgramState) {})
|
||||
func (p *IntcodeProgram) Run() int64 {
|
||||
return p.RunIn(func(int) int64 { return 0 }, func(int64, IntcodeProgramState) {})
|
||||
}
|
||||
|
||||
func (p *IntcodeProgram) RunIn(inputFunc ProvideInputFunc, outputFunc ReceiveOutputFunc) {
|
||||
func (p *IntcodeProgram) RunIn(inputFunc ProvideInputFunc, outputFunc ReceiveOutputFunc) int64 {
|
||||
p.init()
|
||||
|
||||
inputsRequested := 0
|
||||
lastOutput := int64(0)
|
||||
for instructionPointer := 0; instructionPointer < len(p.program) && !p.haltRequested; {
|
||||
instruction := p.GetMemory(instructionPointer)
|
||||
instructionPointer++
|
||||
@ -184,13 +187,28 @@ func (p *IntcodeProgram) RunIn(inputFunc ProvideInputFunc, outputFunc ReceiveOut
|
||||
case opInput:
|
||||
inputsRequested++
|
||||
param1 := p.GetMemory(instructionPointer)
|
||||
p.setMemory(int(param1), inputFunc(inputsRequested), paramModes[0])
|
||||
var inputVal int64
|
||||
if len(p.feedInput) > 0 {
|
||||
inputVal = int64(p.feedInput[0])
|
||||
p.feedInput = p.feedInput[1:]
|
||||
} else {
|
||||
inputVal = inputFunc(inputsRequested)
|
||||
}
|
||||
if p.printASCII && inputVal <= 255 {
|
||||
fmt.Printf("%c", rune(inputVal))
|
||||
}
|
||||
p.setMemory(int(param1), inputVal, paramModes[0])
|
||||
|
||||
instructionPointer += 1
|
||||
|
||||
case opOutput:
|
||||
param1 := p.GetMemory(instructionPointer)
|
||||
outputFunc(p.getParamValue(int(param1), paramModes[0]), p.makeState(instructionPointer))
|
||||
param1Val := p.getParamValue(int(param1), paramModes[0])
|
||||
if p.printASCII && param1Val <= 255 {
|
||||
fmt.Printf("%c", rune(param1Val))
|
||||
}
|
||||
outputFunc(param1Val, p.makeState(instructionPointer))
|
||||
lastOutput = param1Val
|
||||
|
||||
instructionPointer += 1
|
||||
|
||||
@ -256,8 +274,19 @@ func (p *IntcodeProgram) RunIn(inputFunc ProvideInputFunc, outputFunc ReceiveOut
|
||||
}
|
||||
|
||||
p.haltRequested = false
|
||||
|
||||
return lastOutput
|
||||
}
|
||||
|
||||
func (p *IntcodeProgram) Stop() {
|
||||
p.haltRequested = true
|
||||
}
|
||||
|
||||
func (p *IntcodeProgram) SetDebugASCIIPrint(enable bool) {
|
||||
p.printASCII = enable
|
||||
}
|
||||
|
||||
func (p *IntcodeProgram) FeedInputString(str string) {
|
||||
p.feedInput = make([]rune, len(str))
|
||||
copy(p.feedInput, []rune(str))
|
||||
}
|
||||
|
Reference in New Issue
Block a user