Files
2019/days/07.go
Parnic 1784ab77c8 Day 7 solution
I will probably end up regretting this since I assume the "wait to be given an input from some other process before continuing execution" paradigm is going to come up again, but this part 2 goroutine+channel solution felt good (taking advantage of Go features) and made me happy, so I rolled with it.
2022-06-10 10:37:38 -05:00

117 lines
2.6 KiB
Go

package days
import (
"fmt"
"sync"
"parnic.com/aoc2019/utilities"
)
type Day07 struct {
program utilities.IntcodeProgram
amps []utilities.IntcodeProgram
}
func (d *Day07) Parse() {
d.program = utilities.LoadIntcodeProgram("07p")
d.amps = make([]utilities.IntcodeProgram, 5)
for i := range d.amps {
d.amps[i] = d.program.Copy()
}
}
func (d Day07) Num() int {
return 7
}
func (d *Day07) Part1() string {
var highestVal int64
var highestSequence []int64
allSequences := utilities.GetPermutations([]int64{0, 1, 2, 3, 4})
for _, sequence := range allSequences {
if len(sequence) != len(d.amps) {
panic("input sequence does not match up to number of amplifiers")
}
input := int64(0)
var output int64
for i, amp := range d.amps {
amp.RunIn(func(step int) int64 {
if step == 1 {
return sequence[i]
} else if step == 2 {
return input
}
panic("hit more input instructions than expected")
}, func(val int64, state utilities.IntcodeProgramState) {
output = val
})
input = output
}
if output > highestVal {
highestVal = output
if highestSequence == nil {
highestSequence = make([]int64, len(sequence))
}
copy(highestSequence, sequence)
}
}
return fmt.Sprintf("Max thruster signal: %s%d%s (produced by %v)", utilities.TextBold, highestVal, utilities.TextReset, highestSequence)
}
func (d *Day07) Part2() string {
var highestVal int64
var highestSequence []int64
allSequences := utilities.GetPermutations([]int64{5, 6, 7, 8, 9})
for _, sequence := range allSequences {
if len(sequence) != len(d.amps) {
panic("input sequence does not match up to number of amplifiers")
}
inputs := make([]chan int64, len(d.amps))
for i := range d.amps {
d.amps[i].Reset()
inputs[i] = make(chan int64, 1)
inputs[i] <- sequence[i]
}
var finalOutput int64
var wg sync.WaitGroup
for i := range d.amps {
wg.Add(1)
go func(idx int) {
d.amps[idx].RunIn(func(step int) int64 {
input := <-inputs[idx]
return input
}, func(val int64, state utilities.IntcodeProgramState) {
finalOutput = val
inputIdx := idx + 1
if inputIdx == len(inputs) {
inputIdx = 0
}
inputs[inputIdx] <- val
})
wg.Done()
}(i)
}
inputs[0] <- 0
wg.Wait()
if finalOutput > highestVal {
highestVal = finalOutput
if highestSequence == nil {
highestSequence = make([]int64, len(sequence))
}
copy(highestSequence, sequence)
}
}
return fmt.Sprintf("Max thruster signal: %s%d%s (produced by %v)", utilities.TextBold, highestVal, utilities.TextReset, highestSequence)
}