package main import ( "fmt" "io/ioutil" "os" "strings" "time" intcode "git.bullercodeworks.com/brian/adventofcode/2019/intcode-processor" helpers "git.bullercodeworks.com/brian/adventofcode/helpers" ) var a1, a2, a3, a4, a5 *intcode.Program 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) part2(prog) } func part1(prog []int) { allPerms := helpers.IntPermutations([]int{0, 1, 2, 3, 4}) var bestPerm []int max := 0 for k := range allPerms { a1 = intcode.NewProgram(prog) go a1.Run() a2 = intcode.NewProgram(prog) go a2.Run() a3 = intcode.NewProgram(prog) go a3.Run() a4 = intcode.NewProgram(prog) go a4.Run() a5 = intcode.NewProgram(prog) go a5.Run() wrk := pt1RunWithPhaseSettings(allPerms[k]) if wrk > max { max = wrk bestPerm = allPerms[k] } } fmt.Println("Part 1 BEST: ", bestPerm, max) } func pt1RunWithPhaseSettings(settings []int) int { go func() { a1.Input(settings[0]) a1.Input(0) a2.Input(settings[1]) a2.Input(a1.Output()) a3.Input(settings[2]) a3.Input(a2.Output()) a4.Input(settings[3]) a4.Input(a3.Output()) a5.Input(settings[4]) a5.Input(a4.Output()) }() for !a5.NeedsOutput() { time.Sleep(1) } return a5.Output() } func part2(prog []int) { allPerms := helpers.IntPermutations([]int{5, 6, 7, 8, 9}) var bestPerm []int max := 0 for k := range allPerms { a1 = intcode.NewProgram(prog) a1.Reset() go a1.Run() a2 = intcode.NewProgram(prog) a2.Reset() go a2.Run() a3 = intcode.NewProgram(prog) a3.Reset() go a3.Run() a4 = intcode.NewProgram(prog) a4.Reset() go a4.Run() a5 = intcode.NewProgram(prog) a5.Reset() go a5.Run() wrk := pt2RunWithPhaseSettings(allPerms[k]) if wrk > max { max = wrk bestPerm = allPerms[k] } } fmt.Println("Part 2 BEST: ", bestPerm, max) } func pt2RunWithPhaseSettings(settings []int) int { a1.Input(settings[0]) a2.Input(settings[1]) a3.Input(settings[2]) a4.Input(settings[3]) a5.Input(settings[4]) a5Out := 0 for { a1.Input(a5Out) a2.Input(a1.Output()) a3.Input(a2.Output()) a4.Input(a3.Output()) a5.Input(a4.Output()) for !a5.NeedsOutput() { time.Sleep(1) } a5Out = a5.Output() // Wait until amp 5 is either done, or waiting for a5.State() != intcode.RET_DONE && !a5.NeedsInput() { time.Sleep(1) } if a5.State() == intcode.RET_DONE { break } } return a5Out }