2019-12-07 21:57:10 +00:00
|
|
|
package aoc2019
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io/ioutil"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
|
|
|
|
2019-12-09 17:48:40 +00:00
|
|
|
func day07TestMaxOutputFromChain(code []int64, chainStart, chainEnd int, looped bool) int64 {
|
2019-12-07 21:57:10 +00:00
|
|
|
var (
|
|
|
|
chainLen = chainEnd - chainStart + 1
|
2019-12-09 17:48:40 +00:00
|
|
|
permuts [][]int64
|
|
|
|
permute func(a []int64, k int)
|
|
|
|
rootSeq = make([]int64, chainLen)
|
2019-12-07 21:57:10 +00:00
|
|
|
)
|
|
|
|
|
2019-12-09 17:48:40 +00:00
|
|
|
permute = func(a []int64, k int) {
|
2019-12-07 21:57:10 +00:00
|
|
|
if k == len(a) {
|
2019-12-09 17:48:40 +00:00
|
|
|
permuts = append(permuts, append([]int64{}, a...))
|
2019-12-07 21:57:10 +00:00
|
|
|
} else {
|
|
|
|
for i := k; i < len(rootSeq); i++ {
|
|
|
|
a[k], a[i] = a[i], a[k]
|
|
|
|
permute(a, k+1)
|
|
|
|
a[k], a[i] = a[i], a[k]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := range rootSeq {
|
2019-12-09 17:48:40 +00:00
|
|
|
rootSeq[i] = int64(chainStart + i)
|
2019-12-07 21:57:10 +00:00
|
|
|
}
|
|
|
|
permute(rootSeq, 0)
|
|
|
|
|
2019-12-09 17:48:40 +00:00
|
|
|
var maxOutput int64
|
2019-12-07 21:57:10 +00:00
|
|
|
for _, seq := range permuts {
|
|
|
|
var (
|
2019-12-09 17:48:40 +00:00
|
|
|
commInChans = make([]chan int64, chainLen)
|
|
|
|
commOut = make(chan int64, 2)
|
2019-12-07 21:57:10 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Create channels
|
|
|
|
for i := range commInChans {
|
2019-12-09 17:48:40 +00:00
|
|
|
commInChans[i] = make(chan int64, 2)
|
2019-12-07 21:57:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Build execution chain
|
|
|
|
for i := 0; i < chainLen-1; i++ {
|
|
|
|
go executeIntcode(cloneIntcode(code), commInChans[i], commInChans[i+1])
|
|
|
|
}
|
|
|
|
go executeIntcode(cloneIntcode(code), commInChans[chainLen-1], commOut)
|
|
|
|
|
|
|
|
// Initialize chain
|
|
|
|
for i, v := range seq {
|
|
|
|
commInChans[i] <- v
|
|
|
|
}
|
|
|
|
commInChans[0] <- 0 // Input signal
|
|
|
|
|
2019-12-09 17:48:40 +00:00
|
|
|
var lastOutput int64
|
2019-12-07 21:57:10 +00:00
|
|
|
for r := range commOut {
|
|
|
|
lastOutput = r
|
|
|
|
if looped {
|
|
|
|
commInChans[0] <- r
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test output of last execution
|
|
|
|
if lastOutput > maxOutput {
|
|
|
|
maxOutput = lastOutput
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return maxOutput
|
|
|
|
}
|
|
|
|
|
2019-12-09 17:48:40 +00:00
|
|
|
func solveDay7Part1(inFile string) (int64, error) {
|
2019-12-07 21:57:10 +00:00
|
|
|
raw, err := ioutil.ReadFile(inFile)
|
|
|
|
if err != nil {
|
|
|
|
return 0, errors.Wrap(err, "Unable to read input file")
|
|
|
|
}
|
|
|
|
|
|
|
|
code, err := parseIntcode(strings.TrimSpace(string(raw)))
|
|
|
|
if err != nil {
|
|
|
|
return 0, errors.Wrap(err, "Unable to parse intcode program")
|
|
|
|
}
|
|
|
|
|
|
|
|
return day07TestMaxOutputFromChain(code, 0, 4, false), nil
|
|
|
|
}
|
|
|
|
|
2019-12-09 17:48:40 +00:00
|
|
|
func solveDay7Part2(inFile string) (int64, error) {
|
2019-12-07 21:57:10 +00:00
|
|
|
raw, err := ioutil.ReadFile(inFile)
|
|
|
|
if err != nil {
|
|
|
|
return 0, errors.Wrap(err, "Unable to read input file")
|
|
|
|
}
|
|
|
|
|
|
|
|
code, err := parseIntcode(strings.TrimSpace(string(raw)))
|
|
|
|
if err != nil {
|
|
|
|
return 0, errors.Wrap(err, "Unable to parse intcode program")
|
|
|
|
}
|
|
|
|
|
|
|
|
return day07TestMaxOutputFromChain(code, 5, 9, true), nil
|
|
|
|
}
|