diff --git a/2019/day07/input b/2019/day07/input new file mode 100644 index 0000000..1cf7fe7 --- /dev/null +++ b/2019/day07/input @@ -0,0 +1 @@ +3,8,1001,8,10,8,105,1,0,0,21,38,63,72,85,110,191,272,353,434,99999,3,9,102,4,9,9,101,2,9,9,102,3,9,9,4,9,99,3,9,1001,9,4,9,102,2,9,9,1001,9,5,9,1002,9,5,9,101,3,9,9,4,9,99,3,9,1001,9,2,9,4,9,99,3,9,1001,9,3,9,102,2,9,9,4,9,99,3,9,101,2,9,9,102,2,9,9,1001,9,2,9,1002,9,4,9,101,2,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,99,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,99 diff --git a/2019/day07/main.go b/2019/day07/main.go new file mode 100644 index 0000000..14fe227 --- /dev/null +++ b/2019/day07/main.go @@ -0,0 +1,135 @@ +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() + + fmt.Print(allPerms[k], ": ") + wrk := pt1RunWithPhaseSettings(allPerms[k]) + fmt.Println(wrk) + if wrk > max { + max = wrk + bestPerm = allPerms[k] + } + } + fmt.Println("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) + 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() + + fmt.Print(allPerms[k], ": ") + wrk := pt2RunWithPhaseSettings(allPerms[k]) + fmt.Println(wrk) + if wrk > max { + max = wrk + bestPerm = allPerms[k] + } + } + fmt.Println("BEST: ", bestPerm, max) +} + +func pt2RunWithPhaseSettings(settings []int) int { + go func() { + a1.Input(settings[0]) + a2.Input(settings[1]) + a3.Input(settings[2]) + a4.Input(settings[3]) + a5.Input(settings[4]) + a1.Input(0) + for { + a2.Input(a1.Output()) + a3.Input(a2.Output()) + a4.Input(a3.Output()) + a5.Input(a4.Output()) + for !a5.NeedsOutput() { + time.Sleep(1) + } + if a5.State() == intcode.RET_DONE { + break + } + a1.Input(a5.Output()) + } + }() + for a5.State() != intcode.RET_DONE && !a5.NeedsOutput() { + time.Sleep(1) + } + return a5.Output() +} diff --git a/2019/day07/testinput1 b/2019/day07/testinput1 new file mode 100644 index 0000000..e626457 --- /dev/null +++ b/2019/day07/testinput1 @@ -0,0 +1 @@ +3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0 diff --git a/2019/day07/testinput2 b/2019/day07/testinput2 new file mode 100644 index 0000000..e797139 --- /dev/null +++ b/2019/day07/testinput2 @@ -0,0 +1 @@ +3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0 diff --git a/2019/day07/testinput3 b/2019/day07/testinput3 new file mode 100644 index 0000000..2beb112 --- /dev/null +++ b/2019/day07/testinput3 @@ -0,0 +1 @@ +3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0 diff --git a/2019/day07/testinput4 b/2019/day07/testinput4 new file mode 100644 index 0000000..ad78133 --- /dev/null +++ b/2019/day07/testinput4 @@ -0,0 +1 @@ +3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5 diff --git a/2019/day07/testinput5 b/2019/day07/testinput5 new file mode 100644 index 0000000..cd43fb9 --- /dev/null +++ b/2019/day07/testinput5 @@ -0,0 +1 @@ +3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,-5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10 diff --git a/2019/intcode-processor/processor.go b/2019/intcode-processor/processor.go index 486faae..5ca9224 100644 --- a/2019/intcode-processor/processor.go +++ b/2019/intcode-processor/processor.go @@ -30,8 +30,9 @@ const ( ) type Program struct { - code []int - ptr int + originalCode []int + code []int + ptr int state int error error @@ -44,11 +45,22 @@ type Program struct { func NewProgram(prog []int) *Program { p := new(Program) + p.originalCode = make([]int, len(prog)) p.code = make([]int, len(prog)) + copy(p.originalCode, prog) + p.Reset() + return p +} + +func (p *Program) Reset() { + copy(p.code, p.originalCode) + p.ptr = 0 + p.state = RET_OK + p.error = nil + p.waitingForInput = false + p.waitingForOutput = false p.input = make(chan int) p.output = make(chan int) - copy(p.code, prog) - return p } func (p *Program) GetCode() []int { diff --git a/helpers/helpers.go b/helpers/helpers.go index 178b1fe..426c933 100644 --- a/helpers/helpers.go +++ b/helpers/helpers.go @@ -141,3 +141,48 @@ func stringPermHelper(str string, i int) []string { } return ret } + +func IntPermutations(inp []int) [][]int { + perms := intPermHelper(inp, 0) + var wrk [][]int + // Now de-dupe + for i := range perms { + var found bool + for j := range wrk { + if IntSlicesAreEqual(perms[i], wrk[j]) { + found = true + break + } + } + if !found { + wrk = append(wrk, perms[i]) + } + } + return wrk +} + +func intPermHelper(inp []int, i int) [][]int { + ret := [][]int{inp} + if i != len(inp) { + r := make([]int, len(inp)) + copy(r, inp) + for j := i; j < len(r); j++ { + r[i], r[j] = r[j], r[i] + ret = append(ret, intPermHelper(r, i+1)...) + r[i], r[j] = r[j], r[i] + } + } + return ret +} + +func IntSlicesAreEqual(s1 []int, s2 []int) bool { + if len(s1) != len(s2) { + return false + } + for k := range s1 { + if s1[k] != s2[k] { + return false + } + } + return true +}